# HellaJS Framework - Documentation for AI Assistants HellaJS is a reactive JavaScript framework for building fast, lightweight user interfaces with fine-grained reactivity and no virtual DOM. It uses JSX templating with direct DOM binding and provides a comprehensive set of packages for modern web development. ## Framework Overview HellaJS eliminates virtual DOM diffing by creating direct reactive bindings between data and DOM elements. When signals change, only the specific DOM properties that depend on those signals are updated, providing surgical precision and optimal performance. ### Core Characteristics - **Zero Dependencies**: No external runtime dependencies - **TypeScript Ready**: Full TypeScript support with comprehensive type definitions - **<3.5KB Gzipped**: Extremely lightweight core bundle - **Fine-grained Reactivity**: Updates only what actually changed - **Direct DOM Binding**: No virtual DOM overhead - **JSX Templating**: Familiar React-like component syntax - **Reactive Signals**: Graph-based dependency tracking with automatic cleanup - **Memory Efficient**: Automatic memory management and leak prevention ### Architecture Philosophy HellaJS follows a "signals-first" approach where reactive primitives form the foundation of all framework features. This creates a unified, predictable mental model where: - **Signals** hold reactive state - **Computed** values derive from signals automatically - **Effects** handle side effects reactively - **Templates** bind signals directly to DOM elements - **Components** are functions that return templates ## Package Ecosystem ### @hellajs/core - Reactive Primitives The foundation of reactivity with signals, computed values, and effects. #### signal(initialValue?) Creates reactive state containers that automatically notify dependents when changed. **TypeScript Signatures:** ```typescript function signal(): Signal; function signal(initialValue: T): Signal; interface Signal { (): T; // getter (value: T): void; // setter } ``` **Basic Usage:** ```js import { signal } from '@hellajs/core'; const count = signal(0); const user = signal({ name: 'John', age: 30 }); const items = signal([]); // Reading values (getter) console.log(count()); // 0 console.log(user().name); // 'John' // Setting values (setter) - triggers dependency updates count(5); user({ name: 'Jane', age: 25 }); items(['apple', 'banana']); ``` **JSX Integration:** ```jsx // Use signal reference (NOT called) for reactive binding

{count}

// ✅ Reactive

{count()}

// ✅ Also reactive but static value

{user().name}

// ✅ Reactive

{`Count: ${count()}`}

// ✅ Reactive template literal ``` **Key Behaviors:** - Uses strict equality (!==) for change detection - Must create new objects/arrays rather than mutating existing ones - Synchronous updates by default - In JSX: Use `{signal}` for reactive binding, `{signal()}` for current value - Template literals require calling signals: `{`Count: ${count()}`}` ✅ reactive **Advanced Patterns:** ```js // Conditional initialization const user = signal(localStorage.getItem('user') ? JSON.parse(localStorage.getItem('user')) : null); // Array operations (immutable) const todos = signal([]); const addTodo = (todo) => todos([...todos(), todo]); const removeTodo = (id) => todos(todos().filter(t => t.id !== id)); const updateTodo = (id, updates) => todos(todos().map(t => t.id === id ? {...t, ...updates} : t)); // Object operations (immutable) const user = signal({ name: 'John', settings: { theme: 'light' } }); const updateUser = (updates) => user({ ...user(), ...updates }); const updateSettings = (settings) => user({ ...user(), settings: { ...user().settings, ...settings } }); ``` **Error Handling:** ```js // Safe signal access const safeGet = (signal, fallback) => { try { const value = signal(); return value !== undefined && value !== null ? value : fallback; } catch { return fallback; } }; // Validation wrapper const createValidatedSignal = (initialValue, validator) => { const sig = signal(initialValue); return (value) => { if (arguments.length === 0) return sig(); if (validator(value)) { sig(value); } else { console.warn('Invalid value:', value); } }; }; ``` #### computed(getter) Creates lazy, cached derived values that recalculate only when dependencies change. **TypeScript Signatures:** ```typescript function computed(getter: (previousValue?: T) => T): ReadonlySignal; interface ReadonlySignal { (): T; // getter only } ``` **Basic Usage:** ```js import { signal, computed } from '@hellajs/core'; const firstName = signal('John'); const lastName = signal('Doe'); const fullName = computed(() => `${firstName()} ${lastName()}`); console.log(fullName()); // "John Doe" firstName('Jane'); console.log(fullName()); // "Jane Doe" ``` **Features:** - Lazy evaluation - only computes when accessed AND dependencies changed - Automatic caching until dependencies change - Can chain computations efficiently - Conditional dependencies based on execution path - Receives previous value as first argument for optimizations **Advanced Examples:** ```js // Complex derived state const todos = signal([]); const filter = signal('all'); // 'all' | 'active' | 'completed' const filteredTodos = computed(() => { const allTodos = todos(); switch (filter()) { case 'active': return allTodos.filter(t => !t.completed); case 'completed': return allTodos.filter(t => t.completed); default: return allTodos; } }); const statistics = computed(() => { const allTodos = todos(); return { total: allTodos.length, active: allTodos.filter(t => !t.completed).length, completed: allTodos.filter(t => t.completed).length, percentage: allTodos.length > 0 ? Math.round((allTodos.filter(t => t.completed).length / allTodos.length) * 100) : 0 }; }); // Chained computations const users = signal([]); const searchTerm = signal(''); const sortOrder = signal('name'); // 'name' | 'age' | 'email' const filteredUsers = computed(() => users().filter(user => user.name.toLowerCase().includes(searchTerm().toLowerCase()) ) ); const sortedUsers = computed(() => { const filtered = filteredUsers(); return [...filtered].sort((a, b) => { const field = sortOrder(); return a[field] < b[field] ? -1 : a[field] > b[field] ? 1 : 0; }); }); // Performance optimization with previous value const expensiveComputation = computed((previousResult) => { const data = expensiveData(); // Skip computation if input hasn't meaningfully changed if (previousResult && data.version === previousResult.inputVersion) { return previousResult; } // Perform expensive calculation const result = performExpensiveCalculation(data); return { ...result, inputVersion: data.version }; }); ``` **Conditional Dependencies:** ```js const showAdvanced = signal(false); const basicSetting = signal('basic'); const advancedSetting = signal('advanced'); const currentSetting = computed(() => { if (showAdvanced()) { return `Advanced: ${advancedSetting()}`; // Only tracks advancedSetting when showAdvanced is true } return `Basic: ${basicSetting()}`; // Only tracks basicSetting when showAdvanced is false }); // Dependencies change dynamically based on execution path showAdvanced(true); // Now tracks showAdvanced + advancedSetting showAdvanced(false); // Now tracks showAdvanced + basicSetting ``` #### effect(fn) Executes side effects immediately when dependencies change. **TypeScript Signatures:** ```typescript function effect(fn: () => void | (() => void)): () => void; ``` **Basic Usage:** ```js import { signal, effect } from '@hellajs/core'; const count = signal(0); // Effect runs immediately and when count changes const cleanup = effect(() => { console.log(`Count is: ${count()}`); document.title = `Count: ${count()}`; }); // Always call cleanup to prevent memory leaks // cleanup(); ``` **Characteristics:** - Eager execution (runs immediately when dependencies change) - Dynamic dependency tracking - Must not be async functions directly - Always returns cleanup function - Side effects only - no return value used **Advanced Patterns:** ```js // Async operations in effects const userId = signal(1); const userData = signal(null); const loading = signal(false); const error = signal(null); effect(() => { const id = userId(); loading(true); error(null); fetch(`/api/users/${id}`) .then(response => { if (!response.ok) throw new Error(`HTTP ${response.status}`); return response.json(); }) .then(data => { userData(data); loading(false); }) .catch(err => { error(err.message); loading(false); userData(null); }); }); // Cleanup resources in effects effect(() => { const interval = setInterval(() => { console.log('Tick:', count()); }, 1000); // Return cleanup function return () => clearInterval(interval); }); // Effect with multiple dependencies const firstName = signal('John'); const lastName = signal('Doe'); const age = signal(30); effect(() => { // Tracks all three signals const fullName = `${firstName()} ${lastName()}`; const info = `${fullName}, age ${age()}`; localStorage.setItem('userInfo', info); console.log('User info updated:', info); }); // Conditional effects const debugMode = signal(false); const data = signal({}); effect(() => { if (debugMode()) { console.log('Debug data:', data()); // Only tracks data() when debugMode is true } }); ``` **Error Handling in Effects:** ```js // Safe effect execution const safeEffect = (fn) => { return effect(() => { try { fn(); } catch (error) { console.error('Effect error:', error); } }); }; // Effect with retry logic const createRetryableEffect = (fn, maxRetries = 3) => { return effect(() => { let retries = 0; const attempt = () => { try { fn(); } catch (error) { if (retries < maxRetries) { retries++; console.warn(`Effect failed, retrying (${retries}/${maxRetries}):`, error); setTimeout(attempt, Math.pow(2, retries) * 1000); } else { console.error('Effect failed after max retries:', error); } } }; attempt(); }); }; ``` #### batch(fn) Groups multiple signal updates into single execution cycle. **TypeScript Signatures:** ```typescript function batch(fn: () => T): T; ``` **Usage:** ```js import { signal, effect, batch } from '@hellajs/core'; const count = signal(0); const multiplier = signal(1); const result = computed(() => count() * multiplier()); effect(() => { console.log(`Result: ${result()}`); }); // Without batching - effect runs twice count(10); // Logs: "Result: 10" multiplier(3); // Logs: "Result: 30" // With batching - effect runs once batch(() => { count(5); // No effect execution yet multiplier(2); // No effect execution yet }); // Logs: "Result: 10" ``` **Advanced Batching Patterns:** ```js // Batch complex state updates const updateUser = (userId, userData) => { batch(() => { user.id(userId); user.name(userData.name); user.email(userData.email); user.settings(userData.settings); lastUpdated(Date.now()); }); // All effects and computations run once after batch }; // Batch with error handling const safeBatch = (fn) => { try { return batch(fn); } catch (error) { console.error('Batch update failed:', error); throw error; } }; // Async batching pattern const batchedAsyncUpdate = async () => { const userData = await fetchUserData(); const preferences = await fetchUserPreferences(); batch(() => { user(userData); userPreferences(preferences); loading(false); }); }; ``` #### untracked(fn) Reads signals without creating dependency relationships. **TypeScript Signatures:** ```typescript function untracked(fn: () => T): T; ``` **Usage:** ```js import { signal, computed, untracked } from '@hellajs/core'; const count = signal(0); const debugMode = signal(true); const doubled = computed(() => { const value = count(); // Read debugMode without making it a dependency if (untracked(() => debugMode())) { console.log('Debug: count is', value); } return value * 2; }); debugMode(false); // doubled doesn't recalculate count(5); // doubled recalculates but doesn't log (debug is off) ``` **Advanced Patterns:** ```js // Untracked reads for performance const users = signal([]); const lastFetch = signal(0); const cacheTimeout = 5 * 60 * 1000; // 5 minutes const usersWithCache = computed(() => { const currentUsers = users(); // Check cache age without creating dependency const lastFetchTime = untracked(() => lastFetch()); const now = Date.now(); if (now - lastFetchTime > cacheTimeout) { // Trigger refresh but don't make it a dependency untracked(() => { fetch('/api/users') .then(r => r.json()) .then(data => { users(data); lastFetch(now); }); }); } return currentUsers; }); // Debugging without affecting dependencies const createDebuggedComputed = (fn, debugName) => { return computed(() => { const startTime = untracked(() => performance.now()); const result = fn(); const endTime = untracked(() => performance.now()); untracked(() => { if (endTime - startTime > 10) { console.warn(`Slow computation "${debugName}": ${endTime - startTime}ms`); } }); return result; }); }; ``` ### @hellajs/dom - DOM Utilities #### mount(component, selector?) Renders components to DOM with reactive updates and lifecycle management. **TypeScript Signatures:** ```typescript function mount(component: Component, selector?: string): void; type Component = () => VNodeValue; ``` **Basic Usage:** ```js import { mount } from '@hellajs/dom'; const App = () => { const count = signal(0); return (

Count: {count}

); }; mount(App, '#app'); // Defaults to '#app' if selector not provided ``` **Features:** - Establishes reactive root context - Replaces root element entirely - Supports fragments and lifecycle hooks - Single mount point per element recommended - Automatic cleanup on component unmount **Advanced Mounting Patterns:** ```js // Conditional mounting const mountConditionally = (condition, component, selector) => { if (condition) { mount(component, selector); } }; // Multiple root mounting const mountMultiple = (components) => { Object.entries(components).forEach(([selector, component]) => { mount(component, selector); }); }; // Error boundary mounting const mountWithErrorBoundary = (component, selector) => { const ErrorBoundary = () => { const hasError = signal(false); const error = signal(null); try { if (hasError()) { return
Error: {error().message}
; } return component(); } catch (err) { hasError(true); error(err); return
Something went wrong
; } }; mount(ErrorBoundary, selector); }; // Development mode mounting with HMR if (process.env.NODE_ENV === 'development') { if (import.meta.hot) { import.meta.hot.accept(() => { mount(App, '#app'); }); } } ``` #### forEach(signal, itemFn) Optimized reactive list rendering using advanced diffing algorithms. **TypeScript Signatures:** ```typescript function forEach( each: T[] | Signal | (() => T[]), use: (item: T, index: number) => VNodeValue ): (parent: HellaElement) => void; ``` **Basic Usage:** ```jsx import { signal } from '@hellajs/core'; import { forEach } from '@hellajs/dom'; const todos = signal([ { id: 1, text: 'Learn HellaJS', done: false }, { id: 2, text: 'Build app', done: false } ]);
    {forEach(todos, (todo, index) => (
  • {todo.text}
  • ))}
``` **Uses Longest Increasing Subsequence algorithm for minimal DOM operations:** - Key-based tracking for efficient reordering - Minimal DOM operations (only moves/adds/removes what's necessary) - Memory-efficient node caching - Performance scales well with large lists **Advanced Patterns:** ```jsx // Complex list with nested components const TodoItem = ({ todo, onToggle, onDelete }) => (
  • onToggle(todo.id)} /> {todo.text}
  • );
      {forEach(filteredTodos, (todo) => ( ))}
    // Dynamic lists with conditional rendering
    {forEach(users, (user) => (
    {user.name}

    {user.name}

    {user.isOnline() && Online} {user.isAdmin && Admin}
    ))}
    // Grouped lists const groupedTodos = computed(() => { return todos().reduce((groups, todo) => { const category = todo.category || 'uncategorized'; if (!groups[category]) groups[category] = []; groups[category].push(todo); return groups; }, {}); });
    {forEach(Object.entries(groupedTodos), ([category, todos]) => (

    {category}

      {forEach(todos, (todo) => (
    • {todo.text}
    • ))}
    ))}
    // Virtual scrolling pattern for large lists const VirtualList = ({ items, itemHeight, containerHeight }) => { const scrollTop = signal(0); const visibleRange = computed(() => { const start = Math.floor(scrollTop() / itemHeight); const end = Math.min(start + Math.ceil(containerHeight / itemHeight), items().length); return { start, end }; }); const visibleItems = computed(() => { const { start, end } = visibleRange(); return items().slice(start, end).map((item, index) => ({ ...item, virtualIndex: start + index })); }); return (
    scrollTop(e.target.scrollTop)} >
    {forEach(visibleItems, (item) => (
    {item.text}
    ))}
    ); }; ``` **Performance Considerations:** ```jsx // ✅ Use stable keys {forEach(items, item =>
  • {item.name}
  • )} // ❌ Avoid index keys (causes unnecessary re-renders) {forEach(items, (item, index) =>
  • {item.name}
  • )} // ✅ Memoize expensive computations const ExpensiveItem = ({ item }) => { const expensiveValue = computed(() => expensiveCalculation(item)); return
    {expensiveValue()}
    ; }; // ✅ Use computed for filtering/sorting large lists const sortedItems = computed(() => items().sort(compareFn)); {forEach(sortedItems, item => )} ``` ### @hellajs/store - Reactive State Management Creates deeply reactive objects where each property becomes an independent signal. **TypeScript Signatures:** ```typescript function store(initial: T, options?: StoreOptions): Store; interface Store { [K in keyof T]: T[K] extends object ? Store : Signal; computed: ReadonlySignal; set(value: T): void; update(partial: PartialDeep): void; cleanup(): void; } interface StoreOptions { readonly?: boolean | readonly (keyof T)[]; } ``` **Basic Usage:** ```js import { store } from '@hellajs/store'; const user = store({ name: 'John', email: 'john@example.com', preferences: { theme: 'dark', language: 'en' } }); // Each property is reactive console.log(user.name()); // 'John' user.name('Jane'); // Only name-dependent code updates // Nested properties are also reactive console.log(user.preferences.theme()); // 'dark' user.preferences.theme('light'); // Only theme-dependent code updates ``` **Store Methods:** ```js // Individual property access user.name(); // getter user.name('Jane'); // setter // Complete replacement user.set({ name: 'Alice', email: 'alice@example.com', preferences: { theme: 'light', language: 'es' } }); // Partial deep merge user.update({ preferences: { theme: 'dark' } // Merges with existing preferences }); // Cleanup (important for memory management) user.cleanup(); ``` **Advanced Store Patterns:** ```js // Application state store const appStore = store({ user: { id: null, name: '', email: '', roles: [] }, ui: { sidebarOpen: false, theme: 'light', activeModal: null }, data: { todos: [], projects: [], notifications: [] } }); // Computed values from store const isLoggedIn = computed(() => !!appStore.user.id()); const todoCount = computed(() => appStore.data.todos().length); const unreadNotifications = computed(() => appStore.data.notifications().filter(n => !n.read).length ); // Store with validation const createValidatedStore = (initialData, validators = {}) => { const storeInstance = store(initialData); // Wrap setters with validation Object.keys(validators).forEach(key => { const originalSetter = storeInstance[key]; storeInstance[key] = (value) => { if (arguments.length === 0) return originalSetter(); if (validators[key](value)) { originalSetter(value); } else { console.error(`Validation failed for ${key}:`, value); } }; }); return storeInstance; }; const validatedUser = createValidatedStore({ name: '', age: 0, email: '' }, { name: value => typeof value === 'string' && value.length > 0, age: value => typeof value === 'number' && value >= 0, email: value => typeof value === 'string' && value.includes('@') }); // Store with persistence const createPersistedStore = (key, initialData) => { // Load from localStorage const saved = localStorage.getItem(key); const data = saved ? JSON.parse(saved) : initialData; const storeInstance = store(data); // Auto-save to localStorage effect(() => { localStorage.setItem(key, JSON.stringify(storeInstance.computed())); }); return storeInstance; }; const persistedSettings = createPersistedStore('app-settings', { theme: 'light', language: 'en', notifications: true }); ``` **Readonly Properties:** ```js // Specific readonly properties const config = store({ apiUrl: 'https://api.example.com', version: '1.0.0', debug: true }, { readonly: ['apiUrl', 'version'] }); config.debug(false); // ✅ Allowed config.apiUrl('new-url'); // ❌ Runtime error - readonly // All properties readonly const constants = store({ PI: 3.14159, MAX_USERS: 100 }, { readonly: true }); ``` **Nested Stores:** ```js const appState = store({ user: store({ profile: store({ name: 'John', avatar: 'avatar.jpg' }), settings: store({ theme: 'dark', notifications: true }) }), ui: store({ sidebar: store({ isOpen: false, width: 250 }), modals: store({ activeModal: null, backdrop: true }) }) }); // Fine-grained reactivity at every level appState.user.profile.name('Jane'); // Only profile.name dependents update appState.ui.sidebar.isOpen(true); // Only sidebar.isOpen dependents update ``` ### @hellajs/resource - Data Fetching Reactive data fetching with caching, loading states, and error handling. **TypeScript Signatures:** ```typescript function resource( fetcher: (...args: any[]) => Promise | string, options?: ResourceOptions ): Resource; interface Resource { loading(): boolean; error(): Error | null; data(): T | null; status(): 'idle' | 'loading' | 'success' | 'error'; request(): void; fetch(): void; abort(): void; invalidate(): void; } interface ResourceOptions { key?: () => any; initialData?: T; enabled?: boolean; cacheTime?: number; onSuccess?: (data: T) => void; onError?: (error: Error) => void; } ``` **Basic Usage:** ```jsx import { signal } from '@hellajs/core'; import { resource } from '@hellajs/resource'; const userId = signal(1); const userResource = resource( (id) => fetch(`/api/users/${id}`).then(r => r.json()), { key: () => userId(), cacheTime: 60000 } ); // Trigger initial fetch userResource.request(); const UserProfile = () => (
    {userResource.loading() &&
    Loading...
    } {userResource.error() &&
    Error: {userResource.error().message}
    } {userResource.data() && (

    {userResource.data().name}

    {userResource.data().email}

    )}
    ); ``` **Resource States:** - **idle**: No active request - **loading**: Request in progress - **success**: Data available - **error**: Request failed **Advanced Resource Patterns:** ```js // URL-based resources (simple GET requests) const postsResource = resource('/api/posts'); postsResource.request(); // Complex resource with all options const userDataResource = resource( async (userId) => { const response = await fetch(`/api/users/${userId}`); if (!response.ok) { throw new Error(`Failed to fetch user: ${response.statusText}`); } return response.json(); }, { key: () => currentUserId(), initialData: { name: 'Loading...', email: '' }, enabled: computed(() => !!currentUserId() && isAuthenticated()), cacheTime: 5 * 60 * 1000, // 5 minutes onSuccess: (userData) => { console.log('User loaded:', userData.name); analytics.track('user_data_loaded'); }, onError: (error) => { console.error('Failed to load user:', error); errorReporting.captureError(error); } } ); // Resource composition pattern const createResourceGroup = (baseUrl, endpoints) => { return Object.fromEntries( Object.entries(endpoints).map(([name, endpoint]) => [ name, resource(`${baseUrl}${endpoint}`) ]) ); }; const apiResources = createResourceGroup('/api', { users: '/users', posts: '/posts', comments: '/comments' }); // Request lifecycle management const DataComponent = () => { const data = resource(() => new Promise(resolve => setTimeout(() => resolve({ message: 'Data loaded!' }), 2000) ) ); return (
    Status: {data.status()}
    {data.loading() &&
    Loading...
    } {data.data() &&
    {data.data().message}
    }
    ); }; // Error handling with retry const createRetryableResource = (fetcher, options = {}) => { const maxRetries = options.maxRetries || 3; let retryCount = 0; return resource( async (...args) => { try { const result = await fetcher(...args); retryCount = 0; // Reset on success return result; } catch (error) { if (retryCount < maxRetries) { retryCount++; const delay = Math.pow(2, retryCount) * 1000; await new Promise(resolve => setTimeout(resolve, delay)); return fetcher(...args); } throw error; } }, options ); }; // Conditional fetching const conditionalResource = resource( (query) => fetch(`/api/search?q=${query}`).then(r => r.json()), { key: () => searchQuery(), enabled: computed(() => searchQuery().length >= 3) // Only fetch if query is 3+ chars } ); // Dependent resources const userResource = resource(id => fetch(`/api/users/${id}`).then(r => r.json())); const postsResource = resource( userId => fetch(`/api/users/${userId}/posts`).then(r => r.json()), { key: () => userResource.data()?.id, enabled: computed(() => !!userResource.data() && userResource.status() === 'success') } ); // Cache management const managedResource = resource(fetcher, { cacheTime: 10 * 60 * 1000, // 10 minutes key: () => resourceKey() }); // Manual cache control const clearCache = () => managedResource.invalidate(); const forceRefresh = () => managedResource.request(); const useCache = () => managedResource.fetch(); ``` ### @hellajs/router - Client-side Routing Reactive router for single-page applications with history support. **TypeScript Signatures:** ```typescript function router(config: RouterConfig): void; function navigate(path: string, params?: Record, query?: Record, options?: NavigateOptions): void; function route(): RouteInfo; interface RouterConfig { routes: Record; redirects?: RedirectConfig[]; notFound?: RouteHandler; hash?: boolean; hooks?: { before?: () => void; after?: () => void; }; } interface RouteConfig { handler: RouteHandler; before?: () => void; after?: () => void; children?: Record; } interface RouteInfo { handler: RouteHandler | null; params: Record; query: Record; path: string; } type RouteHandler = (params: Record, query: Record) => void; ``` **Basic Setup:** ```jsx import { signal } from '@hellajs/core'; import { router, navigate, route } from '@hellajs/router'; const currentView = signal(null); router({ routes: { '/': () => currentView(), '/about': () => currentView(), '/users/:id': (params) => currentView(), '/search': (params, query) => currentView() }, notFound: () => currentView() }); const App = () => (
    {currentView}
    ); ``` **Advanced Router Features:** **Dynamic Parameters:** ```jsx router({ routes: { '/users/:id': (params) => { const userId = params.id; currentView(); }, '/blog/:category/:postId': (params) => { const { category, postId } = params; currentView(); }, '/files/*': (params) => { const filePath = params['*']; // captures remaining path currentView(); } } }); ``` **Query Parameters:** ```jsx router({ routes: { '/search': (params, query) => { // /search?q=hello&category=posts&page=2 const { q, category, page } = query; currentView(); } } }); ``` **Route Guards and Hooks:** ```jsx const user = signal(null); const isAuthenticated = computed(() => !!user()); const requireAuth = () => { if (!isAuthenticated()) { navigate('/login'); return false; } return true; }; router({ routes: { '/': () => currentView(), '/login': () => currentView(), '/dashboard': { before: requireAuth, handler: () => currentView() }, '/profile': { before: requireAuth, handler: () => currentView(), after: () => console.log('Profile page loaded') } }, hooks: { before: () => { console.log('Navigation starting'); loading(true); }, after: () => { console.log('Navigation complete'); loading(false); } } }); ``` **Nested Routes:** ```jsx router({ routes: { '/admin': { handler: () => currentView(), children: { '/users': { handler: () => currentView(), children: { '/:id': (params) => currentView() } }, '/settings': { handler: () => currentView(), children: { '/general': () => currentView(), '/security': () => currentView() } } } } } }); // /admin/users/123 will have params: { id: '123' } // Child routes inherit parameters from parents ``` **Redirects:** ```jsx router({ routes: { '/dashboard': () => currentView(), '/home': '/', // Simple redirect '/profile': '/user/me' }, redirects: [ { from: ['/old-path', '/legacy'], to: '/new-path' }, { from: ['/admin'], to: '/dashboard' } ] }); ``` **Hash Mode (for static hosting):** ```jsx router({ routes: { '/': () => currentView(), '/about': () => currentView() }, hash: true // URLs become /#/ and /#/about }); ``` **Navigation Methods:** ```js // Basic navigation navigate('/users/123'); // With query parameters navigate('/search', {}, { q: 'hello', page: '2' }); // With parameters and query navigate('/users/:id/posts', { id: '123' }, { sort: 'date' }); // Navigation options navigate('/login', {}, {}, { replace: true }); // Replace history entry navigate('/dashboard', {}, {}, { hash: true }); // Force hash mode ``` **Route Signal Usage:** ```jsx const RouteDebugger = () => { const currentRoute = route(); return (

    Current Route:

    Path: {currentRoute.path}

    Params: {JSON.stringify(currentRoute.params)}

    Query: {JSON.stringify(currentRoute.query)}

    ); }; // Reactive components based on route const Breadcrumbs = () => { const generateBreadcrumbs = () => { const { path, params } = route(); const segments = path.split('/').filter(Boolean); return segments.map((segment, index) => { const isParam = segment.startsWith(':'); const label = isParam ? params[segment.slice(1)] : segment; const href = '/' + segments.slice(0, index + 1).join('/'); return { label, href, isLast: index === segments.length - 1 }; }); }; return ( ); }; ``` **Advanced Router Patterns:** ```jsx // Route-based code splitting const LazyRoute = (importFn) => { return (params, query) => { const component = signal(null); const loading = signal(true); importFn().then(module => { component(module.default); loading(false); }); const LazyComponent = () => { if (loading()) return
    Loading...
    ; const Component = component(); return Component ? : null; }; currentView(); }; }; router({ routes: { '/': () => currentView(), '/dashboard': LazyRoute(() => import('./Dashboard')), '/admin': LazyRoute(() => import('./Admin')) } }); // Route-based data loading const createDataRoute = (component, dataLoader) => { return async (params, query) => { const loading = signal(true); const data = signal(null); const error = signal(null); try { const result = await dataLoader(params, query); data(result); } catch (err) { error(err); } finally { loading(false); } currentView(component({ params, query, data, loading, error })); }; }; router({ routes: { '/users/:id': createDataRoute( UserProfile, (params) => fetch(`/api/users/${params.id}`).then(r => r.json()) ) } }); ``` ### @hellajs/css - CSS-in-JS Type-safe CSS-in-JS with reactive styling and vendor prefixing. **TypeScript Signatures:** ```typescript function css(obj: CSSObject, options?: CSSOptions): string; function cssVars(vars: Record): Record; interface CSSOptions { name?: string; global?: boolean; scoped?: string; } type CSSObject = { [K in keyof CSSProperties]?: CSSProperties[K]; } & { [selector: string]: CSSObject | string | number; }; ``` **Basic Usage:** ```jsx import { css } from '@hellajs/css'; const buttonStyle = css({ padding: '0.75rem 1.5rem', border: 'none', borderRadius: '0.5rem', background: '#3b82f6', color: 'white', fontWeight: '600', cursor: 'pointer', transition: 'all 0.2s ease', '&:hover': { background: '#2563eb', transform: 'translateY(-1px)' }, '&:active': { transform: 'translateY(0)' }, '@media (max-width: 768px)': { padding: '0.5rem 1rem' } }); ``` **Reactive Styles:** ```jsx import { signal, effect } from '@hellajs/core'; import { css } from '@hellajs/css'; const theme = signal('light'); const primaryColor = signal('#3b82f6'); // Reactive styles - automatically update when signals change effect(() => { const dynamicButtonStyle = css({ backgroundColor: primaryColor(), color: theme() === 'dark' ? '#ffffff' : '#000000', padding: '0.75rem 1.5rem', border: `2px solid ${theme() === 'dark' ? '#374151' : '#e5e7eb'}`, borderRadius: '0.5rem', cursor: 'pointer', transition: 'all 0.3s ease', '&:hover': { opacity: 0.8, transform: 'scale(1.02)' } }); }); const ThemeControls = () => (
    primaryColor(e.target.value)} />
    ); ``` **Advanced CSS Patterns:** ```jsx // Responsive design const responsiveGrid = css({ display: 'grid', gap: '1rem', gridTemplateColumns: 'repeat(1, 1fr)', '@media (min-width: 640px)': { gridTemplateColumns: 'repeat(2, 1fr)' }, '@media (min-width: 1024px)': { gridTemplateColumns: 'repeat(3, 1fr)' }, '@media (min-width: 1280px)': { gridTemplateColumns: 'repeat(4, 1fr)' } }); // Animations const fadeIn = css({ '@keyframes fadeIn': { from: { opacity: 0, transform: 'translateY(10px)' }, to: { opacity: 1, transform: 'translateY(0)' } }, animation: 'fadeIn 0.3s ease-out', animationFillMode: 'forwards' }); // Complex selectors const cardStyle = css({ padding: '2rem', borderRadius: '0.75rem', border: '1px solid #e5e7eb', backgroundColor: 'white', boxShadow: '0 1px 3px rgba(0,0,0,0.1)', transition: 'all 0.3s ease', '&:hover': { boxShadow: '0 10px 25px rgba(0,0,0,0.15)', transform: 'translateY(-2px)' }, '& h2': { margin: '0 0 1rem 0', fontSize: '1.5rem', fontWeight: '600' }, '& p': { margin: 0, color: '#6b7280', lineHeight: '1.6' }, '& .card-footer': { marginTop: '1rem', paddingTop: '1rem', borderTop: '1px solid #f3f4f6', display: 'flex', justifyContent: 'space-between', alignItems: 'center' } }); // Scoping options const scopedStyles = css({ '.button': { padding: '0.5rem 1rem' }, '.button.primary': { backgroundColor: '#3b82f6', color: 'white' } }, { scoped: 'my-component' }); // Global styles css({ '*': { boxSizing: 'border-box' }, 'body': { margin: 0, fontFamily: 'system-ui, sans-serif', lineHeight: '1.6' }, 'a': { color: '#3b82f6', textDecoration: 'none' }, 'a:hover': { textDecoration: 'underline' } }, { global: true }); ``` **CSS Variables (Custom Properties):** ```jsx import { cssVars } from '@hellajs/css'; // Static CSS variables const theme = cssVars({ colors: { primary: '#3b82f6', secondary: '#64748b', background: '#ffffff', text: '#1f2937' }, spacing: { xs: '0.25rem', sm: '0.5rem', md: '1rem', lg: '2rem', xl: '4rem' }, fonts: { body: 'system-ui, sans-serif', heading: 'Georgia, serif', mono: 'Menlo, monospace' } }); // Use variables in styles const componentStyle = css({ backgroundColor: 'var(--colors-background)', color: 'var(--colors-text)', padding: 'var(--spacing-lg)', fontFamily: 'var(--fonts-body)' }); // Reactive CSS variables const themeMode = signal('light'); const accentColor = signal('#3b82f6'); effect(() => { const reactiveTheme = cssVars({ theme: { background: themeMode() === 'dark' ? '#0f172a' : '#ffffff', text: themeMode() === 'dark' ? '#f1f5f9' : '#1e293b', accent: accentColor(), border: themeMode() === 'dark' ? '#374151' : '#e5e7eb' } }); }); // Batched theme updates const applyTheme = (mode, color) => { batch(() => { themeMode(mode); accentColor(color); }); // Single efficient CSS variable update }; ``` **Performance Optimization:** ```jsx // Cache static styles at module level const staticButtonStyle = css({ padding: '0.75rem 1.5rem', border: 'none', borderRadius: '0.5rem' }); // Use computed for expensive style calculations const expensiveStyle = computed(() => { // Only recalculates when dependencies change return css({ background: computeComplexGradient(primaryColor(), secondaryColor()), boxShadow: generateComplexShadow(elevation(), blur()) }); }); // Batch multiple style changes const updateStyles = () => { batch(() => { primaryColor('#ff0000'); secondaryColor('#00ff00'); elevation(5); }); // Single DOM update for all style changes }; // Memory management const cleanup = () => { // Remove unused styles css.remove(staticButtonStyle); }; ``` ## JSX Templating System HellaJS uses an advanced templating system that eliminates virtual DOM diffing by creating direct reactive bindings between data and DOM elements. ### Reactive Bindings HellaJS creates function references for reactive bindings when JSX expressions contain function calls: **Valid Patterns:** ```jsx // Signal references (recommended)

    {count}

    // ✅ Reactive binding

    {user().name}

    // ✅ Reactive property access

    {() => count() * 2}

    // ✅ Reactive derived function

    {count() * 2}

    // ✅ Reactive derived expression // Event handlers // ✅ Arrow function // ✅ Function reference // Template literals (must call signals)

    {`Count: ${count()}`}

    // ✅ Reactive template literal

    {`Count: ${count}`}

    // ❌ Static template literal ``` **Advanced Binding Examples:** ```jsx const App = () => { const count = signal(0); const user = signal({ name: 'John', role: 'admin' }); const todos = signal([]); return (
    {/* Simple reactive bindings */}

    Count: {count}

    User: {user().name}

    {/* Conditional bindings */}

    {count() > 10 ? 'High' : 'Low'}

    {user().role === 'admin' && 'Administrator'}

    {/* Derived values */}

    Doubled: {() => count() * 2}

    Progress: {() => Math.min((count() / 100) * 100, 100)}%

    {/* Complex expressions */}
    5 ? 'active' : 'inactive'}`}> Status: {count() > 5 ? 'Active' : 'Inactive'}
    {/* Array operations */}

    Todo count: {() => todos().length}

    Completed: {() => todos().filter(t => t.done).length}

    {/* Template literals */} {`${user().name} - Todo App (${todos().length})`}
    ); }; ``` ### Component Patterns **Static Components:** ```jsx const Header = ({ title, subtitle }) => (

    {title}

    {subtitle &&

    {subtitle}

    }
    ); const Footer = ({ year = new Date().getFullYear() }) => (

    © {year} My App

    ); ``` **Interactive Components:** ```jsx const Counter = ({ initialValue = 0, step = 1 }) => { const count = signal(initialValue); const increment = () => count(count() + step); const decrement = () => count(count() - step); const reset = () => count(initialValue); return (

    Count: {count}

    ); }; const TodoItem = ({ todo, onToggle, onDelete, onEdit }) => { const isEditing = signal(false); const editText = signal(todo().text); const handleSave = () => { if (editText().trim()) { onEdit(todo().id, editText().trim()); isEditing(false); } }; const handleCancel = () => { editText(todo().text); isEditing(false); }; return (
  • onToggle(todo().id)} /> {isEditing() ? (
    editText(e.target.value)} onKeyDown={e => { if (e.key === 'Enter') handleSave(); if (e.key === 'Escape') handleCancel(); }} autofocus />
    ) : (
    isEditing(true)} > {todo().text}
    )}
  • ); }; ``` **Component Composition:** ```jsx const Card = ({ title, variant = 'default', className = '' }, children) => (
    {title &&

    {title}

    }
    {children}
    ); const Modal = ({ isOpen, onClose, title }, children) => { // Close on escape key effect(() => { if (isOpen()) { const handleEscape = (e) => { if (e.key === 'Escape') onClose(); }; document.addEventListener('keydown', handleEscape); return () => document.removeEventListener('keydown', handleEscape); } }); if (!isOpen()) return null; return ( <>