Vite + Node Server Integration

Vite is a fast frontend build tool, not a server API runtime. To use CopyPatch with a Vite-built React frontend, mount the CopyPatch backend in the Node.js server that hosts your application and API.

Express Integration

Use expressMiddleware(backend) from @copypatch/node to mount the handler.

server.ts (Express)
import express from 'express';
import { createCopyPatchBackend } from '@copypatch/backend';
import { expressMiddleware } from '@copypatch/node';
import { createSQLitePersistence } from '@copypatch/storage-sqlite';

const app = express();
const persistence = createSQLitePersistence('./data/copypatch.sqlite');
await persistence.migrate();

const backend = createCopyPatchBackend({
  persistence,
  passphraseHash: process.env.COPYPATCH_PASSPHRASE_HASH!,
});

// CRITICAL: Mount CopyPatch BEFORE express.json() / body-parsers and SPA catch-all fallbacks
app.use('/__copypatch/api/v2', expressMiddleware(backend));

// Host application body parsers & routes
app.use(express.json());
app.use(express.static('dist'));

// SPA Fallback
app.get('*', (req, res) => {
  res.sendFile('dist/index.html', { root: '.' });
});

app.listen(3000, () => {
  console.log('App running on http://localhost:3000');
});
Critical Middleware Order: Always mount expressMiddleware(backend) before any body-parsing middleware (such as express.json() or bodyParser.urlencoded()) and before the SPA wildcard route (app.get('*')). CopyPatch requires the unconsumed incoming request stream.

Hono Integration

Hono handles native standard Web Request/Response objects:

server.ts (Hono)
import { Hono } from 'hono';
import { serve } from '@hono/node-server';
import { createHonoHandler } from '@copypatch/node';
import { backend } from './lib/copypatch';

const app = new Hono();

// Mount CopyPatch at canonical v2 path
app.all('/__copypatch/api/v2/*', createHonoHandler(backend));

serve(app, (info) => {
  console.log(`Listening on http://localhost:${info.port}`);
});

Fastify Integration

Fastify leverages request.raw and reply.hijack():

server.ts (Fastify)
import Fastify from 'fastify';
import { fastifyCopyPatchHandler } from '@copypatch/node';
import { backend } from './lib/copypatch';

const fastify = Fastify();

// Fastify uses request.raw and reply.hijack(); register before content parsers
fastify.all('/__copypatch/api/v2/*', fastifyCopyPatchHandler(backend));

await fastify.listen({ port: 3000 });

Why Not a Vite Dev Proxy?

Do not configure a cross-origin reverse proxy in vite.config.ts for CopyPatch. CopyPatch v2 enforces strict same-origin security:

  • Mutating requests require an exact same-origin Origin header matching the host domain.
  • Session cookies are configured with SameSite=Strict and HttpOnly.
  • For local development, run your Node server with Vite in middleware mode (see examples/vite-node) so the React app and API share the exact same http://localhost:3000 origin.