pattern-engineer-ssr
Skill0 starsChanged 5 months agoMITView on GitHub
SSR/hybrid framework bullets (Next.js App Router, SvelteKit/Remix/Nuxt): only `NEXT_PUBLIC_` env reaches the client (not a security boundary), guard `.server.ts` modules; `use client` at the leaf; fetch at the route boundary not `useEffect`; validate+re-auth+revalidate in server actions; declare render mode; hydration-safe (no `Date.now()`/`window`); no module-level request state; Suspense; never `try/catch` a `redirect()`. Activate on `app/` files, server components, loaders/actions.
- Reads credentials
In this repository74 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- create-bug-issueSkill
- create-enhancement-issueSkill
- create-feature-issuesSkill
- dream-summary-memorySkill
- memory-conventionSkill
- operation-gitSkill
- pattern-architect-api-endpointSkill
- pattern-architect-data-modelSkill
- pattern-architect-deep-moduleSkill
- pattern-e2e-coding-standardSkill
- pattern-engineer-apiSkill
- pattern-engineer-backend-standardSkill
- pattern-engineer-coding-standardSkill
- pattern-engineer-containerSkill
- pattern-engineer-databaseSkill
- pattern-engineer-fastapiSkill
- pattern-engineer-frontend-standardSkill
- pattern-engineer-goSkill
- pattern-engineer-javaSkill
- pattern-engineer-kotlinSkill
- pattern-engineer-nodeSkill
- pattern-engineer-non-functionalSkill
- pattern-engineer-observabilitySkill
- pattern-engineer-pythonSkill
- pattern-engineer-rustSkill
- pattern-engineer-securitySkill
- pattern-engineer-swiftSkill
- pattern-engineer-typescriptSkill
- pattern-engineer-viteSkill
- pattern-exploratory-testingSkill
- pattern-reviewer-apiSkill
- pattern-reviewer-backend-standardSkill
- pattern-reviewer-coding-standardSkill
- pattern-reviewer-containerSkill
- pattern-reviewer-contractSkill
- pattern-reviewer-databaseSkill
- pattern-reviewer-fastapiSkill
- pattern-reviewer-frontend-standardSkill
- pattern-reviewer-goSkill
- pattern-reviewer-javaSkill
- pattern-reviewer-kotlinSkill
- pattern-reviewer-nodeSkill
- pattern-reviewer-non-functionalSkill
- pattern-reviewer-observabilitySkill
- pattern-reviewer-pythonSkill
- pattern-reviewer-rustSkill
- pattern-reviewer-securitySkill
- pattern-reviewer-ssrSkill
- pattern-reviewer-swiftSkill
- pattern-reviewer-test-coverageSkill
- pattern-reviewer-typescriptSkill
- pattern-reviewer-viteSkill
- pattern-test-coverageSkill
- principle-engineer-tddSkill
- scaffold-projectSkill
- workflow-architect-interviewSkill
- workflow-designer-sample-pagesSkill
- workflow-design-interviewSkill
- workflow-e2e-authorSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
10 rules. About 0 are common, 2 are distinctive, and 8 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
8
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 16
After loading this skill, also check $MAIN_ROOT/.claude/memory/patterns/pattern-engineer-ssr.md in the consuming project (resolve …
- Very specific: line 22
Only public-prefixed env vars reach the client bundle: NEXT_PUBLIC_* (Next), $env/static/public + PUBLIC_ (SvelteKit), runtimeConfig.public …
- Very specific: line 24
Read server-only secrets from process env in server code only (process.env.X, SvelteKit $env/static/private / $env/dynamic/private, Nuxt …
- Very specific: line 31
Only serializable props cross the boundary — no functions, class instances, Dates-as-objects, or Symbols passed from server to client.
- Very specific: line 37
Use the framework's request-level dedupe/cache (Next fetch cache + cache(), Nuxt payload, SvelteKit load dedupe) instead of a hand-rolled …
- Very specific: line 48
Don't let an incidental cookies()/headers() call or a cache: "no-store" fetch silently flip a page to dynamic — if it must be dynamic, say …
- Distinctive: line 58
No module-level mutable state holding user/request data — the server runtime is shared across all requests.
- Very specific: line 59
Read request context through framework APIs (cookies(), headers(), draftMode() in Next.
- Very specific: line 64
Don't serially await every fetch at the top of the page.
- Distinctive: line 81
Test client components with React Testing Library (or the framework's component harness).
≈ “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
pattern-engineer-ssr
Server-rendered and hybrid frontend frameworks have a hard server/client boundary that pure-CSR apps don't. These bullets own that boundary, the rendering modes, and the request-scoped data flow — the concerns unique to SSR. Next.js App Router is the primary exemplar; SvelteKit, Remix / React Router 7, and Nuxt idioms are noted parenthetically where the spelling differs.
When to activate
Activate when editing files under app/ (Next.js App Router), pages/ API/data files, React Server Components or "use client" modules, Remix / React Router 7 loader/action exports, SvelteKit +page.server.ts / +page.ts / +layout.server.ts, Nuxt useAsyncData/useFetch/server/ routes, anything reading NEXT_PUBLIC_* / $env/* / runtimeConfig, or configuring rendering mode (export const dynamic/revalidate). Skip for pure-CSR Vite apps — pattern-engineer-vite owns those (no SSR/SSG/SEO/server components). TS rules → pattern-engineer-typescript; generic UI → pattern-engineer-frontend-standard; auth/secrets depth → pattern-engineer-security.
Project memory overlay
After loading this skill, also check $MAIN_ROOT/.claude/memory/patterns/pattern-engineer-ssr.md in the consuming project (resolve MAIN_ROOT="$(dirname "$(git rev-parse --path-format=absolute --git-common-dir)")"). If present, load it as an additive overlay to the rules below; if absent, skip silently. See memory-convention for the full contract (additivity, severity floor, conflict surfacing).
Patterns
Server/client env + module boundary
- Only public-prefixed env vars reach the client bundle:
NEXT_PUBLIC_*(Next),$env/static/public+PUBLIC_(SvelteKit),runtimeConfig.public(Nuxt). Everything unprefixed stays server-side. - The public prefix is NOT a security boundary — every prefixed value is statically inlined into the shipped JS and trivially extractable. Only public values (API URLs, feature flags, publishable keys) get it; secrets never.
- Read server-only secrets from process env in server code only (
process.env.X, SvelteKit$env/static/private/$env/dynamic/private, NuxtruntimeConfig.x) — never imported into a client component. - Guard server-only modules so they can't be bundled to the client:
import "server-only"at the top, the.server.tsfilename convention (Remix / SvelteKit), or keep them underserver/. A client import then fails the build instead of leaking.
The "use client" boundary
- Push
"use client"to the leaf interaction component (the button, the form, the chart), not the page/layout root — everything above stays a server component. - Server components fetch and compose; client components handle state, effects, and event handlers.
- Only serializable props cross the boundary — no functions, class instances, Dates-as-objects, or Symbols passed from server to client. (Remix/SvelteKit: same —
loader/loadreturn must serialize.)
Data fetching at the route boundary
- Fetch first-render data at the route boundary: the server component body, Remix/RR7
loader, SvelteKitload, NuxtuseAsyncData/useFetch. Never a clientuseEffectfetch for data needed on first paint. - Parallelize independent fetches (
Promise.all, parallelawaits) — don't serially chain unrelated requests. - Use the framework's request-level dedupe/cache (Next
fetchcache +cache(), Nuxt payload, SvelteKitloaddedupe) instead of a hand-rolled module-level cache.
Mutations
- Mutate through the framework's server primitive: Next server actions / route handlers, Remix/RR7
action, SvelteKit form actions, Nuxtserver/apiroutes. - Validate input AND re-check authn/authz server-side on every mutation — client state is untrusted, a hidden field or disabled button proves nothing.
- Revalidate after a successful mutation so cached reads reflect the write:
revalidatePath/revalidateTag(Next),invalidateAll(SvelteKit),refreshNuxtData(Nuxt), or return fresh data from the Remixaction.
Rendering mode
- Choose static / ISR / dynamic per route deliberately and declare it explicitly —
export const dynamic,export const revalidate,fetch(..., { next: { revalidate } })(Next); SvelteKitprerender/ssr/csrpage options; NuxtrouteRules. - Don't let an incidental
cookies()/headers()call or acache: "no-store"fetch silently flip a page to dynamic — if it must be dynamic, say so; if it shouldn't be, remove the trigger.
Hydration safety
- Server and client must render identically. No
Date.now(),Math.random(),new Date()formatting, or locale-/timezone-dependent output during render without a stable passed-in input. - Browser-only APIs (
window,document,localStorage,navigator) only inside effects (useEffect/onMount) or behind a mounted guard — never in the render path. suppressHydrationWarningis a last resort (e.g. an intentional timestamp) and needs a comment explaining why the mismatch is expected.
Per-request isolation
- No module-level mutable state holding user/request data — the server runtime is shared across all requests; a module-scoped variable leaks one user's data to the next.
- Read request context through framework APIs (
cookies(),headers(),draftMode()in Next;event.locals/cookiesin SvelteKit;eventin Nuxt) — never via globals or singletons.
Streaming
- Wrap slow data in a Suspense /
defer(Remixdefer, SvelteKit streamed promises) boundary with a meaningful fallback skeleton — fast content paints immediately. - Don't serially
awaitevery fetch at the top of the page; that blocks the whole response on the slowest call.
Control-flow helpers throw
redirect(),notFound()(Next), SvelteKiterror()/redirect(), Remixredirect()throw — never wrap them in atry/catchthat swallows the thrown value, or the navigation silently dies. Re-throw or call them outside thetry.
Auth cookies
- Set auth/session cookies via the framework's response cookie API as
httpOnly(Nextcookies().set, SvelteKitcookies.set, NuxtsetCookie) — never store the session token in client-readable state or non-httpOnlycookies. (Deeper auth substance →pattern-engineer-security.)
SEO metadata
- Emit metadata via the framework metadata API on server-rendered pages:
generateMetadata/metadataexport (Next),<svelte:head>(SvelteKit),useSeoMeta/useHead(Nuxt) — not a client-sidedocument.titlemutation.
Testing
- Unit-test
loader/action/route handlers as plain functions (call them with a fake request, assert the returned data/response). - Test client components with React Testing Library (or the framework's component harness).
- The hydration path (server render → client takeover) belongs to E2E, not unit tests.
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.

