SPA + Backend Architecture
Use this architecture when you have a separate frontend team or an existing React/Vue/Angular application.
When to Choose SPA + Backend
Section titled “When to Choose SPA + Backend”- Separate frontend and backend codebases
- Existing React/Vue/Angular application
- Different deployment strategies for frontend/backend
- Frontend team prefers their own tooling
Project Setup
Section titled “Project Setup”Create the API:
npx create-velox-app my-apiCreate your SPA separately (Vite, Create React App, Next.js, etc.):
npm create vite@latest my-frontend -- --template react-tsBackend: VeloxTS API
Section titled “Backend: VeloxTS API”import { procedures, procedure } from '@veloxts/velox';import { z } from '@veloxts/velox';
export const productProcedures = procedures('products', { listProducts: procedure() .output(z.array(ProductSchema)) .query(({ ctx }) => ctx.db.product.findMany()),
getProduct: procedure() .input(z.object({ id: z.string() })) .output(ProductSchema) .query(({ input, ctx }) => ctx.db.product.findUniqueOrThrow({ where: { id: input.id }, })),});Frontend: Type-Safe Client
Section titled “Frontend: Type-Safe Client”Install the VeloxTS client:
cd my-frontendpnpm add @veloxts/clientCreate a typed client:
import { createClient } from '@veloxts/client';import type { productProcedures } from '../../api/src/procedures/products';
type AppProcedures = { products: typeof productProcedures;};
export const api = createClient<AppProcedures>({ baseUrl: 'http://localhost:3030/api',});Use in components:
import { useEffect, useState } from 'react';import { api } from '../api/client';
export function ProductList() { const [products, setProducts] = useState<Product[]>([]);
useEffect(() => { api.products.listProducts().then(setProducts); }, []);
return ( <ul> {products.map(p => <li key={p.id}>{p.name}</li>)} </ul> );}CORS Configuration
Section titled “CORS Configuration”Enable CORS for your frontend origin:
import { veloxApp } from '@veloxts/velox';
const app = veloxApp({ cors: { origin: ['http://localhost:5173'], // Vite default credentials: true, },});React Query Integration
Section titled “React Query Integration”For better data fetching, use the React hooks:
import { createVeloxHooks } from '@veloxts/client/react';import { api } from './client';
export const { useQuery, useMutation } = createVeloxHooks({ client: api });
// In componentconst { data: products, isLoading } = useQuery( ['products'], () => api.products.listProducts());Next Steps
Section titled “Next Steps”- Client Package - Full client reference
- Authentication - Add auth
- REST Conventions - API patterns