SimpliJS · API reference
Technical Spec: At a Glance
📦 Core imports & types
All framework symbols are importable from the CDN or local simplijs.js.
// Full type definition (simplijs.d.ts)
// Register a new SimpliJS component
component(name: string, setup: ComponentSetup): void;
type ComponentSetup = (element: HTMLElement, props: Record) => ComponentOutput;
type ComponentOutput = {
render?: () => string;
onMount?: () => void;
onUpdate?: () => void;
onDestroy?: () => void;
[key: string]: any; // Custom methods
};
🧩 component(name, setup)
Registers a custom element. The setup function receives the element instance and a reactive props object (auto‑synced from attributes).
// Example with typed props & methods
component('user-profile', (el, props) => {
const state = reactive({ count: 0 });
return {
inc: () => state.count++,
render: () => `
Count: ${state.count} | Initial: ${props.initialCount}
`
};
});
⚠️ Attribute sync: Attributes like count="5" become props.count (string). Use watch or computed for number coercion.
⚛️ reactive(), computed(), watch()
// deeply reactive with error handling
const form = reactive({
email: '',
touches: 0
});
// computed with implicit error catching → component.onError can handle
const isEmail = computed(() => {
if (!form.email.includes('@')) throw new Error('Invalid email format');
return true;
});
watch(() => form.email, (newVal, oldVal) => {
try {
console.log(`email changed: ${oldVal} → ${newVal}`);
} catch (e) {
// if watch throws, it bubbles to component onError (if defined)
throw e;
}
});
computed or watch will be caught by the nearest component’s onError hook. Unhandled errors are logged to console but do not break the app.
🪝 ref() & lifecycle hooks
Refs are populated after render, before onMount.
component('focus-input', (el) => {
const myInput = ref();
return {
onMount: () => {
myInput.value?.focus();
},
onUpdate: () => console.log('rerendered'),
onDestroy: () => console.log('cleanup'),
render: () => ``
};
});
Ref assignment: use s-ref="yourRefName" in template string, matching the key returned from ref().
📡 emit() & on() (global bus)
// component A: emit
component('pinger', () => ({
ping: () => emit('network:status', { online: navigator.onLine }),
render: () => ``
}));
// component B: listen (auto clean on destroy)
component('ponger', () => {
const unsub = on('network:status', (data) => {
console.log('pong', data);
});
return {
onDestroy: () => unsub(),
render: () => `Listening...`
};
});
Error handling: if a handler throws, other listeners still run; error is emitted to window.onerror and component.onError of the listener’s component (if any).
⚡ 41 HTML-First Directives
SimpliJS provides 41 native directives that work directly in your HTML. No compilation required. Below is the categorized reference.
| Category | Directives | Description / Syntax |
|---|---|---|
| Core | s-app | Application boundary for the engine. Initialized on mount. |
| Binding | s-bind / s-model | Deep reactive text/number/form sync. |
| Logic | s-if / s-for / s-switch | Template-driven logic flow with optimized DOM patching. |
| Events | s-click / s-submit / s-key | Declarative performance-optimized event listeners. |
| Utility | s-text / s-html / s-ref | Direct content and DOM ref management. |
Note: The v3.2.0 Directive Engine is highly optimized for performance and works directly on the DOM without a Virtual DOM overhead.
📋 createApp().form() – automated validation
interface FormConfig {
fields: string[]; // field names
validate?: Record<string, (val: any) => string | null>;
onError?: (errors: Record<string, string>) => void;
submit: (data: Record<string, any>) => void;
}
component('contact-form', () => {
const handler = createApp().form({
fields: ['name', 'email'],
validate: {
email: (v) => /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(v) ? null : 'invalid email',
name: (v) => v.trim() ? null : 'name required'
},
onError: (errs) => console.table(errs),
submit: (data) => fetch('/api', { method:'POST', body: JSON.stringify(data) })
});
return {
handler,
render: () => `
`
};
});
✋ Invalid fields automatically get class .is-invalid; the onError receives map of field → message.
🌉 use – universal component bridge
import { use, component } from 'simplijs';
// import a React icon component (ESM)
const IconTag = use.react('https://esm.sh/lucide-react?alias=react&bundle', 'Heart');
component('like-button', () => ({
render: () => `
<button>
<${IconTag} color="red" size="20"></${IconTag}>
like
</button>
`
}));
// error handling: if module fails, component renders nothing and onError is called
Status: The Bridge is fully operational in v3.2.0, allowing seamless integration of React, Vue, and Svelte components into SimpliJS layouts.
🔌 Official Plugin Ecosystem
The SimpliJS ecosystem includes 7 high-performance plugins for enterprise features.
1. @simplijs/auth
Complete auth lifecycle management.
- •
auth.login(creds)- Authenticate and store session. - •
auth.user- Reactive user object. - •
auth.guard(route)- Route protection helper.
2. @simplijs/router
Declarative SPA routing.
- •
router.push(path)- Navigation. - •
router.params- Reactive URL parameters. - •
<s-view>- Router outlet directive.
3. @simplijs/vault-pro
Extended state time-travel and persistence.
- •
s.vault.sync()- Sync state with remote server. - •
s.vault.encrypt()- AES encryption for sensitive local state.
Also includes: @simplijs/bridge-adapters, @simplijs/devtools, @simplijs/forms, and @simplijs/ssg.
🌐 Advanced SEO & SSG Reference
Documentation for @simplijs/ssg and built-in industrial SEO tools.
SEO Helpers (In-App)
// Dynamic Metadata Updates
setSEO({
title: 'My Profile | SimpliJS',
description: 'Pro-grade Reactive Social App',
image: 'https://cdn.com/og.jpg',
twitterHandle: '@sb_tech'
});
// Structured Data (JSON-LD)
setJsonLd({
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": "SimpliJS"
});
// Breadcrumbs & Theme
setBreadcrumbs([{ name: 'Docs', url: '/docs' }, { name: 'SEO', url: '/seo' }]);
setThemeColor('#6a0dad');
SSG Configuration (ssg.config.js)
export default {
baseUrl: 'https://mysite.com',
outDir: 'dist',
minify: true,
rss: { title: 'Blog', items: [...] },
routes: {
'/': HomeTemplate,
'/blog': BlogListTemplate
}
};
// CLI Execution: node ssg.js ssg.config.js
🛡️ Security-First Directive Engine
SimpliJS addresses traditional framework security vulnerabilities (XSS, Template Injection) at the architectural level.
Safe Evaluation Mode
By default, s-state and s-click expressions are evaluated through a high-performance sandbox that prevents access to window, document, or sensitive cookies.
CSP Compatibility
SimpliJS is fully compliant with strict Content Security Policies. It avoids eval() and new Function() for directive parsing, using a custom-built lexical tokenizer.
🕰️ reactive.vault() – time travel state
interface VaultControls {
back(): void; // undo
forward(): void; // redo
share(): string; // returns URL with ?simpli-debug=base64
timeline(): ReadonlyArray<T> // debug history
}
const globalState = reactive.vault({
filter: 'all',
items: []
});
component('vault-ui', () => ({
undo: () => globalState.vault.back(),
redo: () => globalState.vault.forward(),
shareDebug: () => {
const url = globalState.vault.share();
navigator.clipboard?.writeText(url);
},
render: () => `
<div>
<button s-click="undo()">↩️ undo</button>
<button s-click="redo()">↪️ redo</button>
<button s-click="shareDebug()">🔗 share timeline</button>
</div>
`
}));
⏳ Restore from URL: SimpliJS automatically detects ?simpli-debug=... on page load and hydrates the vault.
🧾 Advanced props & attribute typing
Props are reactive, but note that HTML attributes are always strings. Use computed / watch to convert.
component<{ value: string; }>('numeric-display', (el, props) => {
const asNumber = computed(() => {
const num = Number(props.value);
if (isNaN(num)) throw new TypeError(`"${props.value}" is not a number`);
return num;
});
return {
render: () => `<p>${asNumber.value} * 2 = ${asNumber.value * 2}</p>`,
onError: (err) => {
el.innerHTML = `⚠️ ${err.message}`; // fallback ui
}
};
});
🚨 Comprehensive error handling patterns
SimpliJS does not swallow errors – it delegates to hooks and provides fallbacks.
| Scenario | Error object | Handled by |
|---|---|---|
| render() throws | RenderError | console.log + engine fallback |
| event handler throws | original error | window.onerror |
| watch / computed throws | original | console.log + re-throws |
| form validation error (custom) | n/a | config.onError / UI classes |
| bridge import fails | ImportError | console.log |
// top‑level error boundary pattern (wrapping component)
component('error-boundary', () => {
const state = reactive({ hasError: false, errorMsg: '' });
return {
onError: (err) => {
state.hasError = true;
state.errorMsg = err.message;
},
render: () => state.hasError
? `<div>🔥 crash: ${state.errorMsg}</div>`
: `<inner-component />` // child may throw
};
});
🧩 Slot projection
SimpliJS v3.2.0 supports full content projection via s-slot and default slots.
component('user-layout', () => ({
render: () => `
<header><s-slot name="header" /></header>
<main><s-slot /></main>
`
}));
📌 TypeScript / JSDoc quick template
/**
* @param {HTMLElement} el
*/
function setup(el) {
return {
render: () => `Component is active`
};
}
component('typed-demo', setup);
Use the included simplijs.d.ts for full IDE autocompletion.