RS

remorses/spiceflow

Developer tools
169 stars 7 forks Quality 69 Trend 31MIT

Minimal API & React framework, fully type safe, OpenAPI, RSC, MCP, type safe client, streaming with SSE

Overview

spiceflow type safe API and React Server Components framework for Node, Bun, and Cloudflare 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-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 .

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, not spiceflow@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 (
      
        {children}
      
    )
  })
  .page('/', async () => {
    return (
      
    )
  })
  .page('/about', async () => {
    return About
  })

app.listen(3000)

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 (
      
        
          
        
        {children}
      
    )
  })
  .page('/dashboard', async ({ loaderData }) => {
    return (
      
    )
  })
  .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 () => )

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, `` 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.

View the full README on GitHub

Install

npx -y skills add remorses/spiceflow -g -y
New to MCP? Start with the mcpskill.org guide →