The schema system provides a framework-agnostic, schema-driven UI renderer designed for modular web apps. It turns declarative JSON-like schemas into live, reactive UIs, supporting layouts, routing, slots, and dynamic data/actions.
@we/schema-shared(shared/) — Framework-agnostic types, validators, prop resolvers, and mutations@we/schema-solid(solid/) — SolidJS renderer implementation
Operators that appear inside props and resolve to values:
| Operator | Purpose | Example |
|---|---|---|
$store |
Reactive store access | { $store: 'userStore.name' } |
$concat |
String building | { $concat: ['/space/', '$item.uuid'] } |
$action |
Store method call + async lifecycle | { $action: 'store.method', args: ['$arg.id'], onSuccess: [...] } |
$map |
Array/object transformation | { $map: { items: ..., select: { ... } } } |
$pick |
Property extraction | { $pick: { from: ..., props: ['a', 'b'] } } |
$if |
Conditional value | { $if: { condition: ..., then: 'a', else: 'b' } } |
$eq / $ne |
Equality / inequality | { $eq: [{ $store: 'x.role' }, 'admin'] } |
$not |
Logical NOT | { $not: { $store: 'x.locked' } } |
$and / $or |
Logical AND / OR | { $and: [cond1, cond2] } |
$item.* |
Context reference | '$space.name' (inside $each children) |
Operators that appear as the type field and control rendering structure:
| Operator | Purpose |
|---|---|
$if (node) |
Conditional rendering with optional transitions |
$each |
List rendering with context injection |
$routes |
Route outlet placeholder |
| Fragment | Renders children without wrapper (no type) |
| HTML passthrough | Lowercase types render as native elements |
- Slots: Named slots for layout composition
- Component registry: PascalCase → registered component,
we-*→ web component, lowercase → HTML element - REACTIVE_ACCESSOR: Signal tagging for web component prop unwrapping
- Schema validation: Zod-based validation with
validateSchema() - Schema mutations:
findMutations()for diff-based updates,updateSchema()for applying changes - Schema versioning:
schemaVersionfield for future migrations - Transitions:
TransitionConfigfor animated$ifnode show/hide (fade,slide,scale) - Operator token types:
StoreToken,ConcatToken,ActionToken,OperatorToken, etc. for typed schema authoring
See OPERATORS.md for the full operator reference.
-
Install:
pnpm add @we/schema-shared @we/schema-solid solid-js
-
Create a component registry in your app:
import { MyComponent, AnotherComponent } from './components'; export const registry = { MyComponent, AnotherComponent, // ...other components };
-
Render a schema:
import { RenderSchema } from '@we/schema-solid'; import { registry } from './registry'; <RenderSchema node={mySchema} stores={myStores} registry={registry} />;
- Shared types and prop resolvers are in
shared/. - Framework-specific renderers are in
solid/(addreact/, etc. for other frameworks). - To add support for another framework, implement a renderer that uses the shared logic and passes the correct JSX type.
- Types:
SchemaNode,TemplateSchema,RouteSchema,SchemaProp,ComponentRegistry,RenderProps,RendererOutput,TransitionConfig - Operator token types:
StoreToken,ExprToken,ActionToken,IfToken,MapToken,PickToken,EqToken,NeToken,NotToken,AndToken,OrToken,OperatorToken - Functions:
resolveProp(),resolveProps(),splitProps(),validateSchema(),findMutations(),hasToken() - Constants:
REACTIVE_ACCESSOR
RenderSchema: Main renderer componentupdateSchema(): Apply mutations to a reactive Solid store
MIT