A modular ES module toolkit for building JavaScript apps — no build step required.
Fstage is a platform layer: it provides a loader, import map resolution, and a set of composable modules you use to assemble your own framework. Works with any rendering library (LitElement, plain DOM, etc.).
Alpha — breaking changes may occur.
- No build step — native ES modules and import maps only
- Platform stability — conservative ES2020 baseline, explicit control flow, minimal dependencies (see CONTRIBUTING.md)
- Composable — use only the modules you need; wire them together via the registry
- No component lock-in — the component model is defined by a versioned open standard that any runtime can implement
- ES module support (
<script type="module">) - Import map support (Safari 16.4+, Chrome 96+)
- Add the fstage loader to your HTML and set a config path:
<script>
window.FSCONFIG = { configPath: 'js/config.mjs' };
</script>
<script type="module" src="https://cdn.jsdelivr.net/gh/codi0/fstage@latest/src/js/fstage.min.mjs"></script>- Create
js/config.mjs— this is where you declare your import map, load phases, and wire up services. See the tasks example config for a complete reference, or the starter example config for an annotated walkthrough.
fstage dispatches fstage.ready on window when the app is loaded, and fstage.failed on error.
Apps load in sequential phases declared under loadAssets in your config:
export default {
importMap: {
'lit': 'https://cdn.jsdelivr.net/npm/lit-element@4/+esm',
},
loadAssets: {
preload: [ '@fstage/env', '@fstage/registry', '@fstage/stack' ],
libs: [ 'lit', '@fstage/component', '@fstage/store', '@fstage/sync',
'@fstage/history', '@fstage/router', '@fstage/animator',
'@fstage/gestures', '@fstage/transitions',
'@fstage/interactions', '@fstage/form' ],
app: [ 'js/components/app.mjs', 'css/style.css' ],
},
router: {
urlScheme: 'hash',
routes: [ { path: '/', meta: { component: 'my-home', title: 'Home' } } ],
},
storage: { name: 'myapp', schemas: { items: { keyPath: 'id' } } },
afterLoadPreload(e) { e.modules.get('stack.wirePreload', [ e ]); },
afterLoadLibs(e) { e.modules.get('stack.wireStack', [ e ]); },
afterLoadApp(e) { e.modules.get('stack.startStack', [ e ]); },
};Each phase completes before the next starts. afterLoad, afterLoadPreload, afterLoadLibs, and afterLoadApp hooks fire at the end of each phase. The registry is the central service locator — modules register instances there and components inject what they need.
@fstage/stack provides wirePreload, wireStack, and startStack helpers that handle all standard service wiring from config keys alone. Hooks receive an e object with modules and configs namespaces:
e.configs.root() // full root config object
e.configs.root().debug // nested config value
e.modules.get('stack.wireStack', [ e ]) // calls wireStack(e)
e.modules.get('store.createStore', []) // calls createStore(), returns instanceSee the getting started guide for a full walkthrough.
| Example | Description |
|---|---|
examples/starter |
Minimal annotated shell — single route, counter demo, start here |
examples/tasks |
Complete To-Do PWA — sync, offline, animations, gestures, Capacitor |
cd examples/starter && npx serve .See examples/README.md for details.
| Module | Description |
|---|---|
stack |
Default service wiring — wirePreload, wireStack, startStack helpers that replace ~80 lines of afterLoadLibs/afterLoadApp boilerplate with a single call |
store |
Reactive store — get/set/watch, computed, effects, and a full data-lifecycle system (fetch, cache, TTL, optimistic updates, pagination) |
sync |
Offline-first sync — local-first reads/writes, remote handler abstraction, write queue with exponential backoff retry. Also re-exports storage and http — import from here unless you need those modules standalone |
storage |
Two-tier IndexedDB — simple key/value blob store or schema-based rows with SQL-like querying. Re-exported by sync |
http |
Thin fetch wrapper with timeout, form/JSON body helpers, and response parsing. Re-exported by sync |
router |
Client-side router — deterministic matching, param extraction, navigation handler, scroll state |
history |
Browser history abstraction — hash, query string, or path URL schemes |
component |
Web component runtime implementing the Universal Component Definition Standard — declarative state, bindings, watches, computed, animations, interactions |
plugin |
Plugin lifecycle runtime — source registration, activation/deactivation, cleanup scope, handler/contribution ownership |
registry |
Service registry / DI container — the glue between modules |
env |
Platform detection, capability facts, and a layered policy system with CSS variable output |
animator |
WAAPI animation engine — named presets, toggle controllers, flip, stagger, collapse |
transitions |
View transition engine and screen host for page-level animations |
interactions |
Delegated event handling with debounce/throttle and gesture/transition extensions |
gestures |
Touch/pointer gesture detection — swipe, edge pan, long press, tap |
ui |
Reusable, accessible UI primitives — fs-action-sheet (imperative iOS-style sheet), fs-bottom-sheet (swipe-dismissable modal), fs-dialog (centered modal), fs-disclosure (animated show/hide), fs-listbox (keyboard-navigable select with typeahead). All unstyled, CSS-custom-property driven |
form |
Store-backed form validation and submit lifecycle for component definitions |
ssr |
Server-side rendering via Declarative Shadow DOM — createSsrRuntime + renderToString. Supports state defaults, reactive getters, all $src shorthands, host attribute stamping, and per-call error handling. Requires @lit-labs/ssr as a peer dep |
devtools |
Debug panel — store event log, sync queue inspector, storage browser |
push |
Unified push facade with native (Capacitor) + web adapters |
websocket |
Small WebSocket helper with reconnect, send queue, custom events, and channel pub/sub |
utils |
Shared primitives: deep copy, equality, diff, hash, debounce, schedule, nested key access, DOM helpers |
- Getting started
- Stack — default wiring
- UI primitives
- SSR — server-side rendering
- Store
- Data layer — storage, sync, http
- Push — unified native + web notifications
- WebSocket
- Routing — router, history
- Components
- Forms
- Plugin runtime
- Platform — env, animator, transitions, gestures, interactions
- Utilities — utils, registry
- Devtools
- Component Definition Standard
See CONTRIBUTING.md for the coding standard, syntax baseline, and source style guide.