react-node
Skill2 starsChanged 5 months agoMITView on GitHub
Conventions for a React frontend talking to a Node.js backend (Express / Fastify / Hono). Invoke when the atlas shows both a React web framework AND a Node API in the same repo or sibling repos, or when designing the frontend↔backend contract, auth flow, file upload, or WebSocket upgrade. Covers REST-vs-tRPC, JWT-in-httpOnly-cookie rotation, multipart upload, ws handshake, SSR-vs-CSR decision.
In this repository60 other files it gives its agents.
- .claude/CLAUDE.mdCLAUDE.md
- CLAUDE.mdCLAUDE.md
- analyzeSkill
- animation-disciplineSkill
- api-versioningSkill
- autopilotSkill
- browser-e2eSkill
- characterizeSkill
- clarifySkill
- codemodSkill
- constitution-compactSkill
- constitutionSkill
- context-budgetSkill
- creative-webSkill
- db-migrationSkill
- debugSkill
- detect-stackSkill
- dispatch-criteriaSkill
- dreamSkill
- experimentSkill
- fastapiSkill
- flag-cleanupSkill
- flag-rolloutSkill
- flask-realtimeSkill
- framework-detectorSkill
- front-end-designSkill
- grill-meSkill
- handoffSkill
- image-generationSkill
- implementSkill
- initiativeSkill
- instinctSkill
- loopSkill
- nextjsSkill
- observabilitySkill
- okr-alignSkill
- parallel-swarmSkill
- pivotSkill
- planSkill
- pr-bodySkill
- prime-disciplineSkill
- prod-observabilitySkill
- react-viteSkill
- release-trainSkill
- researchSkill
- reviewSkill
- security-guardSkill
- self-healSkill
- shipSkill
- skill-creatorSkill
- specifySkill
- tailwind-disciplineSkill
- tasksSkill
- tdd-loopSkill
- token-budgetSkill
- typographySkill
- verify-loopSkill
- verifySkill
- wip-checkpointSkill
- <kebab-case-skill-name>Skill
The file
We split this skill into the rules it gives an agent
8 rules. About 0 are common, 5 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈5
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 16
tRPC: when both ends are TS and shipped together (monorepo) → end-to-end types, no codegen.
- Distinctive: line 17
REST + OpenAPI: when the backend has non-TS clients, or you want CDN cache + standard tooling.
- Distinctive: line 18
GraphQL: only when the client genuinely composes multiple resources per view (rare) — otherwise it's overhead.
- Very specific: line 20
CSRF: SameSite=Lax covers most: Add a double-submit token if you allow SameSite=None (cross-site SPA → API).
- Very specific: line 21
File uploads: stream, don't buffer: Use multer (Express) / @fastify/multipart with attachFieldsToBody: false → stream to S3/disk.
- Very specific: line 22
REST → WebSocket upgrade: keep the HTTP server, attach ws (or socket.io) on the same port via the upgrade event.
- Distinctive: line 27
Express: when there's an existing ecosystem you must reuse.
- Distinctive: line 28
NestJS: only if your team genuinely wants Angular-style DI/decorators on the server.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
React + Node.js
When to invoke
- Atlas
frameworks.webin {Next.js, Vite-React, Remix} ANDframeworks.apiin {Express, Fastify, Hono, NestJS, tRPC}. - User asks about "frontend talks to backend", "auth flow", "session cookies", "ws upgrade", "file upload", or "SSR vs CSR".
Key conventions
- Contract choice — pick once, document in an ADR.
- tRPC when both ends are TS and shipped together (monorepo) → end-to-end types, no codegen.
- REST + OpenAPI when the backend has non-TS clients, or you want CDN cache + standard tooling. Generate the TS client from the spec.
- GraphQL only when the client genuinely composes multiple resources per view (rare) — otherwise it's overhead.
- Auth: JWT (short access) + rotating refresh, both in
httpOnly; Secure; SameSite=Laxcookies. Never store tokens in localStorage. Refresh rotation: server invalidates the old refresh token on use; reuse → revoke all sessions for that family. - CSRF: SameSite=Lax covers most. Add a double-submit token if you allow
SameSite=None(cross-site SPA → API). Use the framework's CSRF middleware (@fastify/csrf-protection,csurfis unmaintained — usecsrf-csrf). - File uploads: stream, don't buffer. Use
multer(Express) /@fastify/multipartwithattachFieldsToBody: false→ stream to S3/disk. Reject > N MB at the proxy (nginx/CloudFront), not in app. Validate MIME by reading magic bytes (file-type), not theContent-Typeheader. - REST → WebSocket upgrade: keep the HTTP server, attach
ws(orsocket.io) on the same port via theupgradeevent. Authenticate the WS handshake by reading the same session cookie — never put the JWT in the query string (it ends up in access logs). - SSR vs CSR: SSR (Next.js / Remix) by default for content-heavy / SEO-sensitive pages. CSR (Vite-React SPA) when it's an internal tool or fully gated app. Don't bolt SSR onto a finished Vite SPA — migrate to a framework that has it.
- Backend framework choice:
- Hono for edge runtimes (Cloudflare Workers, Bun, Deno) — Web-standard
Request/Response. - Fastify for high-throughput Node — schema-first, faster than Express, plugin model.
- Express when there's an existing ecosystem you must reuse. New code: prefer Hono or Fastify.
- NestJS only if your team genuinely wants Angular-style DI/decorators on the server.
- Hono for edge runtimes (Cloudflare Workers, Bun, Deno) — Web-standard
- Shared types: a
packages/shared/(orapps/api/contracts/) folder exports types consumed by both ends. With tRPC, this is free. With REST, generate from OpenAPI.
Canonical structure (monorepo, pnpm + turbo)
apps/
web/ # React (Vite or Next.js)
api/ # Node (Fastify or Hono)
src/
routes/ # one file per resource
plugins/ # auth, cors, rate-limit
lib/db.ts # Prisma / Drizzle client
lib/auth.ts # JWT signing, cookie helpers
ws/ # socket handlers
server.ts # entrypoint
packages/
shared/ # zod schemas, types, error codes
ui/ # if shared components
turbo.json
pnpm-workspace.yamlCommon pitfalls
- JWT in
localStorage— exfiltrated by any XSS. AlwayshttpOnlycookie. - No refresh rotation — refresh tokens long-lived + non-rotating → one leak = forever access. Rotate on every use, detect reuse, revoke the family.
- CORS too permissive in dev leaks to prod.
Access-Control-Allow-Origin: *with credentials is rejected by browsers — but devs often set both to silence the error. Explicit allowlist, env-driven. - Multipart body parser on every route. Mount it only on the upload route. Otherwise every POST allocates buffers.
- WS auth race: client connects before the cookie is set. Solve by gating the WS connection on a successful
/meREST call, not on app boot.
References
- tRPC: https://trpc.io
- OWASP JWT cheat sheet: https://cheatsheetseries.owasp.org/cheatsheets/JSON_Web_Token_for_Java_Cheat_Sheet.html
- Refresh-token rotation: https://auth0.com/docs/secure/tokens/refresh-tokens/refresh-token-rotation
- Fastify: https://fastify.dev
- Hono: https://hono.dev
- ws upgrade: https://github.com/websockets/ws#external-https-server
Hello world (login → ws upgrade)
// apps/api/src/routes/auth.ts (Fastify)
app.post('/login', { schema: { body: LoginSchema } }, async (req, reply) => {
const user = await verify(req.body)
const access = signAccess({ sub: user.id }, '15m')
const refresh = await issueRefresh(user.id) // rotates a family id
reply
.setCookie('access', access, { httpOnly: true, secure: true, sameSite: 'lax', path: '/' })
.setCookie('refresh', refresh, { httpOnly: true, secure: true, sameSite: 'lax', path: '/auth/refresh' })
.send({ ok: true })
})
// apps/api/src/ws/index.ts
server.on('upgrade', async (req, sock, head) => {
const user = await userFromCookie(req.headers.cookie)
if (!user) return sock.destroy()
wss.handleUpgrade(req, sock, head, ws => wss.emit('connection', ws, user))
})Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

