pulse-js-framework
v1.11.4
Published
A declarative DOM framework with CSS selector-based structure and reactive pulsations
Maintainers
Readme
Pulse Framework
No build. No dependencies. Just JavaScript.
Features
- CSS Selector Syntax - Create DOM elements using familiar CSS selectors
- Reactive Pulsations - Automatic UI updates when state changes
- Custom DSL - Optional
.pulsefile format for cleaner code - No Build Required - Works directly in the browser
- Lightweight - Minimal footprint, maximum performance
- Router & Store - Built-in SPA routing and state management
- Form Handling - Validation, async validators, field arrays
- Async Primitives - useAsync, useResource, usePolling with SWR caching
- Server-Side Rendering - Full SSR with hydration and async data fetching
- Hot Module Replacement - Full HMR with state preservation
- Mobile Apps - Build native Android & iOS apps (zero dependencies)
- TypeScript Support - Full type definitions for IDE autocomplete
- DevTools - Time-travel debugging, dependency graph visualization
Installation
npm install pulse-js-frameworkQuick Start
Create a new project
npx pulse-js-framework create my-app
cd my-app
npm install
npm run devOr with TypeScript
npx pulse-js-framework create my-app --typescript
cd my-app
npm install
npm run devOr from a template
Create projects from built-in example apps:
# E-commerce app (products, cart, checkout)
npx pulse-js-framework create my-shop --ecommerce
# Todo app (filtering, local storage)
npx pulse-js-framework create my-todos --todo
# Blog (posts, sidebar, navigation)
npx pulse-js-framework create my-blog --blog
# Chat app (messages, users, emoji picker)
npx pulse-js-framework create my-chat --chat
# Dashboard (data visualization)
npx pulse-js-framework create my-dashboard --dashboardOr use directly
import { pulse, effect, el, mount } from 'pulse-js-framework';
// Create reactive state
const count = pulse(0);
// Build UI with CSS selector syntax
function Counter() {
const div = el('.counter');
const display = el('h1');
effect(() => {
display.textContent = `Count: ${count.get()}`;
});
const increment = el('button.btn', '+');
increment.onclick = () => count.update(n => n + 1);
div.append(display, increment);
return div;
}
mount('#app', Counter());CSS Selector Syntax
el('div') // <div></div>
el('.container') // <div class="container"></div>
el('#app') // <div id="app"></div>
el('button.btn.primary') // <button class="btn primary"></button>
el('input[type=text]') // <input type="text">
el('h1', 'Hello World') // <h1>Hello World</h1>Reactivity
import { pulse, effect, computed, batch } from 'pulse-js-framework';
const firstName = pulse('John');
const lastName = pulse('Doe');
// Computed values
const fullName = computed(() => `${firstName.get()} ${lastName.get()}`);
// Effects auto-run when dependencies change
effect(() => console.log(`Hello, ${fullName.get()}!`));
firstName.set('Jane'); // Logs: "Hello, Jane Doe!"
// Batch updates (effects run once)
batch(() => {
firstName.set('John');
lastName.set('Smith');
});.pulse File Format
@page Counter
state {
count: 0
}
view {
.counter {
h1 "Count: {count}"
button @click(count++) "+"
button @click(count--) "-"
}
}
style {
.counter { text-align: center; padding: 20px }
}See Pulse DSL documentation for full syntax reference.
CLI Commands
# Project Creation
pulse create <name> # Create new project
pulse create <name> --typescript # Create TypeScript project
pulse create <name> --ecommerce # Create from E-Commerce template
pulse create <name> --todo # Create from Todo App template
pulse create <name> --blog # Create from Blog template
pulse create <name> --chat # Create from Chat template
pulse create <name> --dashboard # Create from Dashboard template
pulse init --typescript # Initialize in current directory
# Development
pulse dev [port] # Start dev server (default: 3000)
pulse build # Build for production
pulse preview [port] # Preview production build
pulse compile <file> # Compile .pulse file
# Code Quality
pulse lint [files] # Validate .pulse files
pulse lint --fix # Auto-fix fixable issues
pulse format [files] # Format .pulse files
pulse analyze # Analyze bundle
# Testing
pulse test # Run tests with Node.js test runner
pulse test --coverage # Run tests with coverage
pulse test --watch # Watch mode
pulse test --create <name> # Generate test file
# Project Tools
pulse doctor # Run project diagnostics
pulse doctor --verbose # Detailed diagnostics
# Creating .pulse Files
pulse new <name> # Create component (src/components/<Name>.pulse)
pulse new <name> --type page # Create page (src/pages/<Name>.pulse)
pulse new <name> --type layout # Create layout (src/layouts/<Name>.pulse)
pulse new <name> --props # Include props section
# Scaffolding
pulse scaffold component <name> # Generate component
pulse scaffold page <name> # Generate page
pulse scaffold store <name> # Generate store module
pulse scaffold hook <name> # Generate custom hook
pulse scaffold service <name> # Generate API service
pulse scaffold context <name> # Generate context provider
pulse scaffold layout <name> # Generate layout component
# Documentation
pulse docs --generate # Generate API docs (Markdown)
pulse docs --generate -f html # Generate HTML docs
pulse docs --generate -f json # Generate JSON docsSee CLI documentation for full command reference.
Core Modules
Router
import { createRouter, lazy } from 'pulse-js-framework/runtime/router';
const router = createRouter({
routes: {
'/': HomePage,
'/users/:id': UserPage,
'/dashboard': lazy(() => import('./Dashboard.js'))
}
});Store
import { createStore, createActions } from 'pulse-js-framework/runtime/store';
const store = createStore({ user: null, theme: 'light' }, { persist: true });
const actions = createActions(store, {
login: (store, user) => store.user.set(user)
});Form
import { useForm, validators } from 'pulse-js-framework/runtime/form';
const { fields, handleSubmit, isValid } = useForm(
{ email: '', password: '' },
{
email: [validators.required(), validators.email()],
password: [validators.required(), validators.minLength(8)]
}
);Async
import { useAsync, useResource } from 'pulse-js-framework/runtime/async';
const { data, loading } = useAsync(() => fetch('/api/users').then(r => r.json()));
const users = useResource('users', fetchUsers, { refreshInterval: 30000 });Accessibility
import {
// Announcements
announce, createAnnouncementQueue,
// Focus management
trapFocus, onEscapeKey, createFocusVisibleTracker,
// User preferences
prefersReducedMotion, prefersReducedTransparency, forcedColorsMode,
// ARIA widgets
createModal, createTooltip, createAccordion, createMenu,
// Color contrast
getContrastRatio, meetsContrastRequirement,
// Validation
validateA11y
} from 'pulse-js-framework/runtime/a11y';
// Screen reader announcements
announce('Item saved successfully');
// Accessible modal dialog
const modal = createModal(dialog, { labelledBy: 'title', closeOnBackdropClick: true });
modal.open();
// Check color contrast (WCAG)
const ratio = getContrastRatio('#333', '#fff'); // 12.63
meetsContrastRequirement(ratio, 'AA'); // trueSee Accessibility documentation for full guide.
See API documentation for full reference.
Mobile Apps
Build native Android and iOS apps:
pulse mobile init
pulse build
pulse mobile build android
pulse mobile run androidimport { createNativeStorage, NativeUI } from 'pulse-js-framework/runtime/native';
const storage = createNativeStorage();
const theme = storage.get('theme', 'light');
NativeUI.toast('Hello from native!');See Mobile documentation for full guide.
IDE Extensions
VS Code
cd vscode-extension && bash install.shIntelliJ IDEA / WebStorm
cd intellij-plugin && ./gradlew buildPluginFeatures: Syntax highlighting, code snippets, bracket matching.
TypeScript Support
Full type definitions included:
import { pulse, Pulse } from 'pulse-js-framework/runtime';
import { createRouter, Router } from 'pulse-js-framework/runtime/router';
const count: Pulse<number> = pulse(0);Examples
| Example | Description | |---------|-------------| | Todo App | Task management with filters | | Blog | CRUD, categories, search | | Chat App | Real-time messaging | | E-commerce | Shopping cart | | Dashboard | Admin UI | | Weather App | API integration, async data fetching | | Sports News | HTTP client with interceptors | | HMR Demo | Hot module replacement | | Router Demo | SPA routing | | Store Demo | State with undo/redo | | Electron App | Desktop notes app | | Server Actions | Rate limiting, CSRF protection | | LESS Example | LESS preprocessor support | | Stylus Example | Stylus preprocessor support | | Webpack | Webpack 5 loader integration | | Rollup | Rollup plugin with tree-shaking | | ESBuild | ESBuild ultra-fast builds | | Parcel | Parcel zero-config bundling | | SASS Example | SASS/SCSS preprocessor support | | Form Validation | useForm, validators, file upload |
Server-Side Rendering
Pulse supports full SSR with hydration and async data fetching:
// server.js
import { renderToString, serializeState } from 'pulse-js-framework/runtime/ssr';
import App from './App.js';
app.get('*', async (req, res) => {
const { html, state } = await renderToString(() => App(), {
waitForAsync: true // Wait for useAsync to resolve
});
res.send(`
<!DOCTYPE html>
<html>
<body>
<div id="app">${html}</div>
<script>window.__PULSE_STATE__ = ${serializeState(state)};</script>
<script type="module" src="/client.js"></script>
</body>
</html>
`);
});
// client.js
import { hydrate } from 'pulse-js-framework/runtime/ssr';
import App from './App.js';
hydrate('#app', () => App(), {
state: window.__PULSE_STATE__
});Documentation
- API Reference - Complete API documentation
- CLI Commands - Command line interface
- Pulse DSL - .pulse file syntax
- Accessibility - A11y guide and ARIA helpers
- HTTP Client - Fetch wrapper with interceptors
- WebSocket - Real-time with auto-reconnect
- GraphQL - Queries, mutations, subscriptions
- Context API - Dependency injection
- DevTools - Debugging and profiling
- Mobile Apps - Native Android & iOS
- SSR - Server-side rendering and hydration
License
MIT
