Skip to content

fxylabs/spfn

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1,232 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Superfunction (SPFN)

Type-safe backend for Next.js

Next.js handles your frontend. SPFN handles your backend.

📖 superfunction.xyz — docs, package guides, and a full-stack tutorial.

npm core npm auth npm cms npm cli License

Status — Beta (0.x). SPFN is in active development and runs in production for its authors. The public API is stabilizing, but may still change between minor releases before 1.0 — pin your versions and skim the CHANGELOG before upgrading. Install from the @beta tag, e.g. npm i @spfn/core@beta.


When You Need SPFN

Building a mobile app? → Next.js (landing page) + SPFN (API) = Complete solution

Building a SaaS product? → Next.js (marketing + dashboard) + SPFN (backend) = Full-stack

Need these features?

  • Complex business logic with transactions
  • Connection pools (PostgreSQL, Redis)
  • Background jobs & scheduled tasks
  • End-to-end type safety
  • Authentication & CMS out of the box

If you just need simple API routes, Next.js is enough. If you need a real backend, Next.js + SPFN.


Quick Start

# Create new project
npx spfn@beta create my-app
cd my-app

# Start databases
docker compose up -d

# Start dev server
npm run spfn:dev

✅ Backend: http://localhost:8790 ✅ Frontend: http://localhost:3790


How It Works

1. Define Routes

// src/server/routes/users.ts
import { route } from '@spfn/core/route';
import { Type } from '@sinclair/typebox';

export const listUsers = route.get('/users')
    .input({
        query: Type.Object({
            limit: Type.Optional(Type.Number()),
        }),
    })
    .handler(async (c) => {
        const { query } = await c.data();
        return { users: [], limit: query.limit ?? 10 };
    });

export const getUser = route.get('/users/:id')
    .input({
        params: Type.Object({
            id: Type.String(),
        }),
    })
    .handler(async (c) => {
        const { params } = await c.data();
        return { id: params.id, name: 'John' };
    });

export const createUser = route.post('/users')
    .input({
        body: Type.Object({
            name: Type.String(),
            email: Type.String(),
        }),
    })
    .handler(async (c) => {
        const { body } = await c.data();
        return { id: '1', ...body };
    });

2. Register Router

// src/server/router.ts
import { defineRouter } from '@spfn/core/route';
import { listUsers, getUser, createUser } from './routes/users';

export const appRouter = defineRouter({
    listUsers,
    getUser,
    createUser,
});

export type AppRouter = typeof appRouter;

The typed client needs no codegen. The RPC proxy that forwards browser calls to the SPFN server does — run pnpm codegen to (re)generate the route map after changing routes.

// src/lib/api-client.ts — the typed client (metadata-free)
import { createApi } from '@spfn/core/nextjs';
import type { AppRouter } from '@/server/router';

export const api = createApi<AppRouter>();
// src/app/api/rpc/[routeName]/route.ts — forwards api.*.call() to the SPFN server
import { createRpcProxy } from '@spfn/core/nextjs/server';
import { routeMap } from '@/generated/route-map';   // generated by `pnpm codegen`

export const { GET, POST } = createRpcProxy({ routeMap });
// app/page.tsx — fully typed call, no manual types
import { api } from '@/lib/api-client';

export default async function Page() {
    const { users } = await api.listUsers.call({ query: { limit: 10 } });
    const user = await api.getUser.call({ params: { id: '123' } });

    return <div>{users.length} users</div>;
}

Core Features

Type-safe Routes

  • Chainable API: route.get().input().handler()
  • TypeBox validation
  • Metadata-free typed client; RPC proxy resolves routes from a generated map

Database

  • Drizzle ORM with helpers
  • Transaction support (AsyncLocalStorage)
  • Repository pattern

Authentication (@spfn/auth)

  • JWT sessions
  • RBAC (roles & permissions)
  • Email/SMS verification

CMS (@spfn/cms)

  • Type-safe labels
  • Version control
  • Multi-locale support

Storage (@spfn/storage)

  • Provider-agnostic object storage (S3 / GCS / local)
  • Upload, download, and deletion APIs

Notifications (@spfn/notification)

  • Multi-channel: Email, SMS, Slack, Push

Monitoring (@spfn/monitor)

  • Error tracking, log management, dashboard

Project Structure

src/
├── server/
│   ├── router.ts           # defineRouter — the API contract
│   ├── server.config.ts    # Server configuration
│   ├── routes/             # route.get/post/... definitions
│   ├── entities/           # Drizzle database schemas
│   └── repositories/       # Data access layer
├── generated/
│   └── route-map.ts        # produced by `pnpm codegen`
├── lib/
│   └── api-client.ts       # createApi<AppRouter>() — typed client
└── app/
    ├── api/rpc/[routeName]/route.ts   # RPC proxy → SPFN server
    └── page.tsx            # Next.js pages

Ecosystem

Package Version Description
@spfn/core Beta Routing, DB, Transactions
spfn Beta CLI & Dev tools
@spfn/auth Beta Authentication & RBAC
@spfn/cms Beta Content Management
@spfn/storage Beta Object storage (S3 / GCS / local)
@spfn/notification Beta Email, SMS, Slack, Push notifications
@spfn/monitor Beta Error tracking & monitoring dashboard
@spfn/migrate Beta Code-based data migrations with a run-once ledger
@spfn/pages Beta Serve a markdown site from a GitHub repo
@spfn/pages-next Beta Next.js integration for @spfn/pages
@spfn/i18n Beta Small server and React internationalization runtime
@spfn/mcp Beta Official-SDK-based MCP route adapter
@spfn/workflow Alpha Pipeline orchestration

Install Packages

# Auth
npm i @spfn/auth@beta

# CMS
npm i @spfn/cms@beta

Using Auth

// src/server/router.ts
import { defineRouter } from '@spfn/core/route';
import { authRouter, authenticate } from '@spfn/auth/server';

export const appRouter = defineRouter({
    // your routes...
})
.packages([authRouter])
.use([authenticate]);

Requirements

  • Node.js >= 18.18.0
  • Next.js >= 15.1.9 or >= 16.0.7 (patched for CVE-2025-66478)
  • PostgreSQL 14+

Documentation

Every package has a deep-dive README in packages/ — see the table above.


Contributing

Contributions are welcome. See CONTRIBUTING.md for setup, the development workflow, and the PR checklist — and AGENTS.md if you work with an AI coding agent. By participating you agree to our Code of Conduct.

Found a security issue? Please report it privately — see SECURITY.md.


License

MIT © FXY Inc.

About

Type-safe backend framework for Next.js: Drizzle entities, repositories, typed routes, and an auto-generated end-to-end client. PostgreSQL + Redis built in.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages