SynapseJS ⚡
Upgrading from 1.8? 1.9 is a security-hardening release with four breaking behaviour changes. Read
docs/migration-1.9.md— each change names the symptom, the reason and the flag that restores the old behaviour where restoring it is safe.
⚡ Why SynapseJS?
Modern fullstack development has broken developer productivity. Changing a single button, query, or validation rule forces you to navigate 5 to 7 decoupled layers across multiple folders:
❌ TRADITIONAL FRAGMENTED STACK:
routes/customers.ts ──────► controllers/customerController.ts
│
dto/customer.dto.ts ◄──────────────┼──────────────► services/customerService.ts
│
entities/Customer.ts ◄──────────────┼──────────────► migrations/001_create_customers.sql
│
components/CustomerForm.tsx ◄───────┼──────────────► tests/customer.test.ts
For human developers, this imposes high cognitive friction. For autonomous AI coding agents (Claude, Cursor, Windsurf, Antigravity), it wastes massive context tokens, invites implicit coupling errors, and triggers endless hallucinated imports.
The SynapseJS Revolution: Locality of Behavior ($N = 1$)
SynapseJS eliminates architectural scattering entirely: a feature is a single contiguous file (*.slice.tsx).
✅ SYNAPSEJS VERTICAL SLICE (src/slices/customers/create-customer.slice.tsx):
┌────────────────────────────────────────────────────────────────────────┐
│ 1. Input Contract ── TypeBox JIT schema (validated at wire speed) │
│ 2. Database DDL ── Declarative SQL statement (up & down) │
│ 3. Functional Result ── Strict Result<T, E> union (zero throw) │
│ 4. Server Action ── Transactional business logic & mutation │
│ 5. SSR Loader ── Server data prefetching │
│ 6. React 19 View ── Interactive UI with auto RPC binding │
│ 7. Test Oracle ── Property-Based Tests (PBT via fast-check) │
└────────────────────────────────────────────────────────────────────────┘
An AST-driven Isomorphic Splitter separates server code (SQL, credentials, actions) from client code (React, RPC stubs) at build time with compiler-enforced AST isolation and automated leak verification gates.
🚀 30-Second Quickstart
Get a production-grade SynapseJS application running in less than 30 seconds:
# 1. Scaffold a new application
bunx @ismaelsoilet/synapsejs new my-saas-app
# 2. Enter project directory & install
cd my-saas-app
bun install
# 3. Start development server with live migrations & Dev Hub
bun run dev
Visit http://localhost:3000 to see your running application and interactive Developer Hub.
Generate a Complete Vertical Slice in One Command
bun run new-slice customers create-customer --fields="name:string,email:string,role:enum(ADMIN|USER)"
The CLI instantly generates:
- Full TypeBox input validator
- SQL table definition with automated migration tracking
- Typed server action returning
Result<Customer, 'INVALID_SCHEMA' | 'DUPLICATE_EMAIL'> - Accessible React 19 UI component
- Property-based test suite executed via
bun:test
🌟 The 7 Architectural Pillars
🧩 Anatomy of a Real Vertical Slice
Here is what an authentic production slice looks like (src/slices/tickets/create-ticket.slice.tsx):
import {
Type,
type Static,
Value,
Ok,
Err,
type Result,
type DatabaseClient,
type SessionContext,
requireAuth,
defineJob,
defineAction,
defineCache,
DataTable,
Button
} from 'synapsejs';
// 1. Input Contract (TypeBox JIT schema)
export const TicketInputSchema = Type.Object({
subject: Type.String({ minLength: 3 }),
priority: Type.Integer({ minimum: 1, maximum: 5 })
});
export type TicketInput = Static<typeof TicketInputSchema>;
// 2. Database DDL (Bidirectional, tracked in _synapse_migration_statements)
export const sliceSchema = `
-- up:
CREATE TABLE IF NOT EXISTS tickets (
id TEXT PRIMARY KEY,
subject TEXT NOT NULL,
priority INTEGER NOT NULL,
status TEXT NOT NULL DEFAULT 'OPEN',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- down:
DROP TABLE IF EXISTS tickets;
`;
// 3. Strict Domain Output Contract
export type TicketOutput = Result<
{ ticketId: string },
'INVALID_SCHEMA' | 'NO_DATABASE' | 'UNAUTHORIZED' | 'FORBIDDEN'
>;
// 4. Background Job
export const notifyStaffJob = defineJob<{ ticketId: string }>({
name: 'notify-staff-ticket',
retryLimit: 3,
backoffSeconds: 5,
perform: async (payload) => {
console.log(`Notification sent for ticket ${payload.ticketId}`);
}
});
// 5. Server Action (Fail-Closed by default, automatic TypeBox validation & RPC stub compilation)
export const createTicketAction = defineAction({
input: TicketInputSchema,
auth: ['support'], // Fail-Closed: requires authenticated session with 'support' role. Use auth: 'public' for open endpoints.
handler: async ({ input, db, session }): Promise<TicketOutput> => {
if (!db) return Err('NO_DATABASE');
const ticketId = crypto.randomUUID();
await db.query(
`INSERT INTO tickets (id, subject, priority, status) VALUES ($1, $2, $3, 'OPEN')`,
[ticketId, input.subject, input.priority]
);
return Ok({ ticketId });
}
});
// 6. SSR Data Loader (Pre-rendered on the server)
export async function createTicketLoader(ctx: { db: DatabaseClient; session: SessionContext }) {
const recentTickets = await ctx.db.findMany<{ id: string; subject: string; priority: number }>(
'tickets',
{ limit: 5, orderBy: { created_at: 'DESC' } }
);
return { recentTickets };
}
// 7. SSR Micro-Cache & ISR Policy (Instant sub-millisecond in-memory cache)
export const sliceCache = defineCache({
ttlSeconds: 60,
staleWhileRevalidateSeconds: 300,
tags: ['tickets']
});
// 8. Dynamic SEO Head Metadata
export function sliceMeta(data: { recentTickets?: unknown[] }) {
return {
title: 'Support Tickets — SynapseJS',
description: 'Create and track customer support requests in real time.',
openGraph: { type: 'website' }
};
}
// 9. React 19 Interactive View Component
export function CreateTicketComponent(props: {
recentTickets?: Array<{ id: string; subject: string; priority: number }>;
onSubmitAction?: (payload: unknown) => Promise<TicketOutput>;
}) {
return (
<div className="p-6 max-w-xl mx-auto space-y-6">
<h1 className="text-2xl font-bold">Open Support Ticket</h1>
<form
onSubmit={async (e) => {
e.preventDefault();
const form = e.currentTarget;
const data = new FormData(form);
const res = await props.onSubmitAction?.({
subject: String(data.get('subject')),
priority: Number(data.get('priority'))
});
if (res?.ok) alert(`Ticket created: ${res.value.ticketId}`);
else alert(`Error: ${res?.error}`);
}}
className="space-y-4"
>
<input name="subject" placeholder="Ticket Subject" className="w-full border p-2 rounded" />
<input name="priority" type="number" defaultValue={3} className="w-full border p-2 rounded" />
<Button type="submit">Submit Ticket</Button>
</form>
{props.recentTickets && (
<DataTable
data={props.recentTickets}
columns={[
{ key: 'subject', header: 'Subject' },
{ key: 'priority', header: 'Priority' }
]}
/>
)}
</div>
);
}
// 10. Property-Based Test Oracle (Verified under bun:test)
export const sliceTests = {
description: 'Support Ticket Invariants',
cases: [
{
name: 'anonymous callers return UNAUTHORIZED before touching the database',
run: async () => {
const res = await createTicketAction({ subject: 'Outage', priority: 1 });
if (res.ok || res.error !== 'UNAUTHORIZED') {
throw new Error(`Expected UNAUTHORIZED, received ${JSON.stringify(res)}`);
}
}
}
]
};
The Golden Rule: Slices Never Import Slices
┌──────────────────────────────────────────────┐
│ src/slices/billing/invoice.slice.tsx │
└──────────────────────┬───────────────────────┘
│ ❌ STRICTLY FORBIDDEN
▼
┌──────────────────────────────────────────────┐
│ src/slices/customers/customer.slice.tsx │
└──────────────────────┬───────────────────────┘
│
Both import from│ shared domain logic
▼
┌──────────────────────────────────────────────┐
│ src/shared/transactions.ts │
│ (Receives DatabaseClient, opens db.tx) │
└──────────────────────────────────────────────┘
If two features must coordinate or share transactional state, that logic belongs in src/shared/<module>.ts. Violations are blocked at compile time with error SLICE_IMPORTS_SLICE.
⚡ High-Performance SSR Micro-Cache & ISR (Incremental Static Regeneration)
SynapseJS eliminates redundant database roundtrips and SSR re-renders on high-traffic read paths. Slices declare caching semantics natively with defineCache:
export const sliceCache = defineCache({
ttlSeconds: 60, // Serves instantaneous in-memory HTML (HIT) for 60 seconds
staleWhileRevalidateSeconds: 300, // Serves stale HTML instantly (STALE) while refreshing in the background
tags: ['tickets', 'support-portal'] // Atomic invalidation keys
});
- Sub-Millisecond In-Memory Hits: Cached HTML is served in < 0.5 ms directly from RAM with header
X-Synapse-Cache: HIT. - Non-Blocking Background ISR: When content enters the
staleWhileRevalidatewindow, callers receive the cached HTML immediately (X-Synapse-Cache: STALE) while Synapse asynchronously re-executes the loader and re-renders fresh HTML in the background without blocking the request. - Deterministic Tag Invalidation: When an action performs a mutation, purge affected pages immediately via
ctx.invalidateCache(['tickets'])or programmatically withserver.invalidateCache(['tickets']). - Cache-Control Transparency: The HTTP server sets standard
Cache-Control: public, max-age=60, stale-while-revalidate=300headers for edge CDNs (Cloudflare, Fastly).
🛡️ Production Hardening & Resilience
The framework ships enterprise-grade resilience guards designed for zero-trust production deployments:
- SSRF & Network Guard:
validateExternalUrlandisPrivateOrReservedIpactively block server-side request forgery targeting loopback, private IPv4/IPv6 CIDRs and cloud metadata endpoints (169.254.169.254, AWS, GCP, Azure). The outbound fetch then connects to the exact address that passed validation (the hostname is never resolved a second time) and refuses redirects, so a rebinding change between check and fetch cannot reach a private address. Static image optimization enforces strict public directory containment. - Anti-Spoofing & Bounded Rate Limiting: The token bucket rate limiter bounds its registry (10,000 client identities by default) and refuses the excess when it is saturated instead of evicting a live counter, so a rotating-identity flood cannot reset an abuser's allowance. Forwarding headers are honoured only under an explicit
SYNAPSE_TRUST_PROXY=true; otherwise the socket address is the identity. State is per process — seepackages/synapse/README.md. - Bounded LRU SSR Cache: In-memory micro-cache bounds storage with LRU eviction and normalizes URLs by sorting query parameters and stripping ad/tracking tokens (
utm_*,fbclid,gclid). - Strict Payload Guards: Automated HTTP 413 rejection for oversized RPC payloads (
maxRpcPayloadBytes, 5MB) and Webhook payloads (maxWebhookPayloadBytes, 10MB), with clean HTTP 400 on malformed JSON bodies. - Zombie Job Auto-Recovery: SQLite and PostgreSQL queue engines track
locked_attimestamps to automatically reclaim orphaned jobs when workers crash, preventing silent pipeline starvation. - SSR Error Isolation: Loader and rendering crashes return HTTP 500 with
X-Robots-Tag: noindex, nofollowand suppress client bundle script tags, preventing client-side hydration thrashing and search engine poisoning. - Secure HttpOnly Cookie Propagation: Actions can set cookies via
ctx.setCookie('name', 'val', { httpOnly: true, secure: true }), which Synapse propagates in RPC response headers viaSet-Cookie. - Graceful Shutdown:
synapse startandserver.stop(drainTimeoutMs)drain in-flight connections within a 5-second window during rolling deployments and container restarts.
🧠 Dual Cognitive Architecture: SynapseJS + Jev System One
Software engineering with autonomous AI coding agents (Claude, Cursor, Windsurf, Antigravity) faces two systemic pitfalls:
- System 2 Structural Friction: Layered architectures scatter code across 5 to 7 directories, forcing agents to burn 15,000+ context tokens on hallucinated imports and cross-file coordination. SynapseJS eliminates this with Locality of Behavior ($N = 1$) and contiguous vertical slices (
*.slice.tsx). - System 1 Cognitive Waste: When an agent encounters a transient environment failure, missing dependency, or trivial syntax issue, standard autoregressive LLMs waste tens of thousands of tokens in circular "deep thought" loops trying to refactor already-working business logic.
SynapseJS pairs natively with Jev System One to provide the industry's first dual-cognitive framework for AI-assisted engineering:
┌────────────────────────────────────────────────────────────────────────┐
│ AGENT / CODING LLM │
└───────────────────▲────────────────────────────────▲───────────────────┘
│ │
[Reflex Decisions & Gating] [Execution & Locality N=1]
│ │
┌───────────────────┴────────────────┐ ┌────────────┴───────────────────┐
│ JEV-HARNESS │ │ SYNAPSEJS │
│ (System 1 Reflex) │ │ (System 2 Structure) │
├────────────────────────────────────┤ ├────────────────────────────────┤
│ • Semantic decisions in 70-300ms │ │ • Locality of Behavior (N = 1) │
│ • Local heuristics (< 500µs) │ │ • Vertical slices (*.slice.tsx)│
│ • Non-autoregressive test-gate │ │ • Fast-Check PBT oracles │
│ • Circular loop abort-check │ │ • Zero-Leak AST Splitter │
│ • Astra-Jev reasoning modulation │ │ • Native MCP Server (18 tools) │
│ • Zero-token waste on env failures │ │ • Slices DDL & auto migrations │
└────────────────────────────────────┘ └────────────────────────────────┘
⚡ Non-Autoregressive Test Gating (synapse test --gate)
When executing property test oracles, the --gate flag (or presence of .jev.json) triggers immediate non-autoregressive triage:
# Run slice oracles with Jev System One semantic triage
bun run synapse test --gate
If a test fails due to environment or missing dependencies, Jev System One flags skipLlm = true with high confidence ($>0.85$), prescribing deterministic fixes (e.g. bun install) without wasting tens of thousands of LLM reasoning tokens:
{
"operation": "PBT_ORACLE_TEST_SUITE",
"status": "FAIL",
"triage": {
"category": "env_missing",
"confidence": 1.0,
"skipLlm": true,
"skipLlmProb": 0.86,
"severityScore": 0.73,
"actionRecommendation": "AUTO-ACTION: Install missing dependency or check environment configuration (Do NOT call LLM)."
}
}
🛡️ Zero-Config Offline Fallback
When no remote Jev endpoint or API key is configured, Jev-Harness seamlessly falls back to sub-millisecond local deterministic heuristics (<500µs), guaranteeing that your local builds, Git pre-commit hooks, and CI/CD pipelines never stall or fail.
📖 For complete architectural specifications, Astra-Jev reasoning modulation, and provider configurations, see docs/jev-integration.md.
🤖 Built for AI Coding Agents: Native Model Context Protocol (MCP)
SynapseJS is the first framework built from day one to be consumed and operated by autonomous AI agents (Cursor, Claude Code, Windsurf, Antigravity).
Instead of forcing an LLM to blindly grep thousands of files, SynapseJS exposes 18 native MCP tools over stdio JSON-RPC 2.0:
bun run mcp
Add to your Agent Config (claude_desktop_config.json / cursor.json)
{
"mcpServers": {
"synapsejs": {
"command": "bunx",
"args": ["synapse", "mcp"],
"cwd": "/path/to/your/synapse-project"
}
}
}
The 18 Native MCP Tools
📊 Empirical Benchmarks & Measured Evidence
To eliminate vaporware, all metrics below are generated by automated benchmark scripts included in this repository:
1. Concurrency: three arms, measured by the run (bun run bench:concurrency)
The script boots the reference application with its slices discovered (it refuses to run when zero are found), and drives three arms with a load generator that runs in a separate process:
SYNAPSE_CONCURRENCY_BENCHMARK — examples/enterprise-crm, 3 slices, 300 requests/arm at concurrency 20
baseline-static-json (not comparable: no render, no database)
throughput 48797.91 req/s · p50 0.28 ms · p95 1.53 ms · p99 1.71 ms · errors 0
ssr-render (loader + component + shell)
throughput 4261.13 req/s · p50 3.45 ms · p95 13.51 ms · p99 18.13 ms · errors 0
rpc-persisted-write (action + SQLite write)
throughput 3413.91 req/s · p50 2.96 ms · p95 21.37 ms · p99 21.84 ms · errors 0
Does not measure: multi-instance behaviour, PostgreSQL, real network latency.
The numbers come from one run on one host: they are a measurement, not a specification. Re-run the
script for your machine. The baseline-static-json arm is a floor and is not comparable to the
framework arms — it renders nothing and touches no database. The rate limiter is widened for the
run, so the arms measure rendering and persistence rather than the allowance.
2. Context Surface Benchmark (bun run bench)
Two identical features ("open ticket", "assign ticket") implemented as vertical slices versus
conventional layering. The app columns cover each application's own feature files and are the
comparable ones; the total columns cover different file sets per repository and are not
comparable — the quoted reduction is the app column (1,832 → 1,627 tokens, ~11%):
3. Test Suite Pass Rate
568 pass
0 fail
1637 expect() calls
Ran 568 tests across 70 files. (100% Green Gates)
🛠️ CLI Reference
All CLI commands output machine-parsable JSON to stdout with exit codes (0 for PASS, 1 for FAIL):
# Development & Production Server
synapse dev [port] [--watch] # Starts dev server with auto-discovery & live migrations
synapse start [port] # Starts production server with graceful shutdown (SIGTERM)
# Diagnostics & Safety
synapse check [file] # Machine diagnostics with exact line/col coordinates
synapse split # Partitions all slices into shared, server, and client modules
synapse test [--gate] # Executes Fast-Check property test oracles (with optional Jev System 1 gating)
# Database & Migrations
synapse migrate # Applies pending slice DDL statements idempotently
synapse rollback [slice] [--steps] # Transactionally rolls back migrations matching down blocks
synapse db-drift # Compares live database schema against slice DDL ASTs
synapse impact <target> # Calculates blast radius across FKs, tables, and imports
# Code Generation & AI
synapse new-slice <domain> <name> # Scaffolds vertical slice (templates: create, list, crud, login, 2fa, oauth)
synapse new-shared <name> # Scaffolds shared domain module in src/shared/<name>.ts with transaction pattern
synapse skeleton # Regenerates .codebase/repo-map.d.ts & .codebase/db-schema.d.ts
synapse mcp # Starts native Model Context Protocol stdio server (18 tools incl. Jev System One)
synapse build [--standalone] # Pre-builds client micro-bundles or standalone release
synapse worker # Starts continuous background jobs queue worker
synapse contract [--markdown] # Emits framework authoring contract specifications
📦 Production Deployment & Docker
Standalone Production Build
Compile your application into a self-contained, standalone production package:
synapse build --standalone
Emits pre-compiled server entry points and client bundles to .synapse/standalone/.
Docker Image
docker build -t my-synapse-app .
docker run -p 3000:3000 -e SYNAPSE_SESSION_SECRET="your-secret" my-synapse-app
- Image Size: ~90MB (Alpine Linux + Bun).
- Security: Runs under unprivileged user
bun.
⚖️ Engineering Integrity & Radical Candor
- Bun Exclusivity: SynapseJS leverages native Bun APIs (
bun:sqlite,Bun.serve,Bun.CryptoHasher,Bun.password,Bun.build). It does not run on Node.js or Deno. - Query Builder Scope: Optimized for single-table transactions and relational joins. Complex multi-table OLAP queries belong in tagged SQL (
db.sql) or dedicated tools like Kysely viactx.services. - Application-Level Multi-Tenancy: Tenant isolation is deterministically enforced at the application boundary via
requireTenantand signed session tokens. For PostgreSQL deployments with strict database-level isolation, Row Level Security (RLS) policies are recommended. - Realtime Scope: Supports both lightweight Server-Sent Events (SSE) via
EventHub/useSubscriptionfor push notifications, and full-duplex persistent WebSockets (defineSocket/useWebSocket) for high-frequency interactive streaming. - Fail-Closed Security by Default: Actions created with
defineActionreject unauthenticated callers by default (UNAUTHORIZED). Open endpoints must explicitly declareauth: 'public'. The server runtime includes CORS origin filtering, CSRF protection, and HMAC-signed session cookie validation (SYNAPSE_SESSION_SECRET). - Declarative Migration DAG: Slice table dependencies and foreign keys are parsed into an acyclic dependency graph (
orderSlicesByDag) to ensure parents are created before child tables. Incremental schema alterations across running production databases should be sequenced as declarative migration statements.
📄 License & Author
Released under the MIT License.
Created by Ismael Soilet. Built for resilient, machine-verifiable, human-auditable software engineering.