About Spiceflow Framework
Spiceflow Framework is an MCP server published by remorses in the Developer Tools category: minimal API & React framework, fully type safe, OpenAPI, RSC, MCP, type safe client, streaming with SSE.
The repository has 168 stars and 7 forks, with the last commit 4 days ago. Recent commit activity is the strongest signal that reported issues will get attention.
Install
git clone https://github.com/remorses/spiceflowThis server has no ConduID identity, so agent calls to it are not receipted. Pin the version you install and review the source before granting it credentials.
Ask AI
Ask AI about Spiceflow Framework
Powered by Claude · Grounded in docs
Security checks
Static checks derived from the repository 21 hours ago. Heuristics on the source, not an audit.
- ✓README presentThe repository ships documentation.
- ✓License declaredUsable under a stated license.
- ✓Tests presentA test suite exists in the repository.
- ✓Dependencies pinnedA lockfile pins dependency versions.
- !No dynamic code executionSource scan found eval or shell execution. Review how tool inputs reach it before granting credentials.
- !Scoped permissionsDoesn't declare a permission scope. Assume it can do anything its process can.
Releases
README
Spiceflow is a type-safe API framework and full-stack React RSC framework focused on absolute simplicity. It works across all JavaScript runtimes: Node.js, Bun, and Cloudflare Workers. Read the source code on GitHub. Full documentation lives at getspiceflow.com.
Features
- Full-stack React framework with React Server Components (RSC), server actions, layouts, and automatic client code splitting
- Works everywhere: Node.js, Bun, and Cloudflare Workers with the same code
- Type safe schema based validation via Zod
- Type safe fetch client with full inference on path params, query, body, and response
- Simple and intuitive API using web standard Request and Response
- Can easily generate OpenAPI spec based on your routes
- Support for Model Context Protocol to easily wire your app with LLMs
- Supports async generators for streaming via server sent events
- Modular design with
.use()for mounting sub-apps - Built-in OpenTelemetry tracing with zero overhead when disabled
Installation
npm install spiceflow@rsc
[!IMPORTANT] Spiceflow is still in pre-release. Install with
spiceflow@rsc, notspiceflow@latest.
AI Agents
To let your AI coding agent know how to use spiceflow, run:
npx -y skills add remorses/spiceflow -g -y
Every documentation page is also available as raw markdown: append .md to any getspiceflow.com URL, for example https://getspiceflow.com/react-data.md.
Basic Usage
API routes return JSON automatically. React pages use .page() and .layout() for server-rendered UI with client interactivity:
import { Spiceflow } from 'spiceflow'
import { Counter } from './counter'
export const app = new Spiceflow()
.get('/api/hello', () => {
return { message: 'Hello, World!' }
})
.layout('/*', async ({ children }) => {
return (
<html>
<body>{children}</body>
</html>
)
})
.page('/', async () => {
return (
<div>
<h1>Home</h1>
<Counter />
</div>
)
})
.page('/about', async () => {
return <h1>About</h1>
})
app.listen(3000)
Use .route() instead of .get()/.post() when you want to pass Zod schemas for validation — it accepts request, response, query, and params schemas.
Two Ways to Use Spiceflow
Spiceflow works as a standalone API framework or as a full-stack React framework — same router, same type safety, same code.
API only — no Vite, no React. Just install spiceflow and build type-safe APIs with Zod validation, streaming, OpenAPI, and a type-safe fetch client:
import { Spiceflow } from 'spiceflow'
const app = new Spiceflow()
.get('/hello', () => ({ message: 'Hello!' }))
app.listen(3000)
Full-stack React (RSC) — add the Vite plugin to get server components, client components, layouts, server actions, and automatic code splitting. All API features still work alongside React pages:
// vite.config.ts
import react from '@vitejs/plugin-react'
import { defineConfig } from 'vite'
import spiceflow from 'spiceflow/vite'
export default defineConfig({
plugins: [react(), spiceflow({ entry: './src/main.tsx' })],
})
How a Spiceflow App Works
Everything is one chained expression on a single Spiceflow instance: API routes, middleware, loaders, layouts, and pages. The chain is the source of truth for both runtime routing and TypeScript inference — the typed fetch client, router.href(), and useLoaderData() all read their types from typeof app.
new Spiceflow() ── one chain, one type
│
┌─────────────────────┼──────────────────────┐
v v v
.get / .post .use(middleware) .loader / .layout / .page
.route (Zod) serveStatic, cors React Server Components
JSON + SSE APIs mounted sub-apps server actions, client chunks
│ │ │
└─────────────────────┼──────────────────────┘
v
app.listen(3000) / app.handle(request)
Node.js <──────> Bun <──────> Cloudflare Workers
For the React side, Vite builds three environments from the same entry: rsc (server components and actions), ssr (HTML rendering), and client (hydration and navigation). Every "use client" file automatically becomes its own browser chunk. Server actions marked "use server" become POST endpoints that re-render the page with fresh data after they run.
A realistic app entry looks like this:
// src/main.tsx
import { Spiceflow, parseFormData } from 'spiceflow'
import { Head, Link, router } from 'spiceflow/react'
import { z } from 'zod'
import { Counter } from './app/counter'
export const app = new Spiceflow()
.get('/api/hello', () => ({ message: 'Hello!' }))
.loader('/dashboard/*', async ({ request }) => {
const user = await getUser(request)
return { user }
})
.layout('/*', async ({ children }) => {
return (
<html>
<Head>
<Head.Meta charSet="UTF-8" />
</Head>
<body>{children}</body>
</html>
)
})
.page('/dashboard', async ({ loaderData }) => {
return (
<div>
<h1>Welcome {loaderData.user.name}</h1>
<Counter />
<Link href={router.href('/')}>Home</Link>
</div>
)
})
.listen(3000)
// Register the app type for type-safe routing everywhere
declare module 'spiceflow/react' {
interface SpiceflowRegister { app: typeof app }
}
Static pages run middleware
.staticPage() renders a page once at build time into .html and .rsc files. On Node.js and Cloudflare Workers, middleware registered with .use() still runs before every static page request, so redirects, auth checks, and response headers work on static pages too:
export const app = new Spiceflow()
.use(({ request, redirect }) => {
if (new URL(request.url).pathname === '/about-us') throw redirect('/about')
})
.staticPage('/about', async () => <About />)
On Cloudflare Workers the prerendered files are stored where only the Worker can read them, so Cloudflare never serves them before your middleware. Add an ASSETS binding in wrangler.jsonc; the Worker runs your .use() blocks, then returns the stored file without rendering again. See Cloudflare prerendered pages.
Middleware also runs while vite build prerenders the page. That request has no cookies or user headers, so a middleware that redirects it makes the build fail.
Documentation
The README is only an overview. The full documentation is split into feature docs — always read the doc for the feature you are working on before writing code. The API is small but opinionated, and the opinions are not guessable from other frameworks.
API framework
| When you work on | Read |
|---|---|
Routes, Zod validation, typed errors, middleware, static files, CORS, streaming/SSE, .onError(), noStackTraces, listen(), waitUntil, Node.js adapters, Next.js mounting, base path |
API Framework |
| Calling the API with the typed fetch client, WebMCP browser tools | Fetch Client |
| Generating OpenAPI documents, response maps, hiding routes | OpenAPI |
| Exposing routes as LLM tools over Model Context Protocol | MCP |
| OpenTelemetry spans, Server-Timing, custom tracers | Tracing and Strada |
Sending non-JSON types (Date, Map, Set, BigInt) over the wire |
Custom Serialization |
React framework (RSC)
| When you work on | Read |
|---|---|
Vite setup, Tailwind, shadcn/ui, app entry, layouts, <Head> SEO, query params, client components, code splitting, router, Link, redirects, 404 pages |
React Framework |
Loaders, useLoaderData, streaming with use(), forms, server actions, parseFormData, useActionState, ErrorBoundary |
Data & Actions |
The SpiceflowRegister type registry, knownPaths, multi-app workspaces |
Type-Safe Routing |
| Rendering remote components from another server | Federation |
Guides
| When you work on | Read |
|---|---|
| Writing vitest tests for routes, pages, and server actions | Testing |
| Auth middleware, proxying, non-blocking auth, cookie patterns, graceful shutdown | Middleware Patterns |
| Authenticating server actions and routes — they are public endpoints | Security |
| Porting an app from Remix or React Router | Migrate from Remix |
| How Spiceflow compares to Next.js, Hono, and Elysia | Comparisons |
| Installing and structuring shadcn/ui components | shadcn/ui |
A dependency crashing with useState is undefined at startup |
use client trap |
Deployment
| When you deploy to | Read |
|---|---|
Cloudflare Workers: setup, bindings, waitUntil, KV caching, edge cache |
Cloudflare |
| Any host, to understand what happens across deploys | Deployment Skew |
| Cloudflare service bindings between Workers | Service Bindings |
| Docker or any container platform | Docker |
Testing
Test your spiceflow app directly with vitest. No browser, no build step, sub-second feedback. Call the app through the typed fetch client, call server actions as plain functions, and assert on responses:
import { createSpiceflowFetch } from 'spiceflow/client'
import { SpiceflowTestResponse } from 'spiceflow/testing'
import { app } from './main.js'
const f = createSpiceflowFetch(app)
// API routes return typed JSON
const data = await f('/api/hello')
expect(data).toEqual({ message: 'Hello, World!' })
// Page routes return SpiceflowTestResponse with rendered HTML
const res = await f('/about')
if (!(res instanceof SpiceflowTestResponse)) throw new Error('expected page')
expect(await res.text()).toContain('About')
The spiceflow Vite plugin auto-detects vitest and configures everything. See the Testing guide for authentication patterns, stateful workflows, and dependency injection.
Comparisons
Spiceflow is a full React RSC framework, not only an API layer. Same app can serve JSON, pages, layouts, server actions, and OpenAPI.
Hono and Elysia are HTTP frameworks. Next.js is a React platform with file-based App Router caching. Spiceflow is both a typed API and a React app in one chain. Every request re-runs matching layouts. No static/dynamic split.
See Comparisons for Next.js, Hono, and Elysia in detail.
README fetched from the repository 21 hours ago. The original is authoritative.