Full-stack RSC Architecture
Use this architecture for complete web applications with a unified codebase, server rendering, and streaming.
When to Choose Full-stack RSC
Section titled “When to Choose Full-stack RSC”- Building a complete web application
- Want unified frontend + backend codebase
- Need SSR and streaming
- Prefer React Server Components model
Project Setup
Section titled “Project Setup”npx create-velox-app my-app --rsc# or with authenticationnpx create-velox-app my-app --rsc-authHow It Works
Section titled “How It Works”VeloxTS uses Vinxi as the HTTP handler, with Fastify embedded for API routes:
Browser Request ↓ Vinxi ├── /api/* → Fastify (tRPC + REST) ├── /_build/* → Static Assets └── /* → RSC RendererProject Structure
Section titled “Project Structure”my-app/├── app/│ ├── pages/ # File-based routing│ │ ├── index.tsx # /│ │ ├── about.tsx # /about│ │ └── users/│ │ ├── index.tsx # /users│ │ └── [id].tsx # /users/:id│ ├── layouts/│ │ └── root.tsx # Root layout│ └── actions/ # Server actions│ └── users.ts├── api/│ └── procedures/ # Backend procedures├── app.config.ts # Vinxi configuration└── package.jsonFile-Based Routing
Section titled “File-Based Routing”Pages in app/pages/ map to routes:
| File | Route |
|---|---|
index.tsx | / |
about.tsx | /about |
users/index.tsx | /users |
users/[id].tsx | /users/:id |
posts/[...slug].tsx | /posts/* (catch-all) |
Server Components
Section titled “Server Components”Pages are Server Components by default:
import { db } from '@/api/database';
export default async function UsersPage() { const users = await db.user.findMany();
return ( <div> <h1>Users</h1> <ul> {users.map(user => ( <li key={user.id}>{user.name}</li> ))} </ul> </div> );}Server Actions
Section titled “Server Actions”Call backend procedures from server actions:
'use server';
import { validated } from '@veloxts/web/server';import { CreateUserSchema } from '@/api/schemas/user';
export const createUser = validated(CreateUserSchema, async (input) => { const user = await db.user.create({ data: input }); return { success: true, user };});Use in forms:
import { createUser } from '@/app/actions/users';
export default function NewUserPage() { return ( <form action={createUser}> <input name="name" required /> <input name="email" type="email" required /> <button type="submit">Create User</button> </form> );}Layouts
Section titled “Layouts”Wrap pages with layouts:
export default function RootLayout({ children }) { return ( <html> <body> <nav>...</nav> <main>{children}</main> </body> </html> );}Next Steps
Section titled “Next Steps”- Server Actions - Validated mutations
- File Routing - Route patterns
- Layouts - Layout system