
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
brkrelease-vanilla
Advanced tools
Vanilla JavaScript widget for BrkRelease notifications and changelog
Widget de JavaScript puro para mostrar actualizaciones y changelog de BrkRelease en cualquier sitio web.
npm install brkrelease-vanilla
<!-- Versión minificada -->
<script src="https://unpkg.com/brkrelease-vanilla@latest/dist/brkrelease-widget.min.js"></script>
<!-- Versión ES Module -->
<script type="module">
import { createBrkReleaseWidget } from 'https://unpkg.com/brkrelease-vanilla@latest/dist/brkrelease-widget.esm.js';
</script>
<!DOCTYPE html>
<html>
<head>
<title>Mi Sitio Web</title>
</head>
<body>
<!-- Tu contenido -->
<!-- BrkRelease Widget -->
<script src="https://unpkg.com/brkrelease-vanilla@latest/dist/brkrelease-widget.min.js"></script>
<script>
// Crear el widget
const widget = new BrkReleaseWidget({
projectId: 'tu-proyecto-id',
apiUrl: 'https://api.brakodev.com'
});
</script>
</body>
</html>
import { createBrkReleaseWidget } from 'brkrelease-vanilla';
const widget = createBrkReleaseWidget({
projectId: 'tu-proyecto-id',
apiUrl: 'https://api.brakodev.com'
});
const { createBrkReleaseWidget } = require('brkrelease-vanilla');
const widget = createBrkReleaseWidget({
projectId: 'tu-proyecto-id',
apiUrl: 'https://api.brakodev.com'
});
interface BrkReleaseWidgetConfig {
// Requeridas
projectId: string; // ID del proyecto de BrkRelease
apiUrl: string; // URL base de la API de BrkRelease
// Opcionales
theme?: 'light' | 'dark'; // Tema del widget (por defecto: 'light')
position?: 'top-left' | 'top-right' | // Posición del widget
'bottom-left' | 'bottom-right' | // Modo modal (por defecto: 'bottom-right')
'sidebar-left' | 'sidebar-right'; // Modo sidebar (NUEVO)
primaryColor?: string; // Color primario del widget (CSS color)
maxReleases?: number; // Máximo número de releases (por defecto: 10)
publishedOnly?: boolean; // Solo releases publicados (por defecto: true)
buttonText?: string; // Texto personalizado para el botón
// Callbacks
onOpen?: () => void; // Callback cuando se abre el widget
onClose?: () => void; // Callback cuando se cierra el widget
onReleaseClick?: (release: Release) => void; // Callback cuando se hace clic en un release
}
El widget ahora soporta un modo sidebar que ocupa todo el lateral de la pantalla, proporcionando una experiencia más inmersiva y siempre visible.
El modo sidebar transforma el widget de un botón flotante + modal a una barra lateral fija que:
| Característica | Modo Modal (tradicional) | Modo Sidebar (nuevo) |
|---|---|---|
| Activación | Botón flotante → Modal | Siempre visible |
| Espacio | Overlay temporal | Barra lateral fija |
| Ancho | Responsive (max 400px) | Fijo (320px) |
| Altura | Contenido dinámico | Toda la pantalla |
| Uso recomendado | Sitios con poco espacio | Dashboards, apps, sitios amplios |
| UX | Menos intrusivo | Más prominente |
<script>
const widget = new BrkReleaseWidget({
projectId: 'tu-proyecto-id',
apiUrl: 'https://api.brakodev.com',
position: 'sidebar-left', // 👈 Sidebar en el lado izquierdo
theme: 'light',
primaryColor: '#3B82F6'
});
</script>
<script>
const widget = new BrkReleaseWidget({
projectId: 'tu-proyecto-id',
apiUrl: 'https://api.brakodev.com',
position: 'sidebar-right', // 👈 Sidebar en el lado derecho
theme: 'dark',
primaryColor: '#10B981'
});
</script>
<!DOCTYPE html>
<html>
<head>
<title>Mi Dashboard con BrkRelease Sidebar</title>
<style>
/* Ajustar el contenido principal para el sidebar */
.main-content {
margin-left: 320px; /* Para sidebar-left */
/* margin-right: 320px; Para sidebar-right */
padding: 20px;
}
/* Responsive: ocultar sidebar en móviles */
@media (max-width: 768px) {
.main-content {
margin-left: 0;
margin-right: 0;
}
}
</style>
</head>
<body>
<!-- Contenido principal -->
<div class="main-content">
<h1>Mi Dashboard</h1>
<p>El sidebar de BrkRelease aparecerá a la izquierda.</p>
</div>
<!-- BrkRelease Sidebar Widget -->
<script src="https://unpkg.com/brkrelease-vanilla@latest/dist/brkrelease-widget.min.js"></script>
<script>
new BrkReleaseWidget({
projectId: 'tu-proyecto-id',
apiUrl: 'https://api.brakodev.com',
position: 'sidebar-left',
theme: 'light',
primaryColor: '#6366F1',
maxReleases: 15,
onReleaseClick: (release) => {
console.log('Release clickeado en sidebar:', release.title);
}
});
</script>
</body>
</html>
/* Ajustar tu layout para el sidebar */
.container {
max-width: calc(100vw - 320px); /* Restar ancho del sidebar */
margin-left: 320px; /* Para sidebar-left */
}
/* Responsive: volver a modal en pantallas pequeñas */
@media (max-width: 1024px) {
.container {
max-width: 100vw;
margin-left: 0;
}
/* El widget automáticamente cambia a modal en móviles */
}
El sidebar se comporta inteligentemente según el tamaño de pantalla:
// Sidebar con configuración avanzada
const widget = new BrkReleaseWidget({
projectId: 'tu-proyecto-id',
apiUrl: 'https://api.brakodev.com',
position: 'sidebar-right',
theme: 'dark',
primaryColor: '#8B5CF6',
backgroundColor: '#1F2937', // Fondo personalizado
textColor: '#F9FAFB', // Texto personalizado
maxReleases: 20,
publishedOnly: true,
removePoweredBy: true, // Quitar "Powered by BrkRelease"
// Callbacks específicos para sidebar
onOpen: () => {
console.log('Sidebar inicializado');
// Analytics para sidebar
gtag('event', 'sidebar_loaded');
},
onReleaseClick: (release) => {
// Tracking específico para clicks en sidebar
analytics.track('sidebar_release_click', {
releaseId: release.id,
position: 'sidebar-right'
});
}
});
<script>
const widget = new BrkReleaseWidget({
projectId: 'tu-proyecto-id',
apiUrl: 'https://api.brakodev.com',
theme: 'dark'
});
</script>
<script>
const widget = new BrkReleaseWidget({
projectId: 'tu-proyecto-id',
apiUrl: 'https://api.brakodev.com',
primaryColor: '#10B981'
});
</script>
<script>
const widget = new BrkReleaseWidget({
projectId: 'tu-proyecto-id',
apiUrl: 'https://api.brakodev.com',
position: 'top-left'
});
</script>
<script>
const widget = new BrkReleaseWidget({
projectId: 'tu-proyecto-id',
apiUrl: 'https://api.brakodev.com',
onOpen: function() {
console.log('Widget abierto');
// Tracking, analytics, etc.
},
onClose: function() {
console.log('Widget cerrado');
},
onReleaseClick: function(release) {
console.log('Release clickeado:', release.title);
// Abrir modal personalizado, redireccionar, etc.
}
});
</script>
<script>
const widget = new BrkReleaseWidget({
projectId: 'tu-proyecto-id',
apiUrl: 'https://api.brakodev.com',
theme: 'dark',
position: 'bottom-left',
primaryColor: '#8B5CF6',
maxReleases: 5,
publishedOnly: true,
buttonText: 'Ver novedades',
onOpen: () => console.log('Widget abierto'),
onClose: () => console.log('Widget cerrado'),
onReleaseClick: (release) => {
console.log('Release:', release.title);
}
});
</script>
// En functions.php o en un plugin
function add_brkrelease_widget() {
?>
<script src="https://unpkg.com/brkrelease-vanilla@latest/dist/brkrelease-widget.min.js"></script>
<script>
new BrkReleaseWidget({
projectId: '<?php echo get_option('brkrelease_project_id'); ?>',
apiUrl: 'https://api.brakodev.com',
theme: '<?php echo get_theme_mod('brkrelease_theme', 'light'); ?>'
});
</script>
<?php
}
add_action('wp_footer', 'add_brkrelease_widget');
<!-- En theme.liquid antes de </body> -->
<script src="https://unpkg.com/brkrelease-vanilla@latest/dist/brkrelease-widget.min.js"></script>
<script>
new BrkReleaseWidget({
projectId: '{{ settings.brkrelease_project_id }}',
apiUrl: 'https://api.brakodev.com',
theme: '{{ settings.brkrelease_theme | default: "light" }}',
position: 'bottom-right'
});
</script>
// En un módulo personalizado
function mymodule_page_attachments(array &$attachments) {
$attachments['#attached']['library'][] = 'mymodule/brkrelease';
}
// En mymodule.libraries.yml
brkrelease:
js:
https://unpkg.com/brkrelease-vanilla@latest/dist/brkrelease-widget.min.js: { type: external, minified: true }
js/brkrelease-init.js: {}
<!-- En Code Injection > Site Footer -->
<script src="https://unpkg.com/brkrelease-vanilla@latest/dist/brkrelease-widget.min.js"></script>
<script>
new BrkReleaseWidget({
projectId: 'tu-proyecto-id',
apiUrl: 'https://api.brakodev.com'
});
</script>
const widget = new BrkReleaseWidget({
projectId: 'tu-proyecto-id',
apiUrl: 'https://api.brakodev.com'
});
// Refrescar datos manualmente
widget.refresh();
// Destruir el widget
widget.destroy();
import { BrkReleaseAPI } from 'brkrelease-vanilla';
// Crear instancia de API
const api = new BrkReleaseAPI('https://api.brakodev.com');
// Obtener releases
const releases = await api.getReleases('proyecto-id');
console.log(releases);
// Obtener información del proyecto
const project = await api.getProject('proyecto-id');
console.log(project);
// Verificar nuevos releases
const { hasNew, count } = await api.hasNewReleases('proyecto-id', '2024-01-01');
console.log(`Hay ${count} nuevos releases:`, hasNew);
import { BrkReleaseAPI } from 'brkrelease-vanilla';
class MiWidgetPersonalizado {
constructor(projectId, apiUrl) {
this.api = new BrkReleaseAPI(apiUrl);
this.projectId = projectId;
this.init();
}
async init() {
const releases = await this.api.getReleases(this.projectId);
this.renderCustomWidget(releases);
}
renderCustomWidget(releases) {
const container = document.getElementById('mi-widget');
container.innerHTML = releases.releases.map(release => `
<div class="mi-release">
<h3>${release.title}</h3>
<p>${release.content}</p>
</div>
`).join('');
}
}
// Usar el widget personalizado
new MiWidgetPersonalizado('tu-proyecto-id', 'https://api.brakodev.com');
El widget incluye estilos autocontenidos, pero puedes sobrescribirlos:
/* Personalizar el botón */
.brkrelease-btn {
background: linear-gradient(45deg, #667eea 0%, #764ba2 100%) !important;
}
/* Personalizar el modal */
.brkrelease-modal-content {
border-radius: 20px !important;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25) !important;
}
/* Personalizar releases */
.brkrelease-release {
border-left: 4px solid #667eea !important;
}
El widget es completamente responsive y funciona en:
El widget maneja automáticamente:
const widget = new BrkReleaseWidget({
projectId: 'proyecto-inexistente',
apiUrl: 'https://api-no-disponible.com',
onError: (error) => {
console.error('Error en BrkRelease:', error);
// Tu lógica de manejo de errores
}
});
Estados de error comunes:
<!DOCTYPE html>
<html>
<head>
<title>Test BrkRelease Widget</title>
</head>
<body>
<h1>Página de prueba</h1>
<script src="https://unpkg.com/brkrelease-vanilla@latest/dist/brkrelease-widget.min.js"></script>
<script>
// Widget de prueba
new BrkReleaseWidget({
projectId: 'test-project',
apiUrl: 'https://api.brakodev.com',
theme: 'light',
onOpen: () => console.log('✅ Widget abierto'),
onClose: () => console.log('❌ Widget cerrado'),
onReleaseClick: (release) => console.log('📰 Release:', release)
});
</script>
</body>
</html>
// Con Jest
describe('BrkReleaseWidget', () => {
test('debería crear el widget correctamente', () => {
const widget = new BrkReleaseWidget({
projectId: 'test',
apiUrl: 'https://api.brakodev.com'
});
expect(document.getElementById('brkrelease-widget')).toBeTruthy();
});
});
eval() ni scripts inline// Para aplicaciones SaaS que quieren notificar nuevas features
new BrkReleaseWidget({
projectId: 'mi-saas-app',
apiUrl: 'https://api.misaas.com/releases',
position: 'top-right',
onReleaseClick: (release) => {
// Tracking para product analytics
analytics.track('release_viewed', {
releaseId: release.id,
releaseType: release.type
});
}
});
// Para tiendas online que quieren mostrar nuevos productos
new BrkReleaseWidget({
projectId: 'mi-tienda',
apiUrl: 'https://api.mitienda.com/releases',
theme: 'dark',
buttonText: 'Nuevos productos',
onOpen: () => {
gtag('event', 'new_products_viewed');
}
});
// Para blogs que quieren notificar nuevos artículos
new BrkReleaseWidget({
projectId: 'mi-blog',
apiUrl: 'https://api.miblog.com/releases',
position: 'bottom-left',
primaryColor: '#FF6B6B'
});
MIT License - Ver archivo LICENSE para más detalles.
¡Las contribuciones son bienvenidas! Ver CONTRIBUTING.md para más información.
Usa GitHub Issues para reportar bugs o solicitar nuevas funcionalidades.
FAQs
Vanilla JavaScript widget for BrkRelease notifications and changelog
We found that brkrelease-vanilla demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.