architecture-rules.ko.md
# 아키텍처 규칙 참조
> hypercore TanStack Start 프로젝트를 위한 rule taxonomy와 blocking gate 요약입니다.
일부 규칙은 공식 TanStack default보다 엄격합니다. 모든 규칙은 다음 중 하나로 이해해야 합니다:
- **Official** — TanStack이 요구하거나 문서화한 동작.
- **Safety policy** — 보안/런타임 correctness를 위한 local blocking rule.
- **Hypercore convention** — 공식 default를 넘어설 수 있는 local/team preference.
Brownfield 적용: touched files는 해당 safety rules와 현재 hypercore conventions를 만족해야 합니다. 손대지 않은 legacy style drift는 safety boundary issue가 아닌 한 migration backlog로 기록할 수 있습니다.
## Source Priority
1. `references/official/current-docs-2026-06-02.ko.md`
2. `references/official/tanstack-start-2026-04-30.ko.md`
3. `references/official/tanstack-router-2026-04-30.ko.md`
4. `references/official/api-drift-notes.ko.md`
5. `rules/` 아래 topic rules
6. Installed versions가 다르면 project-local package types와 tests
## Blocking Safety Gates
| Surface | Classification | Block 또는 fix 조건 |
|---|---|---|
| Loader boundaries | Official + Safety policy | Loader가 server-only execution을 가정하거나 secrets/DB/filesystem을 직접 읽음 |
| Server functions | Official + Safety policy | Mutation input이 runtime에 validate되지 않거나 handler가 없거나 installed package/API version을 따르지 않거나 auth-required RPC가 자체 auth boundary를 갖지 않음 |
| Import protection | Official + Safety policy | Import protection을 disable하거나 config를 overwrite하거나 server/client-only imports가 compiler-recognized boundaries 밖으로 leak됨 |
| Middleware | Official + Safety policy | Client `sendContext`를 runtime validation 없이 server-side에서 trust함 |
| SSR/hydration | Official + Safety policy | Stabilization/fallback strategy 없이 first render에 unstable values 포함 |
| Server routes | Official + Hypercore convention | Explicit justification 없이 internal app RPC를 server functions 대신 server routes로 구현 |
| Route export | Official | File routes가 route instance를 `Route`로 export하지 않음 |
| Route organization | Hypercore convention | Touched app pages가 flat files를 쓰거나 필요한 route-local hooks/components를 생략하거나 route-local `-functions/`를 server function 기본 위치처럼 취급 |
| Project structure | Official + Hypercore convention + Safety policy | Review가 custom route root를 무시하거나, `routeTree.gen.ts`를 수동 편집하거나, shared folder convention을 official law처럼 취급하거나, server-only shared code를 client에 노출하거나, server function wrapper/helper를 섞음 |
| Hooks | Hypercore convention | Touched interactive page/component logic이 `-hooks/`로 이동하지 않고 inline으로 남음 |
| Code style | Hypercore convention | Touched files가 camelCase filenames, `any`, function declarations, missing return types를 쓰거나 required Korean block comments를 생략 |
## Layer Architecture
```text
Route/Page UI
-> route-local hooks / TanStack Query
-> optional route-local -functions/<resource>.functions.ts
또는 modules/<domain>/<feature>/<resource>.functions.ts
-> modules/<domain>/<feature>/<resource>.server.ts
-> lib/<domain>, db/<domain> repositories,
또는 integrations/<provider> server-only clients
-> database/ 또는 external SDK
```
Rules:
- **Safety policy:** Routes는 ORM/database clients를 직접 import하면 안 됩니다.
- **Hypercore convention:** Server functions는 사소하지 않은 business logic에 대해 domain module/lib layer code를 호출해야 합니다.
- **Hypercore convention:** 추출이 오히려 noise를 늘리는 단순 CRUD는 server function 안에 남아도 됩니다.
- **Safety policy:** Auth-required server function은 route `beforeLoad`만 믿지 않고 middleware 또는 handler-level auth check를 가져야 합니다.
- **Hypercore convention + Safety policy:** `*.functions.ts`는 `createServerFn` wrapper entrypoint, `*.server.ts`는 privileged helper로 분리하고 mixed barrel을 만들지 않습니다.
## Official-vs-Hypercore Clarifications
- TanStack Router는 flat, directory, mixed route structures를 공식 지원합니다. Hypercore는 app pages에 route directories를 선호합니다.
- TanStack Start docs는 `src/routes`, `src/router.tsx`, generated `src/routeTree.gen.ts`, `public/`, root `vite.config.ts`를 typical project shape로 보여줍니다. nested `src/modules`, `src/lib`, `src/integrations`와 비슷한 shared folders는 Hypercore/repo-local conventions입니다.
- TanStack Start import protection은 기본 활성화됩니다. Hypercore는 project-specific deny rules가 필요할 때 explicit extension을 요구합니다.
- TanStack Start server function wrapper는 static import 가능한 RPC entrypoint입니다. 큰 앱에서는 `.functions.ts` wrapper와 `.server.ts` server-only helper를 분리하는 official guidance를 Hypercore `src/modules/<domain>/<feature>/` convention으로 적용합니다.
- Zod v4와 함께 쓰는 TanStack Router는 schema를 `validateSearch`에 직접 전달할 수 있습니다. Zod v3는 `@tanstack/zod-adapter`를 사용합니다.
- Server routes는 공식 Start feature입니다. Hypercore는 internal app RPC가 아니라 HTTP semantics 용도로 제한합니다.
- Publishing-only static pages는 `-hooks/`, `-components/`, `-functions/`가 필요 없습니다. Interactive UI가 커지면 `-hooks/` 또는 `-components/`를 추가하고, route-only server action일 때만 `-functions/`를 추가합니다.
## Topic Files
- `rules/project-structure.md` — Start project shape, route-root discovery, generated route tree, shared nested folder grouping, route-local/shared server function placement.
- `rules/routes.md` — route organization, route lifecycle, search params, folder policy.
- `rules/services.md` — server functions, validation, query/mutation layering.
- `rules/hooks.md` — hook extraction and `useServerFn` wrapper policy.
- `rules/import-protection.md` — marker files, deny rules, compiler-boundary leaks.
- `rules/middleware.md` — middleware types, context propagation, `sendContext` validation.
- `rules/execution-model.md` — isomorphic/default execution model.
- `rules/server-routes.md` — server route allowlist and justifications.
- `rules/ssr-hydration.md` — SSR modes and hydration stability.
- `rules/platform.md` — router/env/alias/operational setup.
- `rules/validation.md` — final readback and trigger/resource checks.
## Auto-Remediation Policy
Issue가 local, reversible, low-risk이면 직접 auto-fix합니다:
- Interactive logic 또는 extracted UI가 있는 page에 missing route-local hooks/components 추가.
- Unrelated config를 overwrite하지 않고 custom `importProtection` deny rules를 추가 또는 확장.
- `getRouter()` fresh-instance router setup 추가.
- Marker imports 또는 explicit `createServerOnlyFn` / `createClientOnlyFn` boundaries 추가.
- Untrusted server function input 또는 `sendContext`에 runtime validation 추가.
명확한 user request 없이 broad 또는 potentially breaking migrations를 자동 적용하지 않습니다:
- Mass route/file renames.
- Sweeping server route to server function migrations.
- 여러 route에 걸친 SSR mode changes.
- Alias-wide import rewrites.
- Database schema edits 또는 migration commands.
## Common Mistakes To Fix In Touched Files
| Mistake | Preferred fix |
|---|---|
| `const Route = createFileRoute(...)` | `export const Route = createFileRoute(...)` |
| `loader`를 server-only로 취급 | Privileged work를 `createServerFn` / `createServerOnlyFn` 뒤로 이동 |
| Zod v4 search params를 adapter에 강제로 통과 | Project convention이 adapter를 요구하지 않으면 direct schema 사용 |
| Zod v3 search params에 adapter/fallback 없음 | `@tanstack/zod-adapter`의 `zodValidator` / `fallback` 사용 |
| Runtime validation 없는 server function mutation | `.handler(...)` 전에 `.inputValidator(...)` 추가 |
| Auth-required server function이 route `beforeLoad`만 의존 | server function middleware 또는 handler-level auth check 추가 |
| `*.functions.ts`가 DB/secret helper를 handler 밖 surviving export에서 참조 | `*.server.ts`로 split하고 handler 내부 boundary로 이동 |
| `src/modules/<domain>/<feature>/index.ts`가 `.functions.ts`와 `.server.ts`를 함께 export | barrel 제거 또는 safe/server-only entrypoint 분리 |
| Server-function-only middleware behavior에 `createMiddleware()` 사용 | `createMiddleware({ type: 'function' })` 사용. Request middleware는 `createMiddleware()` 유지 |
| Server/client imports가 environments 사이로 leak | File split, marker 추가, environment function wrapping |
| Static publishing page에 empty folders 강제 | Interactive UI, extracted sections, route-only server action이 생길 때까지 route-local folder를 추가하지 않음 |
| Server route 아래 internal app RPC | HTTP semantics가 필요하지 않으면 server function 선호 |
## Completion Rule
`rules/validation.md`가 통과하고 남은 official API ambiguity가 exact date와 source로 기록되어야 change가 complete입니다.
architecture-rules.md
# Architecture Rules Reference
> Rule taxonomy and blocking gate summary for hypercore TanStack Start projects.
Some rules are stricter than official TanStack defaults. Every rule should be understood as one of:
- **Official** — required or documented by TanStack.
- **Safety policy** — local blocking rule for security/runtime correctness.
- **Hypercore convention** — local/team preference that may exceed official defaults.
Brownfield adoption: touched files must satisfy applicable safety rules and current hypercore conventions. Untouched legacy style drift can be logged as migration backlog unless it creates a safety boundary issue.
## Source Priority
1. `references/official/current-docs-2026-06-02.md`
2. `references/official/tanstack-start-2026-04-30.md`
3. `references/official/tanstack-router-2026-04-30.md`
4. `references/official/api-drift-notes.md`
5. Topic rules under `rules/`
6. Project-local package types and tests when installed versions differ
## Blocking Safety Gates
| Surface | Classification | Block or fix when |
|---|---|---|
| Loader boundaries | Official + Safety policy | A loader assumes server-only execution or reads secrets/DB/filesystem directly |
| Server functions | Official + Safety policy | Mutation input is not validated at runtime, handler is missing, installed package/API version is not respected, or auth-required RPC lacks its own auth boundary |
| Import protection | Official + Safety policy | Import protection is disabled, config is overwritten, or server/client-only imports leak outside compiler-recognized boundaries |
| Middleware | Official + Safety policy | Client `sendContext` is trusted server-side without runtime validation |
| SSR/hydration | Official + Safety policy | First render includes unstable values without a stabilization/fallback strategy |
| Server routes | Official + Hypercore convention | Internal app RPC is implemented as server routes instead of server functions without explicit justification |
| Route export | Official | File routes do not export the route instance as `Route` |
| Route organization | Hypercore convention | Touched app pages use flat files, omit needed route-local hooks/components, or treat route-local `-functions/` as the default server-function home |
| Project structure | Official + Hypercore convention + Safety policy | Review ignores custom route roots, hand-edits `routeTree.gen.ts`, treats shared folder conventions as official law, exposes server-only shared code to clients, or mixes server function wrappers/helpers |
| Hooks | Hypercore convention | Touched interactive page/component logic remains inline instead of moving to `-hooks/` |
| Code style | Hypercore convention | Touched files use camelCase filenames, `any`, function declarations, missing return types, or omit required Korean block comments |
## Layer Architecture
```text
Route/Page UI
-> route-local hooks / TanStack Query
-> optional route-local -functions/<resource>.functions.ts
or modules/<domain>/<feature>/<resource>.functions.ts
-> modules/<domain>/<feature>/<resource>.server.ts
-> lib/<domain>, db/<domain> repositories,
or integrations/<provider> server-only clients
-> database/ or external SDK
```
Rules:
- **Safety policy:** Routes must not import ORM/database clients directly.
- **Hypercore convention:** Server functions should call domain module/lib layer code for non-trivial business logic.
- **Hypercore convention:** Simple CRUD may remain in a server function only when extracting a module/lib layer would add noise.
- **Safety policy:** Auth-required server functions must not rely only on route `beforeLoad`; use middleware or handler-level auth checks.
- **Hypercore convention + Safety policy:** Split `*.functions.ts` `createServerFn` wrapper entrypoints from `*.server.ts` privileged helpers and avoid mixed barrels.
## Official-vs-Hypercore Clarifications
- TanStack Router officially supports flat, directory, and mixed route structures. Hypercore prefers route directories for app pages.
- TanStack Start docs show `src/routes`, `src/router.tsx`, generated `src/routeTree.gen.ts`, `public/`, and root `vite.config.ts` as the typical project shape; nested `src/modules`, `src/lib`, `src/integrations`, and similar shared folders are Hypercore/repo-local conventions.
- TanStack Start import protection is enabled by default. Hypercore requires explicit extension when project-specific deny rules are needed.
- TanStack Start server function wrappers are static-importable RPC entrypoints. Hypercore applies the official larger-app split between `.functions.ts` wrappers and `.server.ts` server-only helpers inside the `src/modules/<domain>/<feature>/` convention.
- TanStack Router with Zod v4 can pass schemas directly to `validateSearch`; Zod v3 uses `@tanstack/zod-adapter`.
- Server routes are an official Start feature; hypercore reserves them for HTTP semantics, not internal app RPC.
- Publishing-only static pages do not require `-hooks/`, `-components/`, or `-functions/`. Add `-hooks/` or `-components/` when interactive UI grows; add `-functions/` only for route-only server actions.
## Topic Files
- `rules/project-structure.md` — Start project shape, route-root discovery, generated route tree, shared nested folder grouping, and route-local/shared server function placement.
- `rules/routes.md` — route organization, route lifecycle, search params, folder policy.
- `rules/services.md` — server functions, validation, query/mutation layering.
- `rules/hooks.md` — hook extraction and `useServerFn` wrapper policy.
- `rules/import-protection.md` — marker files, deny rules, compiler-boundary leaks.
- `rules/middleware.md` — middleware types, context propagation, `sendContext` validation.
- `rules/execution-model.md` — isomorphic/default execution model.
- `rules/server-routes.md` — server route allowlist and justifications.
- `rules/ssr-hydration.md` — SSR modes and hydration stability.
- `rules/platform.md` — router/env/alias/operational setup.
- `rules/validation.md` — final readback and trigger/resource checks.
## Auto-Remediation Policy
Auto-fix directly when the issue is local, reversible, and low-risk:
- Add missing route-local hooks/components for pages with interactive logic or extracted UI.
- Add or extend custom `importProtection` deny rules without overwriting unrelated config.
- Add `getRouter()` fresh-instance router setup.
- Add marker imports or explicit `createServerOnlyFn` / `createClientOnlyFn` boundaries.
- Add runtime validation for untrusted server function input or `sendContext`.
Do not auto-apply broad or potentially breaking migrations without a clear user request:
- Mass route/file renames.
- Sweeping server route to server function migrations.
- SSR mode changes across many routes.
- Alias-wide import rewrites.
- Database schema edits or migration commands.
## Common Mistakes To Fix In Touched Files
| Mistake | Preferred fix |
|---|---|
| `const Route = createFileRoute(...)` | `export const Route = createFileRoute(...)` |
| Treating `loader` as server-only | Move privileged work behind `createServerFn` / `createServerOnlyFn` |
| Zod v4 search params forced through adapter | Use direct schema unless project convention says adapter |
| Zod v3 search params without adapter/fallback | Use `zodValidator` / `fallback` from `@tanstack/zod-adapter` |
| Server function mutation without runtime validation | Add `.inputValidator(...)` before `.handler(...)` |
| Auth-required server function relies only on route `beforeLoad` | Add server function middleware or handler-level auth check |
| `*.functions.ts` references DB/secret helpers from a surviving export outside the handler | Split to `*.server.ts` and move usage inside handler boundary |
| `src/modules/<domain>/<feature>/index.ts` exports both `.functions.ts` and `.server.ts` | Remove barrel or split safe/server-only entrypoints |
| `createMiddleware()` with server-function-only middleware behavior | Use `createMiddleware({ type: 'function' })`; keep request middleware on `createMiddleware()` |
| Server/client imports leaking across environments | Split file, add marker, or wrap in environment function |
| Static publishing page forced into empty folders | Do not add route-local folders until interactive UI, extracted sections, or route-only server actions exist |
| Internal app RPC under server route | Prefer server function unless HTTP semantics are required |
## Completion Rule
A change is complete only when `rules/validation.md` passes and any remaining official API ambiguity is recorded with exact date and source.
references/official/api-drift-notes.ko.md
# TanStack API Drift Notes
- last_verified_at: 2026-06-09
- purpose: Core skill rules가 stale examples에 과적합하지 않도록 official-doc conflicts와 source-priority decisions를 기록합니다.
## Source Priority
1. 정확한 API area에 대한 current canonical guide.
2. 정확한 symbol에 대한 current API/reference page.
3. Installed project의 package types/source.
4. Rename 또는 migration을 설명하는 recent release notes.
5. Examples, comparisons, migration guides, blog posts.
Sources가 충돌하면 편한 쪽을 조용히 선택하지 않습니다. Exact date와 source links로 conflict를 기록합니다.
## `.inputValidator()` vs stale `.validator()` examples
2026-06-09 기준 결정:
- `createServerFn` input validation의 current official Server Functions guide API는 `.inputValidator(...)`로 취급합니다.
- 오래되었거나 lower-priority content의 `.validator(...)` examples는 project-local installed types가 다르게 증명하지 않는 한 version drift로 취급합니다.
- 실제 project를 편집할 때는 broad migration 전에 installed `@tanstack/react-start` version을 확인합니다.
Evidence:
- Current Server Functions guide는 `.inputValidator(...)`를 사용합니다: <https://tanstack.com/start/latest/docs/framework/react/guide/server-functions>
- Current Middleware guide는 server function middleware-owned data validation에 `.inputValidator(...)`를 사용합니다: <https://tanstack.com/start/latest/docs/framework/react/guide/middleware>
- 일부 오래된 history와 examples는 `.validator(...)`를 언급합니다. 이것들은 current `latest` docs authority가 아니라 drift context로 사용합니다.
Skill implication:
- `rules/services.md`는 current-docs 기반 새 작업에 `.inputValidator(...)`를 권장해야 합니다.
- `rules/middleware.md`는 server function middleware-owned data validation에 `.inputValidator(...)`를 권장해야 합니다.
- Existing project에서는 `.validator(...)`를 바꾸기 전에 package types를 확인합니다. 이 skill은 docs만 근거로 broad API migration을 수행하지 않습니다.
- Core `SKILL.md`는 긴 API history를 반복하지 말고 여기로 안내합니다.
## Server function `.inputValidator()` vs middleware `.inputValidator()`
2026-06-09 기준 결정:
- `createServerFn` input validation과 server-function middleware data validation 모두 current official API는 `.inputValidator(...)`입니다.
- 둘을 혼동하지 않습니다. Method name은 같지만 서로 다른 chain object에 속하고 data/context가 다릅니다.
- Local chain type 확인 없이 server-function example을 근거로 middleware-owned validation을 migrate하거나, middleware example을 근거로 server-function validation을 migrate하지 않습니다.
Evidence:
- Current Server Functions guide는 `.inputValidator(...)`를 사용합니다: <https://tanstack.com/start/latest/docs/framework/react/guide/server-functions>
- Current Middleware guide는 server function middleware validation을 `.inputValidator(...)`로 나열합니다: <https://tanstack.com/start/latest/docs/framework/react/guide/middleware>
Skill implication:
- `rules/services.md`는 server function `.inputValidator(...)` guidance를 담당합니다.
- `rules/middleware.md`는 middleware `.inputValidator(...)`, request middleware `createMiddleware()`, server function middleware `createMiddleware({ type: 'function' })` guidance를 담당합니다.
## Search validation and Zod adapters
2026-04-30 기준 결정:
- Zod v4는 `validateSearch`에서 schema를 직접 사용할 수 있습니다.
- Zod v3는 `@tanstack/zod-adapter`와 `zodValidator`/`fallback`을 사용해야 합니다.
- Project가 adapter를 hypercore convention으로 양쪽 version에 표준화할 수는 있지만, 공식 docs보다 엄격하다고 label해야 합니다.
Evidence:
- <https://tanstack.com/router/latest/docs/how-to/validate-search-params>
- <https://tanstack.com/router/latest/docs/how-to/setup-basic-search-params>
## Import protection defaults
2026-04-30 기준 결정:
- Import protection은 Start에서 기본 활성화됩니다.
- Database/server/client 같은 directories 또는 ORM clients 같은 packages에 additional deny rules가 필요하면 explicit config가 여전히 필요합니다.
- Import protection 비활성화는 명시 요청이 없는 한 blocking safety issue입니다.
Evidence: <https://tanstack.com/start/latest/docs/framework/react/guide/import-protection>
## Official vs Hypercore routing structure
2026-04-30 기준 결정:
- Router는 flat, directory, mixed route file structures를 지원합니다.
- Hypercore의 route-directory preference는 maintainability를 위한 local convention이며 official TanStack behavior로 설명하면 안 됩니다.
Evidence: <https://tanstack.com/router/latest/docs/routing/file-based-routing>
references/official/api-drift-notes.md
# TanStack API Drift Notes
- last_verified_at: 2026-06-09
- purpose: Record official-doc conflicts and source-priority decisions so core skill rules do not overfit stale examples.
## Source Priority
1. Current canonical guide for the exact API area.
2. Current API/reference page for the exact symbol.
3. Package types/source in the installed project.
4. Recent release notes that explain a rename or migration.
5. Examples, comparisons, migration guides, and blog posts.
When sources conflict, do not silently pick the convenient one. Record the conflict with exact date and source links.
## `.inputValidator()` vs stale `.validator()` examples
Decision as of 2026-06-09:
- Treat `.inputValidator(...)` as the current official Server Functions guide API for `createServerFn` input validation.
- Treat `.validator(...)` examples in older or lower-priority content as version drift unless project-local installed types prove otherwise.
- If editing a real project, verify against the installed `@tanstack/react-start` version before making broad migrations.
Evidence:
- Current Server Functions guide uses `.inputValidator(...)`: <https://tanstack.com/start/latest/docs/framework/react/guide/server-functions>
- Current Middleware guide uses `.inputValidator(...)` for server function middleware-owned data validation: <https://tanstack.com/start/latest/docs/framework/react/guide/middleware>
- Some older history and examples mention `.validator(...)`; use them as drift context, not as current `latest` docs authority.
Skill implication:
- `rules/services.md` should recommend `.inputValidator(...)` for new current-docs work.
- `rules/middleware.md` should recommend `.inputValidator(...)` for server function middleware-owned data validation.
- For existing projects, verify package types before replacing `.validator(...)`; this skill should not perform broad API migrations from docs alone.
- The core `SKILL.md` should not repeat long API history; point here instead.
## Server function `.inputValidator()` vs middleware `.inputValidator()`
Decision as of 2026-06-09:
- Treat `.inputValidator(...)` as current official API for both `createServerFn` input validation and server-function middleware data validation.
- Do not conflate the two uses. They share a method name but belong to different chain objects and receive different data/context.
- Do not migrate middleware-owned validation based on server-function examples, or server-function validation based on middleware examples, without checking the local chain type.
Evidence:
- Current Server Functions guide uses `.inputValidator(...)`: <https://tanstack.com/start/latest/docs/framework/react/guide/server-functions>
- Current Middleware guide lists server function middleware validation as `.inputValidator(...)`: <https://tanstack.com/start/latest/docs/framework/react/guide/middleware>
Skill implication:
- `rules/services.md` owns server function `.inputValidator(...)` guidance.
- `rules/middleware.md` owns middleware `.inputValidator(...)`, request middleware `createMiddleware()`, and server function middleware `createMiddleware({ type: 'function' })` guidance.
## Search validation and Zod adapters
Decision as of 2026-04-30:
- Zod v4 can use the schema directly in `validateSearch`.
- Zod v3 should use `@tanstack/zod-adapter` with `zodValidator`/`fallback`.
- A project may standardize on the adapter as a hypercore convention, but that must be labelled as stricter than official docs.
Evidence:
- <https://tanstack.com/router/latest/docs/how-to/validate-search-params>
- <https://tanstack.com/router/latest/docs/how-to/setup-basic-search-params>
## Import protection defaults
Decision as of 2026-04-30:
- Import protection is enabled by default in Start.
- Explicit config is still required when the project needs additional deny rules for directories such as database/server/client or packages such as ORM clients.
- Disabling import protection remains a blocking safety issue unless explicitly requested.
Evidence: <https://tanstack.com/start/latest/docs/framework/react/guide/import-protection>
## Official vs Hypercore routing structure
Decision as of 2026-04-30:
- Router supports flat, directory, and mixed route file structures.
- Hypercore's route-directory preference is a local convention for maintainability and should not be described as official TanStack behavior.
Evidence: <https://tanstack.com/router/latest/docs/routing/file-based-routing>
references/official/current-docs-2026-06-02.ko.md
# TanStack Start Current Docs Snapshot
- checked_at: 2026-06-09
- source: Context7 `/websites/tanstack_start_framework_react`, TanStack 공식 docs pages와 직접 TanStack 공식 페이지 확인 기반
- use_when: Start/Router API behavior, Start Vite plugin config, import protection, execution boundaries, server-function API shape가 architecture decision에 영향을 줄 때
- authority: API 사실은 TanStack 공식 문서가 기준이며, Hypercore convention은 `rules/`에 남긴다.
## 확인한 공식 사실
### Project setup and router
- 공식 build-from-scratch guide에서 `vite.config.ts`는 `@tanstack/react-start/plugin/vite`의 `tanstackStart()`를 사용하고, React Vite plugin은 Start plugin 뒤에 둔다.
- 현재 Getting Started guidance는 TanStack Builder 또는 CLI 경로인 `npx @tanstack/cli@latest create`를 권장한다. 예제에 남은 이전 scaffold command를 현재 primary setup path로 취급하지 않는다.
- `src/router.tsx`는 `getRouter()`를 정의하고 generated `routeTree`를 `./routeTree.gen`에서 import한다.
- `src/routes/__root.tsx`는 root application route이며, `routeTree.gen.ts`는 `npm run dev` 또는 `npm run start` 등 Start 실행 시 자동 생성된다.
- Sources:
- <https://tanstack.com/start/latest/docs/framework/react/getting-started>
- <https://tanstack.com/start/latest/docs/framework/react/build-from-scratch.md>
- <https://tanstack.com/start/latest/docs/framework/react/guide/routing>
### Source and route directory config
- Start project는 흔히 `src/routes`를 사용하지만 architecture review에서는 route root를 가정하기 전에 `tanstackStart()` config를 확인해야 한다.
- 이 스킬의 기존 references는 `srcDirectory`와 `router.routesDirectory`를 configurable Start plugin options로 추적한다. Target project에서 package types 또는 docs가 다르면 local package types와 dated note를 우선한다.
- Source:
- <https://tanstack.com/start/latest/docs/framework/react/build-from-scratch.md>
### Server functions and execution boundaries
- `createServerFn()`은 server functions를 정의한다. GET이 default이며, `createServerFn({ method: 'POST' })`처럼 다른 HTTP method를 지정할 수 있다.
- Server functions는 input validation에 `.inputValidator(...)`를 사용하고 execution에 `.handler(...)`를 사용한다. Current server-function guides는 필요하면 handler 전에 middleware를 둔다.
- Server functions는 app same-origin RPC endpoint로 취급한다. Browser-origin server function requests는 Fetch Metadata, Origin, Referer checks와 CSRF middleware로 보호한다. Custom `src/start.ts`를 정의하면 server function CSRF middleware를 명시적으로 유지해야 한다.
- Server functions는 loaders, components, hooks, other server functions, event handlers에서 호출할 수 있다. Components/hooks에서는 `useServerFn()`와 TanStack Query 조합을 사용할 수 있고, route loaders는 server function을 직접 호출할 수 있다.
- Larger-app file organization guidance는 `*.functions.ts`를 `createServerFn` wrapper, `*.server.ts`를 DB/internal server-only helper, suffix 없는 `.ts`를 client-safe schema/types/constants로 분리한다. Static import of server functions는 safe로 설명되며 dynamic import는 피하라고 경고한다.
- `createServerFn`, `createServerOnlyFn`, `createClientOnlyFn`, `createIsomorphicFn`은 공식 execution-control primitives다.
- Client hooks/components는 server functions를 호출할 수 있으며, hook ergonomics가 필요하면 React wrapper인 `useServerFn`을 사용한다.
- Sources:
- <https://tanstack.com/start/latest/docs/framework/react/guide/server-functions.md>
- <https://tanstack.com/start/latest/docs/framework/react/guide/code-execution-patterns.md>
- <https://tanstack.com/start/latest/docs/framework/react/guide/authentication.md>
### Middleware
- TanStack Start에는 두 middleware type이 있다. Request middleware는 `createMiddleware()`를 사용한다. `createMiddleware({ type: 'request' })`도 가능하지만 request type이 default다.
- Server function middleware는 `createMiddleware({ type: 'function' })`를 사용하며 `.client(...)`와 `.server(...)` phase를 정의할 수 있다.
- Server function middleware input transformation/validation도 `.inputValidator(...)`를 사용한다. Middleware `.inputValidator(...)`와 server-function `.inputValidator(...)`는 다른 chain object와 data context에 속하므로 혼동하지 않는다.
- `sendContext`는 explicit이다. Client middleware에서 server middleware로 보낸 값은 client-provided data로 보고 server-side validation 후 신뢰한다.
- Global request middleware는 `src/start.ts`에서 `createStart(() => ({ requestMiddleware: [...] }))`로 설정한다.
- Source:
- <https://tanstack.com/start/latest/docs/framework/react/guide/middleware>
### Import protection
- Start source files에는 import protection이 기본 활성화되어 있다.
- Development default는 mock/warning behavior이며, production build default는 violation에서 error다.
- 기본 client-side denial은 `*.server.*`와 Start server specifiers를 다루고, 기본 server-side denial은 `*.client.*`를 다룬다. `node_modules`는 check에서 제외된다.
- Type-only imports and re-exports are ignored by import protection because runtime bundle에서 제거된다. Runtime value를 포함한 mixed import는 여전히 검사 대상이다.
- Project-specific import protection은 `tanstackStart({ importProtection: { behavior, client, server } })`로 설정할 수 있다.
- `behavior`는 `behavior: 'error'` 같은 mode 또는 `{ dev: 'mock', build: 'error' }` 같은 per-mode object일 수 있다.
- Current options에는 `enabled`, `behavior`, `log`, `include`, `exclude`, `ignoreImporters`, `maxTraceDepth`, environment-specific `client`/`server` `files`와 `specifiers`, `excludeFiles`, `onViolation`이 포함된다.
- `excludeFiles: []`는 `node_modules`처럼 default가 제외하는 위치의 resolved files를 다시 검사하게 할 수 있지만, false positive를 피하려면 의도적으로만 사용한다.
- 명시적 boundary용 side-effect marker imports는 `@tanstack/react-start/server-only`, `@tanstack/react-start/client-only`다.
- Source:
- <https://tanstack.com/start/latest/docs/framework/react/guide/import-protection>
### Server routes
- Server routes는 route file의 `createFileRoute(...)(...)`에 `server`를 추가해 선언한다.
- 현재 형태는 simple method handlers에는 `server.handlers` object를, middleware composition이 필요한 handlers에는 `createHandlers` function을 사용한다.
- `server.middleware`는 모든 handlers에 route-level middleware를 적용할 수 있다.
- Server routes는 Router file-route convention을 따른다. 같은 route path에서 duplicate HTTP methods는 invalid이며, wildcard/splat routes는 trailing `$` file-route convention을 사용한다.
- Source:
- <https://tanstack.com/start/latest/docs/framework/react/guide/server-routes>
## Drift handling
- 이 파일은 날짜가 있는 official-doc snapshot이며 영구 rulebook이 아니다.
- Local installed package types가 다르면 typecheck를 실행하고 project-specific exception을 기록한다.
- `src/modules`, `src/lib`, `src/db`, `src/server`, `src/integrations`, `src/config` grouping은 official TanStack requirement가 아니라 Hypercore convention으로 유지한다.
- `.functions.ts` / `.server.ts` file split은 official guidance에서 가져온 server function organization pattern이지만, 이를 `src/modules/<domain>/<feature>/` nested folder convention으로 강제하는 것은 Hypercore convention이다.
references/official/current-docs-2026-06-02.md
# TanStack Start Current Docs Snapshot
- checked_at: 2026-06-09
- source: Context7 `/websites/tanstack_start_framework_react`, backed by TanStack official docs pages and direct TanStack official page checks
- use_when: Start/Router API behavior, Start Vite plugin config, import protection, execution boundaries, or server-function API shape affects an architecture decision
- authority: Official TanStack docs for API facts; Hypercore conventions remain in `rules/`
## Official facts confirmed
### Project setup and router
- `vite.config.ts` uses `tanstackStart()` from `@tanstack/react-start/plugin/vite`; the React Vite plugin comes after the Start plugin in the official build-from-scratch guide.
- Current Getting Started guidance recommends TanStack Builder or the CLI path `npx @tanstack/cli@latest create`; older scaffolding commands in examples should not be treated as the primary current setup path.
- `src/router.tsx` defines `getRouter()` and imports the generated `routeTree` from `./routeTree.gen`.
- `src/routes/__root.tsx` is the root application route; `routeTree.gen.ts` is generated automatically when Start runs, including `npm run dev` or `npm run start`.
- Sources:
- <https://tanstack.com/start/latest/docs/framework/react/getting-started>
- <https://tanstack.com/start/latest/docs/framework/react/build-from-scratch.md>
- <https://tanstack.com/start/latest/docs/framework/react/guide/routing>
### Source and route directory config
- Start projects commonly use `src/routes`, but architecture reviews must inspect `tanstackStart()` config before assuming the route root.
- Existing references in this skill track `srcDirectory` and `router.routesDirectory` as configurable Start plugin options. If package types or docs disagree in a target project, prefer local package types plus a dated note.
- Source:
- <https://tanstack.com/start/latest/docs/framework/react/build-from-scratch.md>
### Server functions and execution boundaries
- `createServerFn()` defines server functions. GET is the default; other HTTP methods such as POST can be specified with `createServerFn({ method: 'POST' })`.
- Server functions use `.inputValidator(...)` for input validation and `.handler(...)` for execution; current server-function guides show middleware before the handler when needed.
- Treat server functions as same-origin app RPC endpoints. Browser-origin server function requests are protected with Fetch Metadata, Origin, Referer checks, and CSRF middleware. If a project defines custom `src/start.ts`, it must preserve server function CSRF middleware explicitly.
- Server functions can be called from loaders, components, hooks, other server functions, and event handlers. Components/hooks can use `useServerFn()` with TanStack Query; route loaders can call server functions directly.
- Larger-app file organization guidance splits `*.functions.ts` for `createServerFn` wrappers, `*.server.ts` for DB/internal server-only helpers, and unsuffixed `.ts` for client-safe schemas/types/constants. Static imports of server functions are described as safe; dynamic imports are warned against.
- `createServerFn`, `createServerOnlyFn`, `createClientOnlyFn`, and `createIsomorphicFn` are official execution-control primitives.
- Client hooks/components may call server functions; `useServerFn` is the React wrapper when hook ergonomics are needed.
- Sources:
- <https://tanstack.com/start/latest/docs/framework/react/guide/server-functions.md>
- <https://tanstack.com/start/latest/docs/framework/react/guide/code-execution-patterns.md>
- <https://tanstack.com/start/latest/docs/framework/react/guide/authentication.md>
### Middleware
- TanStack Start has two middleware types. Request middleware uses `createMiddleware()`; `createMiddleware({ type: 'request' })` is allowed but the request type is the default.
- Server function middleware uses `createMiddleware({ type: 'function' })` and can define `.client(...)` and `.server(...)` phases.
- Server function middleware input transformation/validation also uses `.inputValidator(...)`; do not confuse middleware `.inputValidator(...)` with server-function `.inputValidator(...)` because they belong to different chain objects and data contexts.
- `sendContext` is explicit. Values sent from client middleware to server middleware must be treated as client-provided data and validated server-side before trust.
- Global request middleware is configured through `createStart(() => ({ requestMiddleware: [...] }))` in `src/start.ts`.
- Source:
- <https://tanstack.com/start/latest/docs/framework/react/guide/middleware>
### Import protection
- Import protection is enabled by default for Start source files.
- Development defaults use mock/warning behavior; production build defaults error on violations.
- Default client-side denial covers `*.server.*` and Start server specifiers; default server-side denial covers `*.client.*`; `node_modules` are excluded from these checks.
- Type-only imports and re-exports are ignored by import protection because they are erased from the runtime bundle; mixed imports still count when they include runtime values.
- Project-specific import protection can be configured with `tanstackStart({ importProtection: { behavior, client, server } })`.
- `behavior` can be a mode such as `behavior: 'error'` or a per-mode object such as `{ dev: 'mock', build: 'error' }`.
- Current options include `enabled`, `behavior`, `log`, `include`, `exclude`, `ignoreImporters`, `maxTraceDepth`, environment-specific `client`/`server` `files` and `specifiers`, `excludeFiles`, and `onViolation`.
- `excludeFiles: []` can opt an environment back into checking resolved files under locations that defaults exclude, such as `node_modules`, but this should be used deliberately to avoid false positives.
- Side-effect marker imports remain available for explicit boundaries: `@tanstack/react-start/server-only` and `@tanstack/react-start/client-only`.
- Source:
- <https://tanstack.com/start/latest/docs/framework/react/guide/import-protection>
### Server routes
- Server routes are declared in route files by adding `server` to `createFileRoute(...)(...)`.
- The current shape uses a `server.handlers` object for simple method handlers or a `createHandlers` function for handlers that need middleware composition.
- `server.middleware` can apply route-level middleware to all handlers.
- Server routes follow Router file-route conventions; duplicate route paths with duplicate HTTP methods are invalid, and wildcard/splat routes use the trailing `$` file-route convention.
- Source:
- <https://tanstack.com/start/latest/docs/framework/react/guide/server-routes>
## Drift handling
- Treat this file as a dated official-doc snapshot, not a permanent rulebook.
- If local installed package types disagree, run typecheck and record the project-specific exception.
- Keep `src/modules`, `src/lib`, `src/db`, `src/server`, `src/integrations`, and `src/config` grouping as Hypercore conventions, not official TanStack requirements.
- The `.functions.ts` / `.server.ts` split is an official server-function organization pattern; enforcing that split inside `src/modules/<domain>/<feature>/` nested folders is a Hypercore convention.
references/official/tanstack-router-2026-04-30.ko.md
# TanStack Router 공식 스냅샷
- last_verified_at: 2026-04-30
- packages_checked:
- `@tanstack/react-router`: `1.168.26`
- Context7 indexed version observed: repository docs는 `v1_114_3`, live latest docs와 cross-check함.
- source_priority: latest docs pages > API pages > examples
Route, search, loader, context, SSR rules에 Router behavior가 영향을 줄 때 이 파일을 사용합니다.
## 이 Skill에서 사용하는 공식 사실
### File routes and `Route` export
- File-based routes는 `createFileRoute(path)(options)`로 configure합니다.
- Generated file route instance는 `tsr generate`와 `tsr watch`가 올바르게 동작하도록 `Route` identifier로 export해야 합니다.
- Sources:
- <https://tanstack.com/router/latest/docs/api/router/createFileRouteFunction>
- <https://tanstack.com/router/latest/docs/routing/routing-concepts>
### Flat and directory routes
- Router는 directory routes, flat routes, mixed flat/directory structures를 공식 지원합니다.
- Hypercore가 app pages에 route directories를 선호할 수는 있지만 이는 team convention이지 official Router requirement가 아닙니다.
- Source: <https://tanstack.com/router/latest/docs/routing/file-based-routing>
### Route lifecycle and loading
- Loading lifecycle은 matching/search validation, serial `beforeLoad`, 그리고 `loader`와 component preload를 포함하는 parallel route loading 순서로 진행됩니다.
- `beforeLoad`는 serial ordering이 필요한 context, auth, redirects에 적합합니다.
- `loader`는 data loading에 적합하며 Router caching/preloading semantics에 참여합니다.
- Slow loader UI는 `pendingComponent`를 사용할 수 있고 default pending threshold는 configure할 수 있습니다.
- Source: <https://tanstack.com/router/latest/docs/guide/data-loading>
### Search parameter validation
- TanStack Router는 schema-based search validation을 지원합니다.
- Zod v4에서는 Zod schema를 `validateSearch`에 직접 사용할 수 있습니다.
- Zod v3에서는 `@tanstack/zod-adapter` (`zodValidator`, `fallback`)를 사용합니다.
- Project가 두 version 모두에 `zodValidator`를 의도적으로 표준화한다면 hypercore convention으로 label합니다.
- Sources:
- <https://tanstack.com/router/latest/docs/how-to/validate-search-params>
- <https://tanstack.com/router/latest/docs/how-to/setup-basic-search-params>
### Router context
- Root route context는 `createRootRouteWithContext`로 type 지정할 수 있습니다.
- `beforeLoad`는 route context를 확장할 수 있고 그 context는 loaders와 child routes에서 사용할 수 있습니다.
- Source: <https://tanstack.com/router/latest/docs/guide/router-context>
### SSR
- Full-stack framework behavior가 필요한 React Router users에게 TanStack Start는 권장 SSR setup입니다.
- Manual Router SSR도 존재하지만 Start가 대부분의 setup details를 처리합니다.
- Source: <https://tanstack.com/router/latest/docs/how-to/setup-ssr>
## Refresh Triggers
다음 경우 이 snapshot을 refresh합니다:
- Router file naming conventions 또는 route generation requirements가 변경됨.
- Zod/adapter usage에 대한 search validation guidance가 변경됨.
- Loader/beforeLoad lifecycle 또는 pending behavior가 변경됨.
- Local package versions가 위 versions보다 materially 이동함.
references/official/tanstack-router-2026-04-30.md
# TanStack Router Official Snapshot
- last_verified_at: 2026-04-30
- packages_checked:
- `@tanstack/react-router`: `1.168.26`
- Context7 indexed version observed: `v1_114_3` for repository docs, cross-checked with live latest docs.
- source_priority: latest docs pages > API pages > examples
Use this file when Router behavior affects route, search, loader, context, or SSR rules.
## Official Facts Used By This Skill
### File routes and `Route` export
- File-based routes are configured with `createFileRoute(path)(options)`.
- The generated file route instance must be exported using the `Route` identifier for `tsr generate` and `tsr watch` to work correctly.
- Sources:
- <https://tanstack.com/router/latest/docs/api/router/createFileRouteFunction>
- <https://tanstack.com/router/latest/docs/routing/routing-concepts>
### Flat and directory routes
- Router officially supports directory routes, flat routes, and mixed flat/directory structures.
- Hypercore may still prefer route directories for app pages, but that is a team convention, not an official Router requirement.
- Source: <https://tanstack.com/router/latest/docs/routing/file-based-routing>
### Route lifecycle and loading
- The loading lifecycle proceeds through matching/search validation, serial `beforeLoad`, and parallel route loading with `loader` and component preload.
- `beforeLoad` is appropriate for context, auth, and redirects that need serial ordering.
- `loader` is appropriate for data loading and participates in Router caching/preloading semantics.
- Slow loader UI can use `pendingComponent`; the default pending threshold is configurable.
- Source: <https://tanstack.com/router/latest/docs/guide/data-loading>
### Search parameter validation
- TanStack Router supports schema-based search validation.
- With Zod v4, a Zod schema can be used directly in `validateSearch`.
- With Zod v3, use `@tanstack/zod-adapter` (`zodValidator`, `fallback`).
- If a project intentionally standardizes on `zodValidator` for both versions, label that as a hypercore convention.
- Sources:
- <https://tanstack.com/router/latest/docs/how-to/validate-search-params>
- <https://tanstack.com/router/latest/docs/how-to/setup-basic-search-params>
### Router context
- Root route context can be typed with `createRootRouteWithContext`.
- `beforeLoad` can extend route context and the resulting context is available to loaders and child routes.
- Source: <https://tanstack.com/router/latest/docs/guide/router-context>
### SSR
- TanStack Start is the recommended SSR setup for React Router users who need full-stack framework behavior.
- Manual Router SSR exists, but Start handles most setup details.
- Source: <https://tanstack.com/router/latest/docs/how-to/setup-ssr>
## Refresh Triggers
Refresh this snapshot when:
- Router file naming conventions or route generation requirements change.
- Search validation guidance changes for Zod/adapter usage.
- Loader/beforeLoad lifecycle or pending behavior changes.
- Local package versions move materially beyond the versions above.
references/official/tanstack-start-2026-04-30.ko.md
# TanStack Start 공식 스냅샷
- last_verified_at: 2026-04-30
- packages_checked:
- `@tanstack/react-start`: `1.167.52`
- `@tanstack/start-plugin-core`: `1.169.7`
- `@tanstack/router-plugin`: `1.167.29`
- source_priority: canonical guide pages > API/reference pages > examples > migration/comparison pages > release notes for drift context
Start-specific API behavior가 architecture rule에 영향을 줄 때 이 파일을 사용합니다. Hypercore conventions는 `rules/`에 두고 official facts는 여기에 둡니다.
## 이 Skill에서 사용하는 공식 사실
### Project structure
- Project structure는 current Start docs 기준으로 2026-05-24에 재확인했습니다. 위 package snapshot은 2026-04-30 version check로 유지합니다.
- Current Start docs는 typical project shape로 `src/routes`, `src/router.tsx`, generated `src/routeTree.gen.ts`, `src/styles.css`, optional `src/types`, `public/`, root `vite.config.ts`, `package.json`, `tsconfig.json`를 보여줍니다.
- Start Vite plugin은 `srcDirectory`와 `router.routesDirectory`를 customize할 수 있습니다. `src/routes`를 hard-code하지 말고 `tanstackStart()` config에서 실제 route root를 도출합니다.
- `routeTree.gen.ts`는 Start/Router tooling이 생성하며 일반 architecture work에서 수동 편집하지 않습니다.
- Sources:
- <https://tanstack.com/start/latest/docs/framework/react/tutorial/fetching-external-api>
- <https://tanstack.com/start/latest/docs/framework/react/guide/routing>
- <https://tanstack.com/start/latest/docs/framework/react/migrate-from-next-js>
### Router setup
- Start의 React routing guide는 `src/router.tsx`가 호출할 때마다 fresh router instance를 반환하는 `getRouter()` function을 export하기를 기대합니다.
- Source: <https://tanstack.com/start/latest/docs/framework/react/guide/routing>
### Server functions
- Canonical server function examples는 `createServerFn({ method })`, optional `.inputValidator(...)`, optional `.middleware(...)`, then `.handler(...)`를 사용합니다.
- Current canonical server-functions guide에서는 Zod schemas를 `.inputValidator(...)`에 직접 전달할 수 있습니다.
- Server functions는 errors, redirects, not-found responses를 throw할 수 있고, 이는 route lifecycles 또는 `useServerFn()`을 쓰는 component calls를 통해 처리됩니다.
- Source: <https://tanstack.com/start/latest/docs/framework/react/guide/server-functions>
### Execution model
- Start code는 명시적으로 제한하지 않는 한 isomorphic입니다.
- Route loaders는 server-only가 아닙니다. SSR 중 server에서, client navigation 중 client에서 실행될 수 있습니다.
- Secrets, DB access, filesystem access, privileged SDK calls는 server-only/server-function boundaries 뒤에 있어야 합니다.
- `createServerFn`, `createServerOnlyFn`, `createClientOnlyFn`, `createIsomorphicFn`이 관련 execution-control primitives입니다.
- Sources:
- <https://tanstack.com/start/latest/docs/framework/react/guide/execution-model>
- <https://tanstack.com/start/latest/docs/framework/react/guide/code-execution-patterns>
### Import protection
- Import protection은 TanStack Start에서 기본 활성화됩니다.
- Defaults에는 client denial for `**/*.server.*` and Start server specifiers, server denial for `**/*.client.*`가 포함됩니다.
- File markers는 side-effect imports입니다: `@tanstack/react-start/server-only`, `@tanstack/react-start/client-only`.
- Custom project deny rules는 `tanstackStart({ importProtection: { client, server, behavior } })`를 통해 추가할 수 있습니다.
- `importProtection: { enabled: false }` 설정은 protection을 비활성화하므로 explicit user decision이 필요합니다.
- Source: <https://tanstack.com/start/latest/docs/framework/react/guide/import-protection>
### Middleware
- Request middleware는 `createMiddleware()`를 사용할 수 있고 server-function middleware는 `createMiddleware({ type: 'function' })`를 사용합니다.
- Client context는 기본적으로 server에 전송되지 않습니다. `sendContext`는 명시적이어야 합니다.
- Dynamic/user-generated `sendContext` values는 trust 전에 server-side validation이 필요합니다.
- Source: <https://tanstack.com/start/latest/docs/framework/react/guide/middleware>
### Server routes
- Server routes는 HTTP endpoints를 위한 official Start feature이며 `createFileRoute(... )({ server: { handlers } })`를 통해 app routes와 나란히 정의할 수 있습니다.
- Webhooks, health/readiness, auth provider endpoints, files, machine-readable public endpoints처럼 raw HTTP semantics가 필요한 경우 server routes를 사용합니다.
- Hypercore는 internal app RPC에 server routes를 쓰는 것을 discouraged합니다. 이는 team policy이며 server functions를 사용합니다.
- Source: <https://tanstack.com/start/latest/docs/framework/react/guide/server-routes>
### SSR and hydration
- Routes는 달리 configure하지 않으면 기본적으로 SSR로 render됩니다.
- Route-level `ssr`와 app-level `defaultSsr`가 selective SSR behavior를 제어합니다.
- Hydration errors는 locale/time-zone differences, `Date.now()`, random IDs, responsive-only logic, feature flags, user preferences에서 흔히 발생합니다.
- Sources:
- <https://tanstack.com/start/latest/docs/framework/react/guide/selective-ssr>
- <https://tanstack.com/start/latest/docs/framework/react/guide/hydration-errors>
## Refresh Triggers
다음 경우 이 snapshot을 refresh합니다:
- TanStack Start가 stable v1 guidance에 도달하거나 guidance가 변경됨.
- `createServerFn`, `.inputValidator()`, middleware, import protection, `getRouter()`, SSR options가 변경됨.
- 이 skill이 새로운 Start guide page에 의존하기 시작함.
- Start project structure, `srcDirectory`, `routesDirectory`, route tree generation guidance가 변경됨.
- Local package versions가 위 versions보다 materially 이동함.
references/official/tanstack-start-2026-04-30.md
# TanStack Start Official Snapshot
- last_verified_at: 2026-04-30
- packages_checked:
- `@tanstack/react-start`: `1.167.52`
- `@tanstack/start-plugin-core`: `1.169.7`
- `@tanstack/router-plugin`: `1.167.29`
- source_priority: canonical guide pages > API/reference pages > examples > migration/comparison pages > release notes for drift context
Use this file when Start-specific API behavior affects an architecture rule. Keep hypercore conventions in `rules/`; keep official facts here.
## Official Facts Used By This Skill
### Project structure
- Project structure was re-checked via current Start docs on 2026-05-24; the package snapshot above remains the 2026-04-30 version check.
- Current Start docs show `src/routes`, `src/router.tsx`, generated `src/routeTree.gen.ts`, `src/styles.css`, optional `src/types`, `public/`, root `vite.config.ts`, `package.json`, and `tsconfig.json` as the typical project shape.
- The Start Vite plugin can customize `srcDirectory` and `router.routesDirectory`; derive the actual route root from `tanstackStart()` config instead of hard-coding `src/routes`.
- `routeTree.gen.ts` is generated by Start/Router tooling and should not be hand-edited for normal architecture work.
- Sources:
- <https://tanstack.com/start/latest/docs/framework/react/tutorial/fetching-external-api>
- <https://tanstack.com/start/latest/docs/framework/react/guide/routing>
- <https://tanstack.com/start/latest/docs/framework/react/migrate-from-next-js>
### Router setup
- Start's React routing guide expects `src/router.tsx` to export a `getRouter()` function that returns a fresh router instance each call.
- Source: <https://tanstack.com/start/latest/docs/framework/react/guide/routing>
### Server functions
- Canonical server function examples use `createServerFn({ method })`, optional `.inputValidator(...)`, optional `.middleware(...)`, then `.handler(...)`.
- Zod schemas can be passed directly to `.inputValidator(...)` in the current canonical server-functions guide.
- Server functions can throw errors, redirects, and not-found responses that are handled through route lifecycles or component calls using `useServerFn()`.
- Source: <https://tanstack.com/start/latest/docs/framework/react/guide/server-functions>
### Execution model
- Start code is isomorphic unless explicitly constrained.
- Route loaders are not server-only; they may execute on the server during SSR and on the client during navigation.
- Secrets, DB access, filesystem access, and privileged SDK calls must live behind server-only/server-function boundaries.
- `createServerFn`, `createServerOnlyFn`, `createClientOnlyFn`, and `createIsomorphicFn` are the relevant execution-control primitives.
- Sources:
- <https://tanstack.com/start/latest/docs/framework/react/guide/execution-model>
- <https://tanstack.com/start/latest/docs/framework/react/guide/code-execution-patterns>
### Import protection
- Import protection is enabled by default in TanStack Start.
- Defaults include client denial for `**/*.server.*` and Start server specifiers, and server denial for `**/*.client.*`.
- File markers are side-effect imports: `@tanstack/react-start/server-only` and `@tanstack/react-start/client-only`.
- Custom project deny rules can be added through `tanstackStart({ importProtection: { client, server, behavior } })`.
- Setting `importProtection: { enabled: false }` disables protection and should require an explicit user decision.
- Source: <https://tanstack.com/start/latest/docs/framework/react/guide/import-protection>
### Middleware
- Request middleware can use `createMiddleware()`; server-function middleware uses `createMiddleware({ type: 'function' })`.
- Client context is not sent to the server by default. `sendContext` must be explicit.
- Dynamic/user-generated `sendContext` values need server-side validation before trust.
- Source: <https://tanstack.com/start/latest/docs/framework/react/guide/middleware>
### Server routes
- Server routes are an official Start feature for HTTP endpoints and can be defined alongside app routes via `createFileRoute(... )({ server: { handlers } })`.
- Use server routes for raw HTTP semantics such as webhooks, health/readiness, auth provider endpoints, files, and machine-readable public endpoints.
- Hypercore discourages server routes for internal app RPC; use server functions for that team policy.
- Source: <https://tanstack.com/start/latest/docs/framework/react/guide/server-routes>
### SSR and hydration
- Routes render with SSR by default unless configured otherwise.
- Route-level `ssr` and app-level `defaultSsr` control selective SSR behavior.
- Hydration errors commonly come from locale/time-zone differences, `Date.now()`, random IDs, responsive-only logic, feature flags, and user preferences.
- Sources:
- <https://tanstack.com/start/latest/docs/framework/react/guide/selective-ssr>
- <https://tanstack.com/start/latest/docs/framework/react/guide/hydration-errors>
## Refresh Triggers
Refresh this snapshot when:
- TanStack Start reaches or changes stable v1 guidance.
- `createServerFn`, `.inputValidator()`, middleware, import protection, `getRouter()`, or SSR options change.
- This skill starts relying on a new Start guide page.
- Start project structure, `srcDirectory`, `routesDirectory`, or route tree generation guidance changes.
- Local package versions move materially beyond the versions above.
rules/conventions.ko.md
# 코드 컨벤션
> TanStack Start 프로젝트 코드 작성 규칙
---
## Rule Classifications
| Rule | Classification | Enforcement |
|---|---|---|
| route filename은 TanStack Router convention 준수 | Official | official route name 유지 |
| route 외 filename은 kebab-case | Hypercore convention | touched file에 적용 |
| no `any`, explicit return type, const arrow function | Hypercore convention | touched code에 적용 |
| 의미 있는 code group의 Korean block comment | Hypercore convention | touched implementation file에 적용 |
---
## 파일 네이밍
> camelCase 파일명 금지 - 모든 파일명은 kebab-case 사용
| 타입 | 규칙 | 예시 |
|------|------|------|
| **일반 파일** | kebab-case | `user-profile.tsx`, `auth-service.ts` |
| **Route 파일** | TanStack Router 규칙 | `__root.tsx`, `index.tsx`, `$id.tsx` |
| **Hook 파일** | `use-` 접두사 + kebab-case | `use-user-filter.ts`, `use-auth.ts` |
| **Component** | PascalCase 컴포넌트, kebab-case 파일 | `UserCard` in `user-card.tsx` |
| **Server Function** | kebab-case | `get-users.ts`, `create-post.ts` |
```
camelCase 금지: getUserById.ts, authService.ts, useUserFilter.ts
kebab-case 필수: get-user-by-id.ts, auth-service.ts, use-user-filter.ts
```
---
## TypeScript 규칙
| 규칙 | 설명 | 예시 |
|------|------|------|
| **함수 선언** | const 함수, 명시적 return type | `const fn = (): ReturnType => {}` |
| **타입 정의** | interface (객체), type (유니온) | `interface User {}`, `type Status = 'a' \| 'b'` |
| **any 금지** | unknown 사용 | `const data: unknown = JSON.parse(str)` |
| **Import 타입** | type import 분리 | `import type { User } from '@/types'` |
```typescript
// const 함수, 명시적 타입
const getUserById = async (id: string): Promise<User> => {
return prisma.user.findUnique({ where: { id } })
}
// any 금지 -> unknown 사용
const parseJSON = (data: string): unknown => {
return JSON.parse(data)
}
// function 키워드 금지
// function badFunction() {} -> const 화살표 함수 사용
```
---
## Import 순서
```typescript
// 1. External libraries
import { createFileRoute } from '@tanstack/react-router'
import { useQuery } from '@tanstack/react-query'
import { z } from 'zod'
// 2. Internal packages (@/)
import { Button } from '@/components/ui/button'
import { prisma } from '@/database/prisma'
import { getUsers } from '@/modules/users/list/users.functions'
// 3. Relative imports (route-specific)
import { UserCard } from './-components/user-card'
import { useUsers } from './-hooks/use-users'
// 4. Type imports
import type { User } from '@/types'
import type { UseUsersReturn } from './-hooks/use-users'
```
---
## 한글 주석 (묶음 단위)
```typescript
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// 사용자 관련 상태
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
const [user, setUser] = useState<User | null>(null)
const [isLoading, setIsLoading] = useState(false)
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// 데이터 조회
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
const { data: users } = useQuery({
queryKey: ['users'],
queryFn: () => getUsers(),
})
```
세세한 줄별 주석 금지. 코드 묶음 단위로만 주석 작성.
---
## 에러 처리 패턴
```typescript
// lib/errors.ts
export class AppError extends Error {
constructor(
message: string,
public statusCode: number = 500,
public code: string = 'INTERNAL_ERROR'
) {
super(message)
this.name = 'AppError'
}
}
export class NotFoundError extends AppError {
constructor(resource: string) {
super(`${resource} not found`, 404, 'NOT_FOUND')
}
}
export class ValidationError extends AppError {
constructor(message: string) {
super(message, 400, 'VALIDATION_ERROR')
}
}
export class UnauthorizedError extends AppError {
constructor() {
super('Unauthorized', 401, 'UNAUTHORIZED')
}
}
```
rules/conventions.md
# Code Conventions
> TanStack Start project coding rules
---
## Rule Classifications
| Rule | Classification | Enforcement |
|---|---|---|
| Route file names follow TanStack Router conventions | Official | Keep official route names |
| Kebab-case non-route filenames | Hypercore convention | Apply to touched files |
| No `any`, explicit return types, const arrow functions | Hypercore convention | Apply to touched code |
| Korean block comments for meaningful code groups | Hypercore convention | Apply to touched implementation files |
---
## File Naming
> camelCase filenames are FORBIDDEN - all filenames must use kebab-case
| Type | Rule | Example |
|------|------|---------|
| **General files** | kebab-case | `user-profile.tsx`, `auth-service.ts` |
| **Route files** | TanStack Router rules | `__root.tsx`, `index.tsx`, `$id.tsx` |
| **Hook files** | `use-` prefix + kebab-case | `use-user-filter.ts`, `use-auth.ts` |
| **Components** | PascalCase component, kebab-case file | `UserCard` in `user-card.tsx` |
| **Server Functions** | kebab-case | `get-users.ts`, `create-post.ts` |
```
FORBIDDEN camelCase: getUserById.ts, authService.ts, useUserFilter.ts
REQUIRED kebab-case: get-user-by-id.ts, auth-service.ts, use-user-filter.ts
```
---
## TypeScript Rules
| Rule | Description | Example |
|------|-------------|---------|
| **Function declaration** | const arrow function, explicit return type | `const fn = (): ReturnType => {}` |
| **Type definition** | interface (objects), type (unions) | `interface User {}`, `type Status = 'a' \| 'b'` |
| **No any** | Use unknown | `const data: unknown = JSON.parse(str)` |
| **Type imports** | Separate type imports | `import type { User } from '@/types'` |
```typescript
// const arrow function, explicit types
const getUserById = async (id: string): Promise<User> => {
return prisma.user.findUnique({ where: { id } })
}
// No any -> use unknown
const parseJSON = (data: string): unknown => {
return JSON.parse(data)
}
// function keyword FORBIDDEN
// function badFunction() {} -> use const arrow function
```
---
## Import Order
```typescript
// 1. External libraries
import { createFileRoute } from '@tanstack/react-router'
import { useQuery } from '@tanstack/react-query'
import { z } from 'zod'
// 2. Internal packages (@/)
import { Button } from '@/components/ui/button'
import { prisma } from '@/database/prisma'
import { getUsers } from '@/modules/users/list/users.functions'
// 3. Relative imports (route-specific)
import { UserCard } from './-components/user-card'
import { useUsers } from './-hooks/use-users'
// 4. Type imports
import type { User } from '@/types'
import type { UseUsersReturn } from './-hooks/use-users'
```
---
## Korean Block Comments (per group)
```typescript
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// User-related state
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
const [user, setUser] = useState<User | null>(null)
const [isLoading, setIsLoading] = useState(false)
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// Data fetching
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
const { data: users } = useQuery({
queryKey: ['users'],
queryFn: () => getUsers(),
})
```
Line-by-line comments are FORBIDDEN. Comments only per code group/block.
---
## Error Handling Pattern
```typescript
// lib/errors.ts
export class AppError extends Error {
constructor(
message: string,
public statusCode: number = 500,
public code: string = 'INTERNAL_ERROR'
) {
super(message)
this.name = 'AppError'
}
}
export class NotFoundError extends AppError {
constructor(resource: string) {
super(`${resource} not found`, 404, 'NOT_FOUND')
}
}
export class ValidationError extends AppError {
constructor(message: string) {
super(message, 400, 'VALIDATION_ERROR')
}
}
export class UnauthorizedError extends AppError {
constructor() {
super('Unauthorized', 401, 'UNAUTHORIZED')
}
}
```
rules/execution-model.ko.md
# Execution Model
> TanStack Start의 서버/클라이언트/공용 실행 경계 규칙
---
## Rule Classifications
| Rule | Classification | Enforcement |
|---|---|---|
| loader는 server-only가 아니라 isomorphic | Official | privileged direct access 차단 |
| secret은 server-only boundary 뒤에 둠 | Safety policy | leak 차단 |
| ad-hoc branching보다 environment function 선호 | Hypercore convention | touched code에서 warn/fix |
---
## 핵심 규칙
코드가 어디서 실행되는지 추측으로 판단하면 안 됩니다. TanStack Start에서는:
- route `loader`는 기본적으로 isomorphic입니다
- `beforeLoad`와 컴포넌트 렌더링은 SSR 모드에 따라 서버/클라이언트/양쪽에서 실행될 수 있습니다
- 브라우저 API가 route 코드에서 자동으로 안전한 것이 아닙니다
- secret은 클라이언트에서 도달 가능한 코드에 두면 안 됩니다
---
## 비타협 규칙
| 확인 항목 | 규칙 |
|------|------|
| `loader`가 secret, DB, filesystem, privileged SDK를 직접 읽음? | 차단. `createServerFn` 또는 `createServerOnlyFn`으로 이동 |
| 클라이언트에서 도달 가능한 코드가 secret 값을 `process.env`에서 직접 읽음? | 차단 |
| 서버에서도 실행될 수 있는 코드에서 `window`, `localStorage`, `document`를 경계 없이 사용함? | 차단 |
| `typeof window` 분기 대신 `createClientOnlyFn` / `createServerOnlyFn` / `createIsomorphicFn`이 더 명확한데 수동 분기함? | 경고. 프레임워크 primitive 선호 |
| 하나의 공용 유틸이 서버 전용 로직과 클라이언트 전용 로직을 함께 섞고 있음? | 차단. 분리하거나 환경 함수 사용 |
---
## 올바른 Primitive 선택
| 목적 | 사용 API |
|------|-----|
| routes/components에서 호출하는 서버 RPC | `createServerFn` |
| 클라이언트에서 호출되면 바로 실패해야 하는 서버 전용 헬퍼 | `createServerOnlyFn` |
| 서버에서 실행되면 바로 실패해야 하는 클라이언트 전용 헬퍼 | `createClientOnlyFn` |
| 서버/클라이언트 구현이 다른 같은 API | `createIsomorphicFn` |
---
## Loader 규칙
`loader` 자체는 secret을 안전하게 숨겨주는 경계가 아닙니다.
잘못된 예:
```ts
export const Route = createFileRoute('/users')({
loader: () => {
return fetch(`/api/users?key=${process.env.SECRET_KEY}`)
},
})
```
올바른 예:
```ts
const getUsersSecurely = createServerFn().handler(async () => {
return fetch(`/api/users?key=${process.env.SECRET_KEY}`)
})
export const Route = createFileRoute('/users')({
loader: () => getUsersSecurely(),
})
```
---
## 보안 규칙
- secret, DB client, filesystem 접근, privileged SDK는 반드시 `createServerFn` 또는 `createServerOnlyFn` 뒤에 둡니다
- 브라우저 API는 `createClientOnlyFn`, `ClientOnly`, client-only component/hook 뒤에 둡니다
- 클라이언트가 import할 수 있는 코드라면, import protection과 실행 경계로 증명되지 않는 한 공개 코드라고 가정합니다
---
## 리뷰 체크리스트
- `loader` 내부에 secret/privileged access가 직접 없음
- 환경 전용 헬퍼는 TanStack Start primitive를 사용함
- 서버 전용 코드가 클라이언트에서 도달되지 않음
- 브라우저 전용 코드가 서버 렌더에서 실행되지 않음
rules/execution-model.md
# Execution Model
> TanStack Start runtime boundary rules for server, client, and isomorphic code
---
## Rule Classifications
| Rule | Classification | Enforcement |
|---|---|---|
| Loaders are isomorphic, not server-only | Official | Block privileged direct access |
| Secrets stay behind server-only boundaries | Safety policy | Block leaks |
| Prefer environment functions over ad-hoc branching | Hypercore convention | Warn/fix in touched code |
---
## Core Rule
Do not guess where code runs. In TanStack Start:
- route `loader` is isomorphic by default
- `beforeLoad` and component rendering may run on server, client, or both depending on SSR mode
- browser APIs are not automatically safe in route code
- secrets are never safe in client-reachable code
---
## Non-Negotiable Rules
| Check | Rule |
|------|------|
| `loader` directly reads secrets, DB, filesystem, or privileged SDKs? | BLOCKED. Move to `createServerFn` or `createServerOnlyFn` |
| Client-reachable code reads secret values directly from `process.env`? | BLOCKED |
| Browser-only APIs (`window`, `localStorage`, `document`) used in server-capable code without guard or boundary? | BLOCKED |
| Manual `typeof window` branching used where `createClientOnlyFn` / `createServerOnlyFn` / `createIsomorphicFn` is clearer? | WARNING. Prefer framework primitives |
| Shared utility mixes server-only and client-only logic in one unbounded function? | BLOCKED. Split or use explicit environment function |
---
## Pick The Right Primitive
| Need | Use |
|------|-----|
| Server RPC callable from routes/components | `createServerFn` |
| Server-only helper that must crash on client | `createServerOnlyFn` |
| Client-only helper that must crash on server | `createClientOnlyFn` |
| Same API with different server/client implementations | `createIsomorphicFn` |
---
## Loader Rule
`loader` is not a safe place for secrets by itself.
Wrong:
```ts
export const Route = createFileRoute('/users')({
loader: () => {
return fetch(`/api/users?key=${process.env.SECRET_KEY}`)
},
})
```
Right:
```ts
const getUsersSecurely = createServerFn().handler(async () => {
return fetch(`/api/users?key=${process.env.SECRET_KEY}`)
})
export const Route = createFileRoute('/users')({
loader: () => getUsersSecurely(),
})
```
---
## Security Rules
- Secrets, DB clients, filesystem access, and privileged SDKs stay behind `createServerFn` or `createServerOnlyFn`
- Browser APIs stay behind `createClientOnlyFn`, `ClientOnly`, or client-only components/hooks
- If code can be imported by the client, assume it is public unless import protection and execution boundaries prove otherwise
---
## Review Checklist
- No `loader` contains secret or privileged access directly
- Environment-specific helpers use TanStack Start primitives
- Server-only code is not reachable from client code
- Browser-only code is not reachable during server render
rules/hooks.ko.md
# Custom Hook Patterns
> logic이 있는 page/component의 interactive logic, server-function wrapper, query orchestration, handler, memo, effect를 모읍니다.
## Rule Classifications
| Rule | Classification | Enforcement |
|---|---|---|
| React hooks는 React rules 준수 | Official | 위반 시 차단 |
| `useServerFn`은 `@tanstack/react-start`에서 import | Official | 잘못된 import 수정 |
| touched interactive page의 `-hooks/` 추출 | Hypercore convention | official default 요청이 없으면 적용 |
| publishing-only static page는 `-hooks/` 예외 | Hypercore convention | 빈 폴더 생성 금지 |
| hook internal order | Hypercore convention | touched hook에 적용 |
## Extraction Rule
Interactive logic이 있는 page/component는 orchestration을 `-hooks/`로 옮깁니다:
- `useState`, `useReducer`, Zustand/global state
- `useServerFn` wrapper
- TanStack Query `useQuery` / `useMutation`
- handler와 callback
- derived memoized value
- effect와 lifecycle code
logic/server integration이 없는 publishing-only static page는 `-hooks/`가 필요 없습니다.
## Folder Pattern
```text
routes/users/
├── index.tsx
├── -hooks/
│ └── use-users.ts
├── -components/
└── -functions/
```
## Hook Internal Order
```typescript
export const useUsers = (): UseUsersReturn => {
// 1. State
// 2. Global stores / context
// 3. Server function wrappers with useServerFn
// 4. Queries and mutations
// 5. Handlers / callbacks
// 6. Memoized derived values
// 7. Effects
// 8. Return object
}
```
## `useServerFn` + TanStack Query Pattern
```typescript
import { useServerFn } from '@tanstack/react-start'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { getUsers } from '../-functions/get-users'
import { createUser } from '../-functions/create-user'
export const useUsers = (): UseUsersReturn => {
const queryClient = useQueryClient()
const getServerUsers = useServerFn(getUsers)
const createServerUser = useServerFn(createUser)
const usersQuery = useQuery({
queryKey: ['users'],
queryFn: () => getServerUsers(),
})
const createMutation = useMutation({
mutationFn: (data: CreateUserInput) => createServerUser({ data }),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['users'] }),
})
return { usersQuery, createMutation }
}
```
## Direct Calls vs Wrappers
| Pattern | When | Import/source |
|---|---|---|
| Direct server function call | `loader`, `beforeLoad`, server-only code | Direct import |
| `useServerFn` wrapper | Client component 또는 hook | `@tanstack/react-start` |
| TanStack Query | Client cache, mutation, invalidation | `@tanstack/react-query` |
## Validation Checklist
- [ ] publishing-only static page에 hook file 생성을 강제하지 않음.
- [ ] logic이 있는 touched page/component가 orchestration을 hook으로 추출함.
- [ ] hook filename이 `use-users.ts` 같은 kebab-case임.
- [ ] hook에 explicit return type/interface가 있음.
- [ ] `useServerFn` wrapper가 `@tanstack/react-start`에서 import됨.
- [ ] hook order가 hypercore sequence를 따르거나 deviation 이유가 기록됨.
rules/hooks.md
# Custom Hook Patterns
> Centralize interactive logic, server-function wrappers, query orchestration, handlers, memoization, and effects for pages/components that have logic.
## Rule Classifications
| Rule | Classification | Enforcement |
|---|---|---|
| React hooks follow React rules | Official | Block violations |
| `useServerFn` imported from `@tanstack/react-start` | Official | Fix wrong imports |
| Logic extraction to `-hooks/` for touched interactive pages | Hypercore convention | Apply unless official defaults requested |
| Publishing-only static pages exempt from `-hooks/` | Hypercore convention | Do not create empty folders |
| Internal hook order | Hypercore convention | Apply to touched hooks |
## Extraction Rule
Pages/components with interactive logic must move orchestration into `-hooks/`:
- `useState`, `useReducer`, Zustand/global state
- `useServerFn` wrappers
- TanStack Query `useQuery` / `useMutation`
- Handlers and callbacks
- Derived memoized values
- Effects and lifecycle code
Publishing-only static pages with no logic and no server integration do not need `-hooks/`.
## Folder Pattern
```text
routes/users/
├── index.tsx
├── -hooks/
│ └── use-users.ts
├── -components/
└── -functions/
```
## Hook Internal Order
```typescript
export const useUsers = (): UseUsersReturn => {
// 1. State
// 2. Global stores / context
// 3. Server function wrappers with useServerFn
// 4. Queries and mutations
// 5. Handlers / callbacks
// 6. Memoized derived values
// 7. Effects
// 8. Return object
}
```
## `useServerFn` + TanStack Query Pattern
```typescript
import { useServerFn } from '@tanstack/react-start'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { getUsers } from '../-functions/get-users'
import { createUser } from '../-functions/create-user'
export const useUsers = (): UseUsersReturn => {
const queryClient = useQueryClient()
const getServerUsers = useServerFn(getUsers)
const createServerUser = useServerFn(createUser)
const usersQuery = useQuery({
queryKey: ['users'],
queryFn: () => getServerUsers(),
})
const createMutation = useMutation({
mutationFn: (data: CreateUserInput) => createServerUser({ data }),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['users'] }),
})
return { usersQuery, createMutation }
}
```
## Direct Calls vs Wrappers
| Pattern | When | Import/source |
|---|---|---|
| Direct server function call | `loader`, `beforeLoad`, server-only code | Direct import |
| `useServerFn` wrapper | Client component or hook | `@tanstack/react-start` |
| TanStack Query | Client cache, mutations, invalidation | `@tanstack/react-query` |
## Validation Checklist
- [ ] Publishing-only static pages were not forced to create hook files.
- [ ] Touched pages/components with logic extract orchestration to a hook.
- [ ] Hook files use kebab-case filenames such as `use-users.ts`.
- [ ] Hook has an explicit return type/interface.
- [ ] `useServerFn` wrappers are imported from `@tanstack/react-start`.
- [ ] Hook order follows the hypercore sequence or records a reason for deviation.
rules/import-protection.ko.md
# Import Protection
> Start의 기본 client/server import boundary를 인정하면서 hypercore safety deny rules를 적용합니다.
## Rule Classifications
| Rule | Classification | Enforcement |
|---|---|---|
| Start import protection은 기본 enabled | Official | custom config 전 behavior 확인 |
| `.server.*`는 client에서, `.client.*`는 server에서 deny | Official | leak 차단 |
| marker import는 module을 한 environment로 제한 | Official | suffix가 부족할 때 사용 |
| `database/`, `server/`, ORM package custom deny rules | Safety policy | 프로젝트에 필요하면 추가/확장 |
| import protection 비활성화 금지 | Safety policy | 명시 요청 없으면 차단 |
## Official Defaults
TanStack Start import protection은 기본 enabled입니다. explicit `importProtection` object가 항상 필요하다고 말하지 않습니다.
기본 deny pattern:
- Client environment: `**/*.server.*`, Start server specifiers.
- Server environment: `**/*.client.*`.
Type-only imports and re-exports are ignored because runtime bundle에서 제거됩니다. Runtime value를 포함하는 mixed imports는 여전히 검사 대상입니다.
## Marker Imports
```typescript
import '@tanstack/react-start/server-only'
import '@tanstack/react-start/client-only'
```
- 한 파일에는 marker 하나만 사용합니다.
- 파일명만으로 boundary가 명확하지 않을 때 사용합니다.
## Custom Deny Rules
프로젝트가 directory/package 추가 차단을 필요로 할 때 explicit `tanstackStart({ importProtection })` config를 추가합니다:
```typescript
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
tanstackStart({
importProtection: {
behavior: { dev: 'mock', build: 'error' },
client: {
files: ['**/*.server.*', '**/server/**', '**/database/**', '**/db/**'],
specifiers: ['@prisma/client', 'bcrypt'],
},
server: {
files: ['**/*.client.*', '**/client/**'],
specifiers: ['localforage'],
},
},
})
```
기존 `tanstackStart()`가 있으면 관련 nested option만 확장합니다. plugin을 중복 추가하거나 unrelated option을 덮어쓰지 않습니다.
Project가 development에서도 violation을 실패시키길 원하면 `behavior: 'error'`를 사용합니다. Current options에는 scoped enforcement와 diagnostics를 위한 `log`, `include`, `exclude`, `ignoreImporters`, `maxTraceDepth`, `onViolation`도 포함됩니다.
`client`와 `server` rules는 `files`, `specifiers`, `excludeFiles`를 지원합니다. Default는 `node_modules` 아래 resolved files를 제외합니다. `excludeFiles: []`는 선택한 environment에서 이 검사를 다시 켜므로, third-party package false positive 가능성을 고려해 의도적으로만 사용합니다.
## Compiler Boundary Leak Rule
`createServerFn` handler 내부 server-only import는 client build에서 제거될 수 있습니다. 같은 import가 client compilation 후 살아남는 코드에서 참조되면 import protection violation입니다.
수정 방법:
- surviving helper를 `*.server.*`로 분리.
- helper를 `createServerOnlyFn`으로 감싸기.
- browser-only code는 `*.client.*` 또는 `createClientOnlyFn` 뒤로 이동.
- server function wrapper는 `*.functions.ts`에 두고 DB/secret/filesystem helper는 sibling `*.server.ts`로 분리.
- `src/modules/<domain>/<feature>/index.ts`나 `-functions/index.ts`에서 safe exports와 server-only exports를 섞지 않기.
## Server Function Import Shape
Server function wrapper 자체는 loader/component/hook에서 static import할 수 있습니다. 하지만 wrapper file이 client build에서 살아남는 export를 통해 server-only helper를 참조하면 leak입니다.
권장:
```text
src/modules/users/profile/
├── profile.functions.ts # createServerFn exports
├── profile.server.ts # DB/secret helper
└── profile.schemas.ts # client-safe schema
```
금지/경고:
- `profile.functions.ts`가 handler 밖 helper export에서 `profile.server.ts`를 참조
- `index.ts`가 `profile.functions.ts`와 `profile.server.ts`를 함께 re-export
- client component가 `*.server.ts`, `src/db/**`, privileged SDK를 직접 import
- server function을 dynamic import해서 bundler rewrite/import-protection trace를 흐리게 함
## Validation Checklist
- [ ] import protection이 disabled가 아님.
- [ ] project directory/package에 필요하면 custom deny rules가 있음.
- [ ] Type-only imports를 runtime boundary leak로 잘못 보고하지 않음.
- [ ] 기존 `tanstackStart()` option을 덮어쓰지 않고 확장함.
- [ ] `behavior: 'error'`와 `{ dev, build }` behavior를 의도적으로 선택함.
- [ ] Third-party resolved-file checks가 의도적으로 필요할 때만 `excludeFiles: []`를 사용함.
- [ ] `.server.*`, `.client.*`, marker import가 일관됨.
- [ ] server-only import가 recognized boundary 밖에 살아남지 않음.
- [ ] `*.functions.ts` wrapper와 `*.server.ts` helper가 split되어 있음.
- [ ] safe/server-only mixed barrel이 없음.
- [ ] tree-shaking false positive 가능성이 있으면 production build로 확인함.
rules/import-protection.md
# Import Protection
> Enforce Start client/server import boundaries without hiding the fact that Start has defaults.
## Rule Classifications
| Rule | Classification | Enforcement |
|---|---|---|
| Start import protection exists and is enabled by default | Official | Verify behavior before custom config |
| `.server.*` denied from client and `.client.*` denied from server | Official | Block leaks |
| Marker imports restrict modules to one environment | Official | Use when suffix is not enough |
| Custom deny rules for `database/`, `server/`, ORM packages | Safety policy | Add/extend when project needs them |
| Never disable import protection silently | Safety policy | Block unless user explicitly requests |
## Official Defaults
TanStack Start import protection is enabled by default. Do not claim an explicit `importProtection` object is always required.
Default-denied patterns include:
- Client environment: `**/*.server.*` and Start server specifiers.
- Server environment: `**/*.client.*`.
Type-only imports and re-exports are ignored because they are erased from the runtime bundle. Mixed imports still count when they include runtime values.
## Marker Imports
```typescript
import '@tanstack/react-start/server-only'
import '@tanstack/react-start/client-only'
```
- Use one marker at most per file.
- Use markers when file names cannot clearly express the environment boundary.
## Custom Deny Rules
Add explicit `tanstackStart({ importProtection })` config when the project needs stronger rules for directories or packages:
```typescript
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
export default defineConfig({
plugins: [
tanstackStart({
importProtection: {
behavior: { dev: 'mock', build: 'error' },
client: {
files: ['**/*.server.*', '**/server/**', '**/database/**', '**/db/**'],
specifiers: ['@prisma/client', 'bcrypt'],
},
server: {
files: ['**/*.client.*', '**/client/**'],
specifiers: ['localforage'],
},
},
}),
],
})
```
If `tanstackStart()` already exists, extend only the relevant nested options. Do not duplicate plugins or overwrite unrelated options.
Use `behavior: 'error'` when a project wants violations to fail even in development. Current options also include `log`, `include`, `exclude`, `ignoreImporters`, `maxTraceDepth`, and `onViolation` for scoped enforcement and diagnostics.
`client` and `server` rules support `files`, `specifiers`, and `excludeFiles`. The default excludes resolved files under `node_modules`; setting `excludeFiles: []` opts back into those checks for the selected environment and should be deliberate because third-party packages can produce false positives.
## Compiler Boundary Leak Rule
Server-only imports used inside a `createServerFn` handler may be removed from the client build. If the same import is referenced by code that survives client compilation, import protection should flag it.
Fix with one of:
- Split the surviving helper into `*.server.*`.
- Wrap the helper with `createServerOnlyFn`.
- Move browser-only code behind `*.client.*` or `createClientOnlyFn`.
- Put server function wrappers in `*.functions.ts` and split DB/secret/filesystem helpers to sibling `*.server.ts`.
- Do not mix safe exports with server-only exports in `src/modules/<domain>/<feature>/index.ts` or `-functions/index.ts`.
## Server Function Import Shape
Server function wrappers themselves may be statically imported from loaders/components/hooks. A wrapper still leaks if surviving client-build exports reference server-only helpers outside the handler boundary.
Recommended:
```text
src/modules/users/profile/
├── profile.functions.ts # createServerFn exports
├── profile.server.ts # DB/secret helper
└── profile.schemas.ts # client-safe schema
```
Blocked or warned:
- `profile.functions.ts` references `profile.server.ts` from a helper export outside the handler.
- `index.ts` re-exports both `profile.functions.ts` and `profile.server.ts`.
- Client components import `*.server.ts`, `src/db/**`, or privileged SDKs directly.
- Server functions are dynamically imported, obscuring bundler rewrite/import-protection traces.
## Validation Checklist
- [ ] Import protection is not disabled.
- [ ] Custom deny rules are present when project directories/packages require them.
- [ ] Type-only imports are not misreported as runtime boundary leaks.
- [ ] Existing `tanstackStart()` options are extended, not overwritten.
- [ ] `behavior: 'error'` vs `{ dev, build }` behavior is chosen intentionally.
- [ ] `excludeFiles: []` is used only when third-party resolved-file checks are intentionally required.
- [ ] `.server.*`, `.client.*`, and marker imports are used consistently.
- [ ] Server-only imports do not survive outside recognized boundaries.
- [ ] `*.functions.ts` wrappers and `*.server.ts` helpers are split.
- [ ] There are no mixed safe/server-only barrels.
- [ ] Dev warnings are confirmed with production build when tree-shaking might remove false positives.
rules/middleware.ko.md
# Middleware
> validation, context 전파, client-to-server 데이터 전달을 위한 middleware 규칙
---
## Rule Classifications
| Rule | Classification | Enforcement |
|---|---|---|
| Request middleware는 default로 `createMiddleware()` 사용 | Official | request middleware에 function-only syntax를 강제하지 않음 |
| Server function middleware는 `createMiddleware({ type: 'function' })` 사용 | Official | `.client(...)`, `.inputValidator(...)`, server-function-only behavior가 쓰이면 잘못된 middleware type 차단 |
| Server function middleware validation은 `.inputValidator(...)` 사용 | Official | middleware와 server-function validation chain을 개념적으로 분리 |
| `sendContext`는 명시적이며 자동 전송 아님 | Official | trust 전 validation |
| client-provided context를 server-side 검증 | Safety policy | unvalidated trust 차단 |
| shared auth/logging/tenant logic 중앙화 | Hypercore convention | touched code에서 warn/fix |
---
## 핵심 규칙
Middleware는 단순 auth 용도가 아닙니다. request context, validation, logging, server-safe 데이터 전파를 명시적으로 처리하는 경계입니다.
TanStack Start에는 두 middleware type이 있습니다:
- Request middleware: `createMiddleware()` 또는 `createMiddleware({ type: 'request' })`. Server requests, server routes, SSR, server functions에 적용되며 `.server(...)`만 가집니다.
- Server function middleware: `createMiddleware({ type: 'function' })`. `createServerFn` middleware chain용이며 `.client(...)`, `.server(...)`, `.inputValidator(...)`를 사용할 수 있습니다.
---
## 비타협 규칙
| 확인 항목 | 규칙 |
|------|------|
| Request middleware가 function-only behavior를 사용함? | 차단. `createMiddleware({ type: 'function' })` 사용 |
| Server function middleware validation을 `.validator(...)`로 작성함? | 차단. Middleware는 `.inputValidator(...)`를 사용하고 server functions도 별도 chain에서 `.inputValidator(...)`를 사용 |
| 클라이언트에서 `sendContext`로 보낸 동적 데이터를 서버에서 검증 없이 사용함? | 차단 |
| `next({ context: ... })` 대신 암묵적으로 context를 변형함? | 차단 |
| 공통 auth/logging/tenant 로직을 middleware 대신 각 handler에 중복함? | 경고. middleware 우선 |
---
## 허용 패턴
- server function middleware가 데이터 변환 또는 검증을 책임질 때 `.inputValidator(...)`를 사용합니다
- Middleware `.inputValidator(...)`와 server-function `.inputValidator(...)`를 혼동하지 않습니다. method name은 같지만 서로 다른 API입니다.
- `next({ context: { ... } })`로 context를 확장합니다
- client middleware의 `sendContext`는 서버에 정말 필요한 데이터만 전송합니다
- 클라이언트가 보낸 `sendContext`는 서버에서 반드시 검증 후 신뢰합니다
- global request middleware는 `src/start.ts`에서 `createStart(() => ({ requestMiddleware: [...] }))`로 설정합니다
---
## `sendContext` 보안 규칙
클라이언트 context는 자동으로 신뢰할 수 없습니다.
잘못된 예:
```ts
const requestLogger = createMiddleware({ type: 'function' })
.client(async ({ next, context }) => {
return next({
sendContext: {
workspaceId: context.workspaceId,
},
})
})
.server(async ({ next, context }) => {
useWorkspace(context.workspaceId)
return next()
})
```
올바른 예:
```ts
const requestLogger = createMiddleware({ type: 'function' })
.client(async ({ next, context }) => {
return next({
sendContext: {
workspaceId: context.workspaceId,
},
})
})
.server(async ({ next, context }) => {
const workspaceId = zodValidator(z.string()).parse(context.workspaceId)
useWorkspace(workspaceId)
return next()
})
```
---
## 리뷰 체크리스트
- Request middleware는 function-only feature가 필요하지 않으면 `createMiddleware()`를 사용
- Server function middleware는 `createMiddleware({ type: 'function' })`를 사용
- Server function middleware는 middleware-owned data validation에 `.inputValidator(...)`를 사용
- 공통 request 로직이 middleware에 중앙화됨
- `sendContext`가 최소화되어 있고 서버에서 검증됨
- Context 확장이 명시적이고 typed 되어 있음
rules/middleware.md
# Middleware
> Middleware rules for validation, context propagation, and safe client-to-server data transfer
---
## Rule Classifications
| Rule | Classification | Enforcement |
|---|---|---|
| Request middleware uses `createMiddleware()` by default | Official | Do not force function-only syntax for request middleware |
| Server function middleware uses `createMiddleware({ type: 'function' })` | Official | Block wrong middleware type when `.client(...)`, `.inputValidator(...)`, or server-function-only behavior is used |
| Server function middleware validation uses `.inputValidator(...)` | Official | Keep middleware and server-function validation chains conceptually separate |
| `sendContext` is explicit and not automatic | Official | Validate before trust |
| Validate client-provided context server-side | Safety policy | Block unvalidated trust |
| Centralize shared auth/logging/tenant logic | Hypercore convention | Warn/fix in touched code |
---
## Core Rule
Middleware is not just for auth. It is the boundary where request context, validation, logging, and server-safe data propagation must be made explicit.
TanStack Start has two middleware types:
- Request middleware: `createMiddleware()` or `createMiddleware({ type: 'request' })`. It runs for server requests, server routes, SSR, and server functions and only has `.server(...)`.
- Server function middleware: `createMiddleware({ type: 'function' })`. It is for `createServerFn` middleware chains and may use `.client(...)`, `.server(...)`, and `.inputValidator(...)`.
---
## Non-Negotiable Rules
| Check | Rule |
|------|------|
| Request middleware written with function-only behavior? | BLOCKED. Use `createMiddleware({ type: 'function' })` |
| Server function middleware validation written as `.validator(...)`? | BLOCKED. Middleware uses `.inputValidator(...)`; server functions also use `.inputValidator(...)` on their own chain |
| Dynamic data sent from client via `sendContext` and used on the server without validation? | BLOCKED |
| Middleware mutates context implicitly instead of returning `next({ context: ... })`? | BLOCKED |
| Shared auth/logging/tenant logic duplicated across handlers instead of middleware? | WARNING. Prefer middleware |
---
## Approved Patterns
- Use `.inputValidator(...)` on server function middleware when the middleware owns data transformation or validation
- Do not conflate middleware `.inputValidator(...)` with server-function `.inputValidator(...)`; they share a method name but belong to separate APIs
- Use `next({ context: { ... } })` to extend context
- Use client middleware `sendContext` only for data that is actually needed on the server
- Validate client-provided `sendContext` on the server before trusting it
- Use `createStart(() => ({ requestMiddleware: [...] }))` in `src/start.ts` for global request middleware
---
## `sendContext` Security Rule
Client context is not automatically trusted.
Wrong:
```ts
const requestLogger = createMiddleware({ type: 'function' })
.client(async ({ next, context }) => {
return next({
sendContext: {
workspaceId: context.workspaceId,
},
})
})
.server(async ({ next, context }) => {
useWorkspace(context.workspaceId)
return next()
})
```
Right:
```ts
const requestLogger = createMiddleware({ type: 'function' })
.client(async ({ next, context }) => {
return next({
sendContext: {
workspaceId: context.workspaceId,
},
})
})
.server(async ({ next, context }) => {
const workspaceId = zodValidator(z.string()).parse(context.workspaceId)
useWorkspace(workspaceId)
return next()
})
```
---
## Review Checklist
- Request middleware uses `createMiddleware()` unless function-only features are needed
- Server function middleware uses `createMiddleware({ type: 'function' })`
- Server function middleware uses `.inputValidator(...)` for middleware-owned data validation
- Shared request logic is centralized in middleware
- `sendContext` is minimal and validated on the server
- Context extension is explicit and typed
rules/platform.ko.md
# Platform Setup
> Router, env, alias, 운영 인접 설정 규칙
---
## Rule Classifications
| Rule | Classification | Enforcement |
|---|---|---|
| `src/router.tsx`가 fresh-instance `getRouter()` export | Official | missing setup 차단 |
| server/client env boundary | Safety policy | secret leak 차단 |
| non-trivial app runtime env validation | Hypercore convention + Safety policy | warn 또는 `src/config/env.ts` scaffold 추가 |
| Vite version-aware path alias | Hypercore convention | touched code에서 수정 |
---
## Router 설정
- `src/router.tsx`는 반드시 `getRouter()`를 export해야 합니다
- `getRouter()`는 호출할 때마다 새로운 router instance를 생성해서 반환해야 합니다
- `scrollRestoration`, preload 기본값, cache 설정 같은 router-wide 동작은 여기서 설정합니다
---
## Environment 규칙
- 새 TanStack Start env scaffold에서는 `src/env/`, `src/env.ts`, `src/env.d.ts`를 만들지 않습니다.
- env 코드는 `src/config/` 아래에 유지하고, canonical validation module은 `src/config/env.ts`입니다.
- TanStack Start/Vite 프로젝트에서는 `@t3-oss/env-core`와 `zod`를 사용하고 `createEnv`로 scaffold합니다.
- 프로젝트가 Vite `envPrefix`를 명시적으로 바꾸지 않았다면 client 변수는 `clientPrefix: "VITE_"`로 설정합니다.
- `VITE_*` 변수는 client에 노출되므로 secret, token, private API key, password, database URL을 담으면 안 됩니다.
- 서버 전용 env는 `process.env`에 두고 server boundary 뒤에서 접근하며 `server`에 나열합니다.
- client-safe env는 `import.meta.env`에서 가져오고 `client`에 나열하며 public prefix를 사용합니다.
- 명시적인 build-time coverage가 필요하면 `runtimeEnvStrict`를 우선 사용하고, framework/runtime이 전체 env object를 안정적으로 제공할 때만 `runtimeEnv`를 사용합니다.
- shared config file이 server/client 양쪽에서 import될 수 있으면 `isServer: typeof window === "undefined"`를 포함합니다.
- 프로젝트에 문서화된 예외가 없으면 새 validation module에는 `emptyStringAsUndefined: true`를 설정합니다.
- 서버 변수 이름 자체가 client bundle에 노출되면 안 되는 경우에도 schema split은 `src/config/` 아래(예: `env.server.ts`, `env.client.ts`)에서 수행하고 `src/env/` 아래에는 만들지 않습니다.
Canonical starter shape:
```ts
// src/config/env.ts
import { createEnv } from "@t3-oss/env-core"
import * as z from "zod"
export const env = createEnv({
server: {
DATABASE_URL: z.url(),
},
clientPrefix: "VITE_",
client: {
VITE_PUBLIC_APP_URL: z.url(),
},
runtimeEnvStrict: {
DATABASE_URL: process.env.DATABASE_URL,
VITE_PUBLIC_APP_URL: import.meta.env.VITE_PUBLIC_APP_URL,
},
isServer: typeof window === "undefined",
emptyStringAsUndefined: true,
})
```
---
## Path Alias 규칙
- path alias는 암묵적으로 가정하지 말고 명시적으로 설정합니다
- Vite 8+: `resolve.tsconfigPaths: true` 우선
- Vite 7 이하: `vite-tsconfig-paths` 사용
- 저장소 전체에서 하나의 canonical alias 규칙을 유지합니다
---
## 운영 인접 패턴
- health/readiness endpoint는 server route로 허용됩니다
- sitemap/robots 생성은 prerender 설정 또는 server route를 사용할 수 있습니다
- integration/LLMO용 machine-readable endpoint는 명시적으로 필요할 때 허용됩니다
- observability hook, metrics, Sentry류 연동은 페이지 로직이 아니라 operations/platform 문서에 둡니다
---
## 리뷰 체크리스트
- `getRouter()`가 존재하고 새 instance를 반환함
- env 사용이 typed이고 경계가 안전함
- alias 설정이 사용 중인 Vite 버전과 맞음
- 운영 endpoint가 내부 앱 RPC와 섞이지 않음
rules/platform.md
# Platform Setup
> Router, environment, alias, and operations-adjacent setup rules
---
## Rule Classifications
| Rule | Classification | Enforcement |
|---|---|---|
| `src/router.tsx` exports fresh-instance `getRouter()` | Official | Block missing setup |
| Server/client env boundaries | Safety policy | Block secret leaks |
| Runtime env validation for non-trivial apps | Hypercore convention + Safety policy | Warn or add `src/config/env.ts` scaffold |
| Vite-version-aware path aliases | Hypercore convention | Fix when touched |
---
## Router Setup
- `src/router.tsx` must export `getRouter()`
- `getRouter()` must create and return a fresh router instance each call
- Router-wide behavior such as `scrollRestoration`, preload defaults, and cache settings belong here
---
## Environment Rules
- Do not create `src/env/`, `src/env.ts`, or `src/env.d.ts` for new TanStack Start env scaffolds.
- Keep env code under `src/config/`; the canonical validation module is `src/config/env.ts`.
- Use `@t3-oss/env-core` with `zod` for TanStack Start/Vite projects; scaffold with `createEnv`.
- Configure client variables with `clientPrefix: "VITE_"` unless the project has explicitly changed Vite `envPrefix`.
- `VITE_*` variables are client-exposed and must not contain secrets, tokens, private API keys, passwords, or database URLs.
- Server-only env vars stay in `process.env`, are accessed behind server boundaries, and are listed in `server`.
- Client-safe env vars come from `import.meta.env`, are listed in `client`, and use the public prefix.
- Prefer `runtimeEnvStrict` for explicit build-time coverage; otherwise use `runtimeEnv` only when the framework/runtime reliably provides the whole env object.
- Include `isServer: typeof window === "undefined"` when a shared config file can be imported from both server and client code.
- Set `emptyStringAsUndefined: true` for new validation modules unless the project has a documented reason not to.
- If sensitive server variable names must not ship to client bundles, split the schema under `src/config/` (for example `env.server.ts` and `env.client.ts`), not under `src/env/`.
Canonical starter shape:
```ts
// src/config/env.ts
import { createEnv } from "@t3-oss/env-core"
import * as z from "zod"
export const env = createEnv({
server: {
DATABASE_URL: z.url(),
},
clientPrefix: "VITE_",
client: {
VITE_PUBLIC_APP_URL: z.url(),
},
runtimeEnvStrict: {
DATABASE_URL: process.env.DATABASE_URL,
VITE_PUBLIC_APP_URL: import.meta.env.VITE_PUBLIC_APP_URL,
},
isServer: typeof window === "undefined",
emptyStringAsUndefined: true,
})
```
---
## Path Alias Rules
- Path aliases must be configured intentionally, not assumed
- Vite 8+: prefer `resolve.tsconfigPaths: true`
- Vite 7 and earlier: use `vite-tsconfig-paths`
- Keep one canonical alias convention in the repo
---
## Operations-Adjacent Patterns
- Health/readiness endpoints are allowed as server routes
- Sitemap/robots generation may use prerender config or server routes
- Machine-readable endpoints for integrations/LLMO are allowed when explicitly required
- Observability hooks, metrics, and Sentry-style integrations belong in operations/platform docs, not page logic
---
## Review Checklist
- `getRouter()` exists and returns a new instance
- Env usage is typed and boundary-safe
- Alias setup matches the Vite version in use
- Operational endpoints are not mixed with internal app RPC
rules/project-structure.ko.md
# Project Structure and Shared Folder Organization
> TanStack Start project shape, route-root discovery, generated route tree handling, Hypercore shared-folder grouping 규칙.
## Rule Classifications
| Rule | Classification | Enforcement |
|---|---|---|
| Start source와 route root는 `tanstackStart({ srcDirectory, router: { routesDirectory } })` 또는 defaults에서 도출 | Official | config가 다르면 `src/routes`를 hard-code하지 않음 |
| `src/router.tsx`가 `getRouter()`를 export하고 generated `routeTree.gen.ts`를 import | Official | `rules/platform.md`와 함께 확인 |
| `routeTree.gen.ts`는 Start/Router tooling이 생성 | Official + Safety policy | 일반 architecture work에서 수동 편집 금지 |
| `public/`, root `vite.config.ts`, `package.json`, `tsconfig.json`는 project-level surface로 유지 | Official/docs-derived | source folder 안의 app code처럼 이동하지 않음 |
| `src/modules`, `src/lib`, `src/db`, `src/server`, `src/integrations`, `src/config` 같은 shared folders | Hypercore convention | domain/runtime ownership을 nested folder로 표현 |
| server-only shared code는 compiler-recognized boundaries 뒤에 둠 | Safety policy | client-reachable secret/DB/privileged import 차단 |
| Server function wrapper와 server-only helper 분리 | Official + Safety policy + Hypercore convention | `.functions.ts` / `.server.ts` / schema split 적용 |
## Official Start Project Shape
기본 Start project shape는 source-rooted이며 route tree가 generated됩니다:
```text
src/
├── routes/
│ ├── __root.tsx
│ ├── index.tsx
│ └── example.tsx
├── router.tsx
├── routeTree.gen.ts
├── styles.css
└── types/
public/
vite.config.ts
package.json
tsconfig.json
```
해석:
- `src/routes`는 default route directory이며, config가 override하면 무조건적인 path가 아닙니다.
- `src/router.tsx`는 router creation을 담당하고 `getRouter()`를 export해야 합니다.
- `src/routeTree.gen.ts`는 generated file입니다. route 변경을 위해 수동 rewrite하지 않습니다.
- `public/`은 static assets용입니다.
- `vite.config.ts`에는 Start plugin과 route/source directory customization이 있습니다.
## Route Root Discovery
Folder structure를 강제하기 전에 Start plugin config를 확인합니다:
```ts
// vite.config.ts
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
export default defineConfig({
plugins: [
tanstackStart({
srcDirectory: 'src',
router: {
routesDirectory: 'routes',
},
}),
],
})
```
Default route root는 `src/routes`입니다. `srcDirectory` 또는 `router.routesDirectory`가 custom이면 config에서 실제 route root를 도출하고 review에 보고합니다.
## Route-Local Nested Organization
특정 route에만 존재하는 route-local organization은 route 근처에 둡니다. 기본 route folder는 얇게 유지합니다:
```text
<route-root>/<page>/
├── index.tsx # page UI
├── route.tsx # layout/beforeLoad/loader when needed
├── -components/
├── -hooks/
└── -sections/
```
`-functions/`는 domain module로 만들 필요가 없는 route-only server action에만 사용합니다:
```text
<route-root>/<page>/
└── -functions/
│ ├── <resource>.functions.ts # createServerFn wrappers; static import 가능
│ ├── <resource>.server.ts # DB/secret/filesystem/server-only helper
│ └── schemas.ts # route-local client-safe validation/types
```
이 shape는 Hypercore convention입니다. TanStack Router는 flat, directory, mixed route structures를 공식 지원하므로 flat route files를 official TanStack usage로 invalid라고 말하지 않습니다. Router의 `routeFileIgnorePrefix` 기본값은 `-`이므로 `-components`, `-hooks`, `-functions` 같은 route-local folders는 route file로 처리되지 않는 co-location 용도로 적합합니다.
Page UI composition과 route-specific orchestration은 route-local folders를 사용합니다. Publishing-only static pages에 empty folders를 강제하지 않습니다. Server function은 기본적으로 `src/modules/<domain>/<feature>/`에 두고, route-only action일 때만 route-local `-functions/`를 예외적으로 사용합니다.
Server function을 route-local exception으로 둘지 domain module로 승격할지는 reuse와 domain 범위로 판단합니다:
| 상황 | 위치 |
|---|---|
| 진짜 단일 route의 임시/고유 action만 사용 | `<route-root>/<page>/-functions/<resource>.functions.ts` |
| domain noun이 있거나 query key/cache/auth/permission이 필요 | `src/modules/<domain>/<feature>/<resource>.functions.ts` |
| 같은 route group의 여러 child route가 공유 | 기본은 `src/modules/<domain>/<feature>/`; 해당 route group과 분리할 수 없을 때만 parent `-functions/` |
| 서로 다른 route tree 또는 app-wide hook이 공유 | `src/modules/<domain>/<feature>/<resource>.functions.ts` |
| DB, secret, filesystem, privileged SDK helper | `*.server.ts` 또는 `src/db/<domain>/*.server.ts` |
| Zod schema, DTO, query key, formatter처럼 client-safe reuse | route-local `schemas.ts`, `src/modules/<domain>/<feature>/*.schemas.ts`, 또는 `src/lib/<domain>/...` |
## Shared Nested Folder Grouping
Routes를 가로질러 공유되는 code는 route root 밖에 두고, touched shared code를 추가하거나 재구성할 때는 nested logical grouping을 사용해야 합니다. 명시적 project exception을 기록하지 않는 한 `src/lib/foo.ts`, `src/modules/foo.ts`, `src/config/foo.ts` 같은 새 direct leaf file을 만들지 않습니다. Domain ownership, runtime boundary, dependency direction을 보여주는 `src/modules/<domain>/<feature>/foo.ts`, `src/lib/<domain>/foo.ts`, `src/db/<domain>/foo.server.ts`, `src/integrations/<provider>/client.server.ts` 같은 ownership folder를 사용합니다.
이 shared-folder shape는 Hypercore 또는 repo-local convention으로 label합니다(official TanStack requirement 아님). TanStack 공식 문서가 특정 `src/modules`, `src/lib`, `src/integrations` grouping을 요구하지 않기 때문입니다.
Naming decision:
- Domain-owned feature code는 `src/modules/<domain>/<feature>/`를 사용합니다. Server functions, server-only helpers, feature hooks, feature components, schemas, query keys, DTOs를 함께 담아도 좁은 service wrapper처럼 오해되지 않기 때문입니다.
- `src/services/`는 기본 domain layer로 사용하지 않습니다. Hooks, schemas, query keys, UI support가 RPC wrapper 옆에 함께 있을 때 이름이 너무 좁고 애매해집니다.
- External SDK/client adapters는 `src/integrations/<provider>/`를 사용합니다. Domain modules가 provider를 orchestration할 수는 있지만 provider-specific client가 domain workflow를 소유하지는 않습니다.
권장 Hypercore shape 예시:
```text
src/
├── lib/
│ ├── auth/
│ │ ├── session.ts
│ │ └── permissions.ts
│ └── cache/
│ └── query-keys.ts
├── modules/
│ ├── billing/
│ │ └── invoices/
│ │ ├── invoices.functions.ts # createServerFn wrappers; client/loader static import 가능
│ │ ├── invoices.server.ts # handler 내부에서만 import하는 server-only logic
│ │ ├── invoices.schemas.ts # shared validation schemas / serializable DTOs
│ │ ├── invoices-query-keys.ts # TanStack Query keys if shared across routes
│ │ ├── hooks/
│ │ └── components/
│ └── users/
│ └── profile/
│ ├── profile.functions.ts
│ ├── profile.server.ts
│ └── profile.schemas.ts
├── db/
│ ├── core/
│ │ └── client.server.ts
│ └── users/
│ └── user-repository.server.ts
├── integrations/
│ └── stripe/
│ ├── client.server.ts
│ └── webhook.schemas.ts
├── server/
│ ├── auth/
│ │ └── middleware.ts
│ └── csrf/
│ └── start.ts
└── config/
└── env.ts # platform/env validation entrypoint exception
```
Shared folder 책임:
| Folder | 목적 | Runtime boundary |
|---|---|---|
| `src/modules/<domain>/<feature>/` | domain feature ownership, cross-route server functions, query/mutation entrypoints, reusable feature hooks/components | `.functions.ts`는 static import 가능; privileged helper는 `.server.ts` |
| `src/lib/<domain>/` | cross-feature client-safe 또는 isomorphic helpers, formatters, permissions, low-level query key primitives | secret/DB import 금지. 필요하면 module `.server.ts` 또는 `src/db`로 split |
| `src/db/<domain>/` | DB client, repositories, ORM-specific mapping | 기본 server-only. route/client import 금지 |
| `src/integrations/<provider>/` | external SDK/client adapters, webhook schemas, provider-specific mapping | secret-bearing client는 `.server.ts`; domain workflow는 modules에서 orchestrate |
| `src/server/<area>/` | request middleware, server entry helpers, auth/session request utilities | server-only 또는 request-runtime only |
| `src/config/<area>/` | env/runtime config, feature flags, deployment config | public/private split 명확화 |
Direct leaf exception은 좁게 둡니다. `src/router.tsx`, generated `src/routeTree.gen.ts`, root `src/start.ts` 또는 `src/config/env.ts`처럼 framework/platform entrypoint로 이미 정해진 파일은 유지할 수 있습니다. 새 domain/shared code는 nested folder가 기본입니다.
## Server Function File Placement
다음 상황에서는 nested grouping을 선호합니다:
- 새 touched shared code가 그대로라면 `src/modules`, `src/lib`, `src/db`, `src/server`, `src/integrations`, `src/config` 아래 direct file로 놓이게 됨
- shared folder에 서로 다른 책임의 files가 세 개 이상 있음
- domain logic, provider integration, schemas, DTOs, query keys, permissions가 섞여 있음
- server-only helper와 client-safe helper가 혼동되기 쉬움
- route-local `-functions/`가 reusable domain module logic으로 커지고 있음
- 관련 없는 helpers가 나란히 있어 imports가 모호해짐
TanStack Start 공식 file organization guidance는 큰 앱에서 server function wrapper와 server-only helper를 분리합니다. Hypercore는 이를 nested domain folder 안에 적용합니다:
```text
src/modules/users/profile/
├── profile.functions.ts # createServerFn wrappers; route loader/component/hook에서 static import
├── profile.server.ts # DB/secret/filesystem access; handler 내부에서만 import
├── profile.schemas.ts # inputValidator schema, serializable DTO
└── profile-query-keys.ts # client-safe query keys
```
규칙:
- `.functions.ts`는 `createServerFn` exports만 두는 server RPC entrypoint입니다. Static import는 loader/component/hook에서 허용되지만 dynamic import는 피합니다.
- `.server.ts`는 DB, secrets, filesystem, privileged SDK를 포함할 수 있으며 client-reachable code에서 직접 import하지 않습니다.
- schema/type/query-key file은 client-safe로 유지합니다. server-only import를 섞지 않습니다.
- `index.ts` barrel은 safe exports와 server-only exports를 섞기 쉬우므로 `-functions/`와 `src/modules/<domain>/<feature>/`에서 만들지 않습니다.
- route-local `-functions/`가 여러 route에서 import되거나 domain noun/cache/auth/permission을 갖기 시작하면 `src/modules/<domain>/<feature>/`로 승격합니다.
## Boundary and Import Protection Notes
Folder name 자체는 runtime boundary를 강제하지 않습니다.
Privileged shared code에는 다음 중 하나 이상의 명시적 보호를 사용합니다:
- 적절한 경우 `.server.` file suffix
- `@tanstack/react-start/server-only` marker import
- server-only execution boundary용 `createServerOnlyFn`
- client-callable server RPC용 `createServerFn`
- 프로젝트가 더 강한 folder/package protection을 필요로 할 때 custom `importProtection` deny rules
Route loader 또는 client-reachable module이 DB clients, secret env, filesystem access, privileged SDK wrappers를 직접 import하지 않게 합니다.
## Hard Rules
| 확인 | 규칙 |
|---|---|
| `tanstackStart()` config가 `srcDirectory` 또는 `routesDirectory`를 customize했는데 review가 `src/routes`를 가정 | 실제 route root를 도출할 때까지 차단 |
| 일반 architecture change에서 `routeTree.gen.ts`를 수동 편집 | 차단 |
| Shared `src/modules` / `src/lib` layout을 official TanStack law처럼 제시 | 차단 |
| touched shared root가 exception 없이 `src/modules/foo.ts`, `src/lib/foo.ts`, `src/integrations/foo.ts` 같은 direct leaf file을 추가하려 함 | 경고. logical nested folder로 이동 |
| touched shared folder가 mixed server/client 또는 domain boundaries를 flat layout에 숨김 | 경고. nested grouping 권장 |
| server function wrapper가 server-only helper와 같은 generic file 또는 mixed barrel에 섞임 | 경고. `.functions.ts`와 `.server.ts`로 split |
| server function을 dynamic import하거나 `functions/index.ts` barrel을 통해 가져옴 | 경고. static direct import 사용 |
| server-only shared code가 client-reachable이거나 import protection이 없음 | 차단 |
## Review Checklist
- [ ] 실제 source root와 route root를 Start config 또는 documented defaults에서 도출함.
- [ ] `src/router.tsx`와 generated `routeTree.gen.ts`의 역할을 유지함.
- [ ] Route-local folders는 route-specific logic/UI/server integration이 있을 때만 사용함.
- [ ] Publishing-only pages에 empty route-local folders를 강제하지 않음.
- [ ] 새 touched shared code는 explicit exception이 없는 한 `src/modules`, `src/lib`, `src/db`, `src/server`, `src/integrations`, `src/config` 바로 아래 direct leaf file을 만들지 않음.
- [ ] Shared folders는 boundaries를 명확히 할 때 nested `src/modules`, `src/lib`, `src/db`, `src/server`, `src/integrations`, `src/config` grouping을 사용함.
- [ ] Server functions가 route-local exception인지 domain module인지 reuse/domain 범위로 판단됨.
- [ ] Server function wrapper는 `.functions.ts`, privileged helper는 `.server.ts`, schema/query-key는 client-safe file로 분리됨.
- [ ] `functions/index.ts` 또는 mixed `src/modules/<domain>/<feature>/index.ts` barrel을 만들지 않음.
- [ ] Official Start facts, Safety policy, Hypercore conventions를 별도로 label함.
- [ ] Server-only shared modules에 명시적 import/runtime protection이 있음.
rules/project-structure.md
# Project Structure and Shared Folder Organization
> TanStack Start project shape, route-root discovery, generated route tree handling, and Hypercore shared-folder grouping rules.
## Rule Classifications
| Rule | Classification | Enforcement |
|---|---|---|
| Start source and route root are derived from `tanstackStart({ srcDirectory, router: { routesDirectory } })` or defaults | Official | Do not hard-code `src/routes` when config differs |
| `src/router.tsx` exports `getRouter()` and imports generated `routeTree.gen.ts` | Official | Coordinate with `rules/platform.md` |
| `routeTree.gen.ts` is generated by Start/Router tooling | Official + Safety policy | Do not hand-edit for normal architecture work |
| `public/`, root `vite.config.ts`, `package.json`, and `tsconfig.json` remain project-level surfaces | Official/docs-derived | Do not move into source folders as app code |
| Shared folders such as `src/modules`, `src/lib`, `src/db`, `src/server`, `src/integrations`, and `src/config` | Hypercore convention | Express domain/runtime ownership with nested folders |
| Server-only shared code stays behind compiler-recognized boundaries | Safety policy | Block client-reachable secret/DB/privileged imports |
| Split server function wrappers from server-only helpers | Official + Safety policy + Hypercore convention | Apply `.functions.ts` / `.server.ts` / schema split |
## Official Start Project Shape
The default Start project shape is source-rooted and route-tree generated:
```text
src/
├── routes/
│ ├── __root.tsx
│ ├── index.tsx
│ └── example.tsx
├── router.tsx
├── routeTree.gen.ts
├── styles.css
└── types/
public/
vite.config.ts
package.json
tsconfig.json
```
Interpretation:
- `src/routes` is the default route directory, not an unconditional path if config overrides it.
- `src/router.tsx` owns router creation and should export `getRouter()`.
- `src/routeTree.gen.ts` is generated. Do not manually rewrite it to change routes.
- `public/` is for static assets.
- `vite.config.ts` is where the Start plugin and route/source directory customization live.
## Route Root Discovery
Before enforcing folder structure, inspect the Start plugin config:
```ts
// vite.config.ts
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
export default defineConfig({
plugins: [
tanstackStart({
srcDirectory: 'src',
router: {
routesDirectory: 'routes',
},
}),
],
})
```
Default route root is `src/routes`. If `srcDirectory` or `router.routesDirectory` is customized, derive the actual route root from config and report it in the review.
## Route-Local Nested Organization
Route-local organization belongs near the route when it exists only for that route. Keep the default route folder thin:
```text
<route-root>/<page>/
├── index.tsx # page UI
├── route.tsx # layout/beforeLoad/loader when needed
├── -components/
├── -hooks/
└── -sections/
```
Use `-functions/` only for route-only server actions that should not become a domain module:
```text
<route-root>/<page>/
└── -functions/
│ ├── <resource>.functions.ts # createServerFn wrappers; safe static imports
│ ├── <resource>.server.ts # DB/secret/filesystem/server-only helper
│ └── schemas.ts # route-local client-safe validation/types
```
This shape is a Hypercore convention. TanStack Router officially supports flat, directory, and mixed route structures, so do not call flat route files invalid official TanStack usage. Router's default `routeFileIgnorePrefix` is `-`, so `-components`, `-hooks`, and `-functions` are appropriate co-located folders that are not treated as route files.
Use route-local folders for page UI composition and route-specific orchestration. Do not force empty folders onto publishing-only static pages. Server functions live in `src/modules/<domain>/<feature>/` by default; use route-local `-functions/` only as an exception for route-only actions.
Decide whether server functions stay route-local or move to a domain module by reuse and domain scope:
| Situation | Location |
|---|---|
| Truly used only by a single route's temporary/specific action | `<route-root>/<page>/-functions/<resource>.functions.ts` |
| Has a domain noun or needs query keys/cache/auth/permissions | `src/modules/<domain>/<feature>/<resource>.functions.ts` |
| Shared by several child routes in the same route group | `src/modules/<domain>/<feature>/` by default; parent `-functions/` only when the function is inseparable from that route group |
| Shared across route trees or app-wide hooks | `src/modules/<domain>/<feature>/<resource>.functions.ts` |
| DB, secret, filesystem, privileged SDK helper | `*.server.ts` or `src/db/<domain>/*.server.ts` |
| Zod schema, DTO, query key, formatter, or client-safe reuse | Route-local `schemas.ts`, `src/modules/<domain>/<feature>/*.schemas.ts`, or `src/lib/<domain>/...` |
## Shared Nested Folder Grouping
Shared code that spans routes should live outside the route root and should use nested logical grouping when touched shared code is added or reorganized. Do not add new direct leaf files such as `src/lib/foo.ts`, `src/modules/foo.ts`, or `src/config/foo.ts` unless an explicit project exception is recorded. Use ownership folders such as `src/modules/<domain>/<feature>/foo.ts`, `src/lib/<domain>/foo.ts`, `src/db/<domain>/foo.server.ts`, or `src/integrations/<provider>/client.server.ts` to communicate domain ownership, runtime boundary, and dependency direction.
Label this shared-folder shape as a Hypercore or repo-local convention (not official TanStack requirement), because official TanStack docs do not require a specific `src/modules`, `src/lib`, or `src/integrations` grouping.
Naming decision:
- Use `src/modules/<domain>/<feature>/` for domain-owned feature code because it can hold server functions, server-only helpers, feature hooks, feature components, schemas, query keys, and DTOs without implying that everything is a narrow service wrapper.
- Do not use `src/services/` as the default domain layer. The name is too narrow for feature ownership and becomes ambiguous when hooks, schemas, query keys, and UI support live beside RPC wrappers.
- Use `src/integrations/<provider>/` for external SDK/client adapters. Domain modules may orchestrate providers, but provider-specific clients do not own domain workflows.
Recommended Hypercore shapes include:
```text
src/
├── lib/
│ ├── auth/
│ │ ├── session.ts
│ │ └── permissions.ts
│ └── cache/
│ └── query-keys.ts
├── modules/
│ ├── billing/
│ │ └── invoices/
│ │ ├── invoices.functions.ts # createServerFn wrappers; safe static imports from clients/loaders
│ │ ├── invoices.server.ts # server-only logic imported only inside handlers
│ │ ├── invoices.schemas.ts # shared validation schemas / serializable DTOs
│ │ ├── invoices-query-keys.ts # TanStack Query keys if shared across routes
│ │ ├── hooks/
│ │ └── components/
│ └── users/
│ └── profile/
│ ├── profile.functions.ts
│ ├── profile.server.ts
│ └── profile.schemas.ts
├── db/
│ ├── core/
│ │ └── client.server.ts
│ └── users/
│ └── user-repository.server.ts
├── integrations/
│ └── stripe/
│ ├── client.server.ts
│ └── webhook.schemas.ts
├── server/
│ ├── auth/
│ │ └── middleware.ts
│ └── csrf/
│ └── start.ts
└── config/
└── env.ts # platform/env validation entrypoint exception
```
Shared folder responsibilities:
| Folder | Purpose | Runtime boundary |
|---|---|---|
| `src/modules/<domain>/<feature>/` | Domain feature ownership, cross-route server functions, query/mutation entrypoints, reusable feature hooks/components | `.functions.ts` is safe to static import; privileged helpers are `.server.ts` |
| `src/lib/<domain>/` | Cross-feature client-safe or isomorphic helpers, formatters, permissions, low-level query key primitives | No secret/DB imports. Split into a module `.server.ts` or `src/db` when needed |
| `src/db/<domain>/` | DB clients, repositories, ORM-specific mapping | Server-only by default. Never import from routes/client code |
| `src/integrations/<provider>/` | External SDK/client adapters, webhook schemas, provider-specific mapping | Secret-bearing clients use `.server.ts`; domain workflows are orchestrated from modules |
| `src/server/<area>/` | Request middleware, server entry helpers, auth/session request utilities | Server-only or request-runtime only |
| `src/config/<area>/` | Env/runtime config, feature flags, deployment config | Keep public/private split explicit |
Keep direct leaf exceptions narrow. Framework/platform entrypoints such as `src/router.tsx`, generated `src/routeTree.gen.ts`, root `src/start.ts`, or `src/config/env.ts` can remain when the framework or project treats them as entrypoints. New domain/shared code defaults to nested folders.
## Server Function File Placement
Prefer nested grouping when:
- any new touched shared code would otherwise be placed as a direct file under `src/modules`, `src/lib`, `src/db`, `src/server`, `src/integrations`, or `src/config`
- a shared folder has three or more mixed-responsibility files
- domain logic, provider integration, schemas, DTOs, query keys, and permissions are mixed together
- server-only and client-safe helpers are easy to confuse
- route-local `-functions/` are growing into reusable domain module logic
- imports become ambiguous because unrelated helpers sit side by side
TanStack Start's official file organization guidance separates server function wrappers from server-only helpers in larger applications. Hypercore applies that pattern inside nested domain folders:
```text
src/modules/users/profile/
├── profile.functions.ts # createServerFn wrappers; static import from route loader/component/hook
├── profile.server.ts # DB/secret/filesystem access; imported only inside handlers
├── profile.schemas.ts # inputValidator schema, serializable DTO
└── profile-query-keys.ts # client-safe query keys
```
Rules:
- `.functions.ts` is a server RPC entrypoint containing `createServerFn` exports. Static imports from loaders/components/hooks are allowed; avoid dynamic imports.
- `.server.ts` may contain DB, secrets, filesystem, or privileged SDK access and must not be imported from client-reachable code.
- Schema/type/query-key files stay client-safe. Do not mix in server-only imports.
- Avoid `index.ts` barrels in `-functions/` and `src/modules/<domain>/<feature>/` because they can mix safe exports with server-only exports.
- Promote route-local `-functions/` to `src/modules/<domain>/<feature>/` when several routes import them or they gain domain nouns/cache/auth/permissions.
## Boundary and Import Protection Notes
Folder names do not enforce runtime boundaries by themselves.
Use one or more explicit protections for privileged shared code:
- `.server.` file suffix where appropriate
- `@tanstack/react-start/server-only` marker import
- `createServerOnlyFn` for server-only execution boundaries
- `createServerFn` for client-callable server RPC
- custom `importProtection` deny rules when the project needs stronger folder/package protection
Never let route loaders or client-reachable modules import DB clients, secret env, filesystem access, or privileged SDK wrappers directly.
## Hard Rules
| Check | Rule |
|---|---|
| Review assumes `src/routes` while `tanstackStart()` config customizes `srcDirectory` or `routesDirectory` | BLOCKED until actual route root is derived |
| Normal architecture change hand-edits `routeTree.gen.ts` | BLOCKED |
| Shared `src/modules` / `src/lib` layout is presented as official TanStack law | BLOCKED |
| Touched shared root would add a direct leaf file such as `src/modules/foo.ts`, `src/lib/foo.ts`, or `src/integrations/foo.ts` without an exception | WARNING. Move into a logical nested folder |
| Touched shared folder hides mixed server/client or domain boundaries in a flat layout | WARNING. Prefer nested grouping |
| Server function wrappers are mixed with server-only helpers in a generic file or mixed barrel | WARNING. Split into `.functions.ts` and `.server.ts` |
| Server functions are imported dynamically or through a `functions/index.ts` barrel | WARNING. Use static direct imports |
| Server-only shared code is client-reachable or lacks import protection | BLOCKED |
## Review Checklist
- [ ] Actual source root and route root were derived from Start config or documented defaults.
- [ ] `src/router.tsx` and generated `routeTree.gen.ts` roles are preserved.
- [ ] Route-local folders are used only when route-specific logic/UI/server integration exists.
- [ ] Publishing-only pages were not forced into empty route-local folders.
- [ ] New touched shared code avoids direct leaf files under `src/modules`, `src/lib`, `src/db`, `src/server`, `src/integrations`, or `src/config` unless an explicit exception is recorded.
- [ ] Shared folders use nested `src/modules`, `src/lib`, `src/db`, `src/server`, `src/integrations`, or `src/config` grouping when it clarifies boundaries.
- [ ] Server functions are classified as route-local exceptions or domain modules based on reuse/domain scope.
- [ ] Server function wrappers are `.functions.ts`, privileged helpers are `.server.ts`, and schema/query-key files are client-safe.
- [ ] No `functions/index.ts` or mixed `src/modules/<domain>/<feature>/index.ts` barrel was introduced.
- [ ] Official Start facts, Safety policy, and Hypercore conventions are labelled separately.
- [ ] Server-only shared modules have explicit import/runtime protection.
rules/routes.ko.md
# Route Structure
> route 조직, file-route lifecycle, search validation, hypercore page folder convention.
## Rule Classifications
| Rule | Classification | Enforcement |
|---|---|---|
| file route instance를 `Route`로 export | Official | 없으면 차단 |
| search params를 사용할 때 validation | Official + Safety policy | 사용자 입력이 동작에 영향 주면 차단 |
| `beforeLoad`가 `loader`보다 먼저 실행되는 lifecycle | Official | auth/context/redirect에 사용 |
| Router는 flat/directory 혼용 지원 | Official | flat route를 TanStack invalid라고 말하지 않음 |
| 앱 페이지 route-directory 선호 | Hypercore convention | official default 요청이 없으면 touched page에 적용 |
| interactive logic 또는 커지는 UI가 있는 페이지의 `-hooks/`, `-components/` | Hypercore convention | route-local orchestration 또는 UI extraction이 있으면 적용 |
| route-local server function exception용 `-functions/` | Hypercore convention + Safety policy | 기본은 domain module; route-only action만 local 유지 |
## Publishing-Only Exception
Publishing-only page는 interactive logic과 server integration이 없는 static display page입니다.
예: terms, privacy, about, 단순 marketing content.
- `-components/`, `-hooks/`, `-functions/`가 필요 없습니다.
- interactive logic을 추가하면 필요에 따라 `-hooks/`와 route-local component를 만듭니다.
- server integration을 추가할 때도 기본은 `src/modules/<domain>/<feature>/`의 server function을 route-local hook에서 호출하는 것입니다. 진짜 단일 route 전용 action만 `-functions/`에 둡니다.
## Hypercore Route Folder Shape
Global Start project structure, actual route-root discovery, generated `routeTree.gen.ts`, shared nested folder policy는 `rules/project-structure.ko.md`를 읽습니다.
```text
routes/<page>/
├── index.tsx # page UI
├── route.tsx # layout/beforeLoad/loader when needed
├── -components/ # route-local UI
├── -hooks/ # route-local state/query orchestration
└── -sections/ # large page sections when needed
```
Route-local server function exception:
```text
routes/<page>/
└── -functions/
├── <resource>.functions.ts
├── <resource>.server.ts
└── <resource>.schemas.ts
```
공식 TanStack Router는 flat route file도 지원합니다. 위 구조들은 hypercore maintainability convention입니다. `-components/`, `-hooks/`, `-functions/` 같은 `-` prefix folder는 Router의 default ignore-prefix와 맞아 route file generation에 포함되지 않는 co-location folder로 사용합니다.
## File Route Export
```typescript
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/users/')({
component: UsersPage,
})
```
- route instance는 `Route`로 export해야 합니다.
- `createFileRoute` path string은 router plugin 또는 CLI가 생성/갱신합니다.
## Route Lifecycle
| Step | Official behavior | Use for |
|---|---|---|
| `validateSearch` | matching/search validation 중 실행 | URL search state 파싱/검증 |
| `beforeLoad` | route loading 전 serial 실행 | Auth, redirects, context extension |
| `loader` | route loading phase에서 실행, cache/preload 가능 | Data loading; server-only로 취급 금지 |
| `pendingComponent` | threshold 기반 optional pending UI | 느린 critical loader UX |
| `errorComponent` | route lifecycle/render error 처리 | Recoverable route errors |
## Search Validation
search params를 사용하면 검증합니다.
Zod v4 official path:
```typescript
import { z } from 'zod'
const searchSchema = z.object({ page: z.number().default(1) })
export const Route = createFileRoute('/products/')({
validateSearch: searchSchema,
component: ProductsPage,
})
```
Zod v3 official path:
```typescript
import { zodValidator, fallback } from '@tanstack/zod-adapter'
import { z } from 'zod'
const searchSchema = z.object({ page: fallback(z.number(), 1).default(1) })
export const Route = createFileRoute('/products/')({
validateSearch: zodValidator(searchSchema),
component: ProductsPage,
})
```
프로젝트가 모든 버전에서 `zodValidator`를 표준화한다면 project note에 hypercore convention으로 표시합니다.
## Loader Boundary Rule
- TanStack Start loader는 isomorphic입니다.
- loader code에서 secret, database client, filesystem, privileged SDK에 직접 접근하지 않습니다.
- privileged work는 route-local exception인 `-functions/<resource>.functions.ts` 또는 기본 shared 위치인 `src/modules/<domain>/<feature>/<resource>.functions.ts`의 `createServerFn` 뒤로 옮깁니다.
- `*.functions.ts` handler 내부에서만 `*.server.ts` helper를 import하고, route/component/hook은 server function wrapper를 static import합니다.
## Validation Checklist
- [ ] touched file route가 `Route`를 export함.
- [ ] search params가 설치된 Zod version에 맞게 검증됨.
- [ ] auth/context/redirect는 필요한 경우 `beforeLoad`에 있음.
- [ ] loader code에 direct secret/DB/filesystem access가 없음.
- [ ] publishing-only page에 빈 route-local folder를 강제하지 않음.
- [ ] interactive logic이 있는 page는 route-local hooks/components를 갖거나 이유가 기록됨.
- [ ] route-local server functions가 `.functions.ts` / `.server.ts` / schema split을 따르거나 `src/modules/<domain>/<feature>/`로 승격됨.
rules/routes.md
# Route Structure
> Route organization, file-route lifecycle, search validation, and hypercore page folder conventions.
## Rule Classifications
| Rule | Classification | Enforcement |
|---|---|---|
| File route instance exported as `Route` | Official | Block if missing |
| Search params validated when consumed | Official + Safety policy | Block if unvalidated user input affects behavior |
| `beforeLoad` before `loader` lifecycle | Official | Use for auth/context/redirect decisions |
| Mixed flat/directory routes supported by Router | Official | Do not claim flat routes are invalid TanStack usage |
| Route-directory preference for app pages | Hypercore convention | Apply to touched app pages unless official defaults requested |
| `-hooks/` and `-components/` for pages with interactive logic or growing UI | Hypercore convention | Apply when route-local orchestration or UI extraction exists |
| `-functions/` only for route-local server function exceptions | Hypercore convention + Safety policy | Use domain modules by default; keep route-only actions local |
## Publishing-Only Exception
Publishing-only pages are static display pages with no interactive logic and no server integration.
Examples: terms, privacy, about, simple marketing content.
- They do **not** require `-components/`, `-hooks/`, or `-functions/`.
- If interactive logic is added, create `-hooks/` and route-local components as needed.
- When server integration is added, the default is to call server functions from `src/modules/<domain>/<feature>/` via route-local hooks. Use `-functions/` only for truly single-route actions.
## Hypercore Route Folder Shape
For global Start project structure, actual route-root discovery, generated `routeTree.gen.ts`, and shared nested folder policy, read `rules/project-structure.md`.
```text
routes/<page>/
├── index.tsx # page UI only
├── route.tsx # layout/beforeLoad/loader when needed
├── -components/ # page-local components when UI grows or repeats
├── -hooks/ # page-local interactive/query orchestration
└── -sections/ # optional for large page sections
```
Route-local server function exception:
```text
routes/<page>/
└── -functions/
├── <resource>.functions.ts
├── <resource>.server.ts
└── <resource>.schemas.ts
```
Official TanStack Router supports flat route files. The shapes above are hypercore maintainability conventions. `-`-prefixed folders such as `-components/`, `-hooks/`, and `-functions/` align with Router's default ignore prefix and are used as co-location folders that route generation does not treat as route files.
## File Route Export
```typescript
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/users/')({
component: UsersPage,
})
```
- The route instance must be exported as `Route`.
- `createFileRoute` path strings are generated/updated by the router plugin or CLI.
## Route Lifecycle
| Step | Official behavior | Use for |
|---|---|---|
| `validateSearch` | Runs during matching/search validation | Parse and validate URL search state |
| `beforeLoad` | Runs serially before route loading | Auth, redirects, context extension |
| `loader` | Runs in route loading phase and can be cached/preloaded | Data loading; do not treat as server-only |
| `pendingComponent` | Optional threshold-based pending UI | Slow critical loader UX |
| `errorComponent` | Handles route lifecycle/render errors | Recoverable route errors |
## Search Validation
When a route consumes search params, validate them.
Zod v4 official path:
```typescript
import { z } from 'zod'
const searchSchema = z.object({
page: z.number().default(1),
})
export const Route = createFileRoute('/products/')({
validateSearch: searchSchema,
component: ProductsPage,
})
```
Zod v3 official path:
```typescript
import { zodValidator, fallback } from '@tanstack/zod-adapter'
import { z } from 'zod'
const searchSchema = z.object({
page: fallback(z.number(), 1).default(1),
})
export const Route = createFileRoute('/products/')({
validateSearch: zodValidator(searchSchema),
component: ProductsPage,
})
```
If a project standardizes on `zodValidator` for all versions, label that as a hypercore convention in the project notes.
## Loader Boundary Rule
- Loaders are isomorphic in TanStack Start.
- Do not access secrets, database clients, filesystem, or privileged SDKs directly in loader code.
- Move privileged work behind `createServerFn` in route-local exception `-functions/<resource>.functions.ts` or the default shared location `src/modules/<domain>/<feature>/<resource>.functions.ts`.
- Import `*.server.ts` helpers only inside `*.functions.ts` handlers; routes/components/hooks statically import the server function wrapper.
## Validation Checklist
- [ ] Touched file routes export `Route`.
- [ ] Search params are validated with a pattern appropriate to the installed Zod version.
- [ ] `beforeLoad` holds auth/context/redirect logic that must run serially.
- [ ] Loader code contains no direct secret/DB/filesystem access.
- [ ] Publishing-only pages were not forced into empty route-local folders.
- [ ] Pages with interactive logic have route-local hooks/components or a documented reason not to.
- [ ] Route-local server functions use `.functions.ts` / `.server.ts` / schema split or have been promoted to `src/modules/<domain>/<feature>/`.
rules/server-routes.ko.md
# Server Routes
> TanStack Start server route는 공식 HTTP endpoint 기능입니다. hypercore는 실제 HTTP semantics가 있을 때 사용합니다.
## Rule Classifications
| Rule | Classification | Enforcement |
|---|---|---|
| `createFileRoute(... )({ server })`로 정의하는 server route | Official | 허용 |
| simple handlers는 `server.handlers`, composed handlers는 `createHandlers` function 사용 | Official | 현재 handler shape 사용 |
| Route-level middleware는 `server.middleware`로 선언 가능 | Official | 모든 handler가 request behavior를 공유할 때 적용 |
| webhook/file/health/auth/public machine endpoint | Official + Hypercore convention | justification 있으면 허용 |
| duplicate route path + HTTP method handlers | Official | collision 차단 |
| internal app RPC를 server route로 구현 | Hypercore convention | server function 선호 |
| 검증 없는 request body 신뢰 | Safety policy | trust 전 validation |
## Current Server Route Shape
Server routes는 TanStack Router file-route convention을 따릅니다. `createFileRoute(...)(...)`에 `server` property가 있으면 API route가 됩니다.
Simple handlers는 `server.handlers` object를 사용합니다:
```ts
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/hello')({
server: {
handlers: {
GET: async ({ request }) => {
return new Response('Hello, World! from ' + request.url)
},
},
},
})
```
Handlers에 middleware composition이 필요하면 current server-routes guide의 `createHandlers` function form을 사용합니다. 동일 route-level middleware가 모든 handlers에 적용되어야 하면 `server.middleware`를 사용합니다.
같은 resolved route path에 duplicate methods를 만들지 않습니다. `users.ts`와 `users.index.ts` 같은 file-route variants는 같은 API route로 resolve될 수 있으며 duplicate HTTP methods는 invalid입니다. wildcard/splat server routes는 `routes/file/$.ts`처럼 trailing `$` convention을 사용합니다.
## Allowed Uses
단순 app-internal RPC가 아니라 HTTP semantics가 있을 때 server route를 사용합니다:
- Third-party webhook.
- Auth provider callback 또는 required auth endpoint.
- Health/readiness endpoint.
- File upload/download 또는 wildcard HTTP handler.
- `robots.txt`, `sitemap.xml`, LLMO/metadata endpoint.
- Public machine-readable resource.
## Prefer Server Functions For
- React component 또는 route loader가 소비하는 app read/mutation.
- End-to-end typing과 server function middleware가 유리한 internal RPC.
- TanStack Query invalidation pattern을 공유해야 하는 operation.
## Validation Checklist
- [ ] 새 server route마다 HTTP justification이 있음.
- [ ] Simple server routes는 `server.handlers` object를 사용하고, composed handlers는 current `createHandlers` function form을 사용함.
- [ ] `server.middleware`는 모든 handler가 공유하는 route-level behavior에만 사용함.
- [ ] Duplicate route path + HTTP method collision을 확인함.
- [ ] Wildcard/splat routes는 필요할 때 trailing `$` file-route convention을 사용함.
- [ ] request body, params, headers, client-sent context를 trust 전에 검증함.
- [ ] user가 HTTP endpoint를 명시 요청하지 않았다면 internal app RPC는 server function을 사용함.
- [ ] 필요한 경우 route/handler level middleware가 적용됨.
rules/server-routes.md
# Server Routes
> TanStack Start server routes are official HTTP endpoints; hypercore reserves them for actual HTTP semantics.
## Rule Classifications
| Rule | Classification | Enforcement |
|---|---|---|
| Server routes defined with `createFileRoute(... )({ server })` | Official | Allowed |
| Simple handlers use `server.handlers`; composed handlers use `createHandlers` | Official | Use the current handler shape |
| Route-level middleware can be declared with `server.middleware` | Official | Apply when all handlers share request behavior |
| Server routes for webhooks/files/health/auth/public machine endpoints | Official + Hypercore convention | Allowed with justification |
| Duplicate route path + HTTP method handlers | Official | Block collisions |
| Internal app RPC implemented as server route | Hypercore convention | Prefer server function |
| Unvalidated request body in server route | Safety policy | Validate before trust |
## Current Server Route Shape
Server routes follow TanStack Router file-route conventions. A route becomes an API route when `createFileRoute(...)(...)` includes a `server` property.
Simple handlers use a `server.handlers` object:
```ts
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/hello')({
server: {
handlers: {
GET: async ({ request }) => {
return new Response('Hello, World! from ' + request.url)
},
},
},
})
```
When handlers need middleware composition, use the `createHandlers` function form documented by the current server-routes guide. Use `server.middleware` when the same route-level middleware applies to all handlers.
Do not create duplicate methods for the same resolved route path. File-route variants such as `users.ts` and `users.index.ts` can resolve to the same API route; duplicate HTTP methods are invalid. wildcard/splat server routes use the trailing `$` convention, such as `routes/file/$.ts`.
## Allowed Uses
Use server routes when the endpoint has HTTP semantics that are not just app-internal RPC:
- Third-party webhooks.
- Auth provider callbacks or required auth endpoints.
- Health/readiness endpoints.
- File upload/download or wildcard HTTP handlers.
- `robots.txt`, `sitemap.xml`, LLMO/metadata endpoints.
- Public machine-readable resources.
## Prefer Server Functions For
- App reads/mutations consumed by React components or route loaders.
- Internal RPC that benefits from end-to-end typing and Start server function middleware.
- Operations that should share TanStack Query invalidation patterns.
## Validation Checklist
- [ ] Every new server route states its HTTP justification.
- [ ] Simple server routes use a `server.handlers` object; composed handlers use the current `createHandlers` function form.
- [ ] `server.middleware` is used only for route-level behavior shared by all handlers.
- [ ] Duplicate route path + HTTP method collisions were checked.
- [ ] Wildcard/splat routes use the trailing `$` file-route convention when needed.
- [ ] Request bodies, params, headers, and client-sent context are validated before trust.
- [ ] Internal app RPC uses server functions unless the user explicitly requested HTTP endpoints.
- [ ] Server route middleware is applied at route or handler level where needed.
rules/services.ko.md
# Server Functions and Domain Modules
> Server function API 사용, runtime validation, route/modules/lib/database layering 규칙.
## Rule Classifications
| Rule | Classification | Enforcement |
|---|---|---|
| client-callable server RPC는 `createServerFn` 사용 | Official | server RPC에 필요 |
| canonical validation API는 `.inputValidator(...)` | Official + Drift note | installed types가 다르지 않으면 `.validator(...)` 차단 |
| mutation input runtime validation | Safety policy | POST/PUT/PATCH validation 없으면 차단 |
| chain에서 handler는 마지막 | Official/API shape | malformed chain 차단 |
| non-trivial logic은 domain module/lib layer | Hypercore convention | touched non-trivial logic에 적용 |
| server function wrapper와 server-only helper 분리 | Official + Safety policy | `.functions.ts`와 `.server.ts` 역할 분리 |
| `functions/index.ts` barrel 금지 | Hypercore convention + Safety policy | import-protection/tree-shaking ambiguity 방지 |
| server functions는 same-origin app RPC | Official + Safety policy | public/cross-origin HTTP endpoint는 server route 사용 |
`.inputValidator()`와 stale `.validator()` 예시는 `references/official/api-drift-notes.md`를 봅니다.
## Canonical Server Function Pattern
```typescript
import { createServerFn } from '@tanstack/react-start'
import { z } from 'zod'
const createUserSchema = z.object({
email: z.email(),
name: z.string().min(1),
})
export const createUser = createServerFn({ method: 'POST' })
.inputValidator(createUserSchema)
.middleware([authMiddleware])
.handler(async ({ data, context }) => {
return createUserMutation({ data, user: context.user })
})
```
Notes:
- 현재 canonical guide에서 `inputValidator`는 Zod schema를 직접 받을 수 있습니다.
- middleware와 input validation 순서는 바뀔 수 있지만 `handler`는 chain 마지막입니다.
- project-local installed version이 다르면 typecheck로 확인하고 예외를 기록합니다.
- Server function은 app same-origin RPC입니다. public API, webhook, cross-origin endpoint, raw HTTP semantics가 필요하면 `rules/server-routes.ko.md`에 따라 server route를 사용합니다.
## Server Function File Organization
TanStack Start 공식 guidance는 큰 앱에서 server function wrapper와 server-only helper를 분리합니다. Hypercore는 이 패턴을 route-local `-functions/` exception과 shared `src/modules/<domain>/<feature>/` nested folder에 적용합니다.
Route-local exception 예시:
```text
src/routes/billing/
├── route.tsx
├── index.tsx
├── -hooks/
│ └── use-invoices.ts
└── -functions/
├── invoices.functions.ts
├── invoices.server.ts
└── invoices.schemas.ts
```
Default domain module 예시:
```text
src/modules/billing/invoices/
├── invoices.functions.ts
├── invoices.server.ts
├── invoices.schemas.ts
├── invoices-query-keys.ts
├── hooks/
└── components/
```
역할:
| File | Import 가능 위치 | 허용 내용 |
|---|---|---|
| `*.functions.ts` | loader, component, hook, 다른 server function에서 static import | `createServerFn` wrapper, middleware/inputValidator/handler chain |
| `*.server.ts` | `*.functions.ts` handler 내부 또는 server-only module | DB, secrets, filesystem, privileged SDK, internal business logic |
| `*.schemas.ts` / `schemas.ts` | client/server 모두 | Zod schemas, serializable DTOs, constants |
| `*-query-keys.ts` | client/server 모두 | TanStack Query key builders, cache tags |
규칙:
- server function은 dynamic import하지 않습니다. Client bundle rewrite와 import protection 추적을 위해 direct static import를 사용합니다.
- `*.functions.ts`는 server-only helper를 handler 밖 surviving export에서 참조하지 않습니다.
- safe exports와 `.server.ts` exports를 같은 `index.ts` barrel에서 re-export하지 않습니다.
- route-local `-functions/`가 cross-route reuse, domain noun, cache/auth/permission 책임을 얻으면 `src/modules/<domain>/<feature>/`로 승격합니다.
- shared domain code는 domain/feature 단위 nested folder를 사용합니다. `src/modules/foo.ts` direct leaf를 새로 만들지 않습니다.
- external provider client는 domain module에 섞지 않고 `src/integrations/<provider>/` 또는 server-only module로 분리합니다.
## Layering
```text
Route / hook / query
-> routes/<page>/-functions/<resource>.functions.ts
또는 src/modules/<domain>/<feature>/<resource>.functions.ts
-> src/modules/<domain>/<feature>/<resource>.server.ts
-> src/lib/<domain>/shared helpers, src/db/<domain>/repositories,
또는 src/integrations/<provider>/server-only clients
-> database/ORM client 또는 external SDK
```
- **Safety policy:** route는 database/ORM client를 직접 import하지 않습니다.
- **Safety policy:** `*.server.ts` 또는 DB/repository imports는 client-reachable file에 살아남지 않게 합니다.
- **Hypercore convention:** non-trivial business logic은 route file이 아니라 `modules/<domain>/<feature>/` 또는 domain-specific `lib/<domain>/` folders에 둡니다.
- **Hypercore convention:** extraction이 noise라면 simple CRUD는 server function에 남길 수 있습니다.
## Query and Mutation Pattern
- Reads: 안전하고 cache semantic이 맞으면 GET server function 사용.
- Mutations: POST/PUT/PATCH + runtime `inputValidator`.
- Client hook은 보통 `useServerFn`과 TanStack Query로 server function/cache invalidation을 감쌉니다.
- Loader는 React component가 아니므로 server function을 직접 호출할 수 있습니다.
- Auth-required server function은 route `beforeLoad`만 믿지 않습니다. Server function 자체에 middleware 또는 handler-level auth check를 둡니다.
- Custom `src/start.ts`를 정의했다면 server function CSRF request middleware가 유지되는지 확인합니다.
- User/session/tenant에 의존하는 GET server function은 public cache header를 쓰지 않습니다. 응답 cache policy는 identity dependency를 기준으로 정합니다.
## Validation Checklist
- [ ] 새 mutation server function에 `.inputValidator(...)`가 있음.
- [ ] 새 `.validator(...)` 사용이 없거나 installed package types로 정당화됨.
- [ ] `handler`가 chain 마지막임.
- [ ] auth-required server function이 middleware 또는 equivalent checked boundary를 사용함.
- [ ] `*.functions.ts`와 `*.server.ts`가 분리되어 있고 server-only import가 recognized boundary 밖에 살아남지 않음.
- [ ] server functions가 direct static import되며 dynamic import나 mixed barrel을 통하지 않음.
- [ ] public/cross-origin/raw HTTP endpoint는 server function이 아니라 server route로 구현됨.
- [ ] custom `src/start.ts`가 있으면 server function CSRF middleware를 보존함.
- [ ] route가 ORM/database client에 직접 접근하지 않음.
- [ ] non-trivial logic이 `modules/<domain>/<feature>/` 또는 domain-specific `lib/<domain>/` folders로 분리됨.
- [ ] `functions/index.ts` barrel export를 만들지 않음.
rules/services.md
# Server Functions and Domain Modules
> Server function API usage, runtime validation, and hypercore layering between routes, modules, lib helpers, integrations, and database access.
## Rule Classifications
| Rule | Classification | Enforcement |
|---|---|---|
| Use `createServerFn` for client-callable server RPC | Official | Required for server RPC |
| Use `.inputValidator(...)` as canonical validation API | Official + Drift note | Block new `.validator(...)` unless installed types prove otherwise |
| Validate mutation input at runtime | Safety policy | Block POST/PUT/PATCH without validation |
| Handler last in chain | Official/API shape | Block malformed chain |
| Domain module/lib layer for non-trivial logic | Hypercore convention | Apply to touched non-trivial logic |
| Split server function wrappers from server-only helpers | Official + Safety policy | Keep `.functions.ts` and `.server.ts` roles separate |
| No `functions/index.ts` barrel | Hypercore convention + Safety policy | Avoid import-protection/tree-shaking ambiguity |
| Server functions are same-origin app RPC | Official + Safety policy | Use server routes for public/cross-origin HTTP endpoints |
See `references/official/api-drift-notes.md` for `.inputValidator()` vs stale `.validator()` examples.
## Canonical Server Function Pattern
```typescript
import { createServerFn } from '@tanstack/react-start'
import { z } from 'zod'
const createUserSchema = z.object({
email: z.email(),
name: z.string().min(1),
})
export const createUser = createServerFn({ method: 'POST' })
.inputValidator(createUserSchema)
.middleware([authMiddleware])
.handler(async ({ data, context }) => {
return createUserMutation({ data, user: context.user })
})
```
Notes:
- `inputValidator` can accept Zod schemas directly in the canonical current guide.
- Middleware and input validation order can vary; `handler` must finish the chain.
- If a project-local installed version disagrees, verify with typecheck and record the exception.
- Server functions are same-origin app RPC. Use server routes for public APIs, webhooks, cross-origin endpoints, or raw HTTP semantics under `rules/server-routes.md`.
## Server Function File Organization
TanStack Start's official guidance separates server function wrappers from server-only helpers for larger applications. Hypercore applies this pattern inside route-local `-functions/` exceptions and shared `src/modules/<domain>/<feature>/` nested folders.
Route-local exception example:
```text
src/routes/billing/
├── route.tsx
├── index.tsx
├── -hooks/
│ └── use-invoices.ts
└── -functions/
├── invoices.functions.ts
├── invoices.server.ts
└── invoices.schemas.ts
```
Default domain module example:
```text
src/modules/billing/invoices/
├── invoices.functions.ts
├── invoices.server.ts
├── invoices.schemas.ts
├── invoices-query-keys.ts
├── hooks/
└── components/
```
Roles:
| File | Importable from | Allowed contents |
|---|---|---|
| `*.functions.ts` | Static imports from loaders, components, hooks, or other server functions | `createServerFn` wrappers, middleware/inputValidator/handler chains |
| `*.server.ts` | Inside `*.functions.ts` handlers or server-only modules | DB, secrets, filesystem, privileged SDKs, internal business logic |
| `*.schemas.ts` / `schemas.ts` | Client and server | Zod schemas, serializable DTOs, constants |
| `*-query-keys.ts` | Client and server | TanStack Query key builders, cache tags |
Rules:
- Do not dynamically import server functions. Use direct static imports so client-bundle rewrites and import protection remain traceable.
- `*.functions.ts` must not reference server-only helpers from surviving exports outside handlers.
- Do not re-export safe exports and `.server.ts` exports through the same `index.ts` barrel.
- Promote route-local `-functions/` to `src/modules/<domain>/<feature>/` when cross-route reuse, domain nouns, cache/auth, or permission responsibilities appear.
- Shared domain code uses nested domain/feature folders. Do not add new direct leaves such as `src/modules/foo.ts`.
- Keep external provider clients out of domain modules when possible; put them under `src/integrations/<provider>/` or a server-only module.
## Layering
```text
Route / hook / query
-> routes/<page>/-functions/<resource>.functions.ts
or src/modules/<domain>/<feature>/<resource>.functions.ts
-> src/modules/<domain>/<feature>/<resource>.server.ts
-> src/lib/<domain>/shared helpers, src/db/<domain>/repositories,
or src/integrations/<provider>/server-only clients
-> database/ORM client or external SDK
```
- **Safety policy:** routes do not import database/ORM clients directly.
- **Safety policy:** `*.server.ts` or DB/repository imports must not survive in client-reachable files.
- **Hypercore convention:** non-trivial business logic belongs in `modules/<domain>/<feature>/` or domain-specific `lib/<domain>/` folders, not route files.
- **Hypercore convention:** simple CRUD can stay in a server function if extraction would add noise.
## Query and Mutation Pattern
- Reads: use GET server functions when safe and cache semantics are appropriate.
- Mutations: use POST/PUT/PATCH with runtime `inputValidator`.
- Client hooks should usually wrap server functions with `useServerFn` and TanStack Query for cache invalidation.
- Loaders may directly call server functions because route lifecycle code is not a React component.
- Auth-required server functions must not rely only on route `beforeLoad`; add middleware or handler-level auth checks to the server function itself.
- If a custom `src/start.ts` exists, confirm server-function CSRF request middleware is preserved.
- GET server functions that depend on user/session/tenant data must not set public cache headers. Choose response cache policy from identity dependency.
## Validation Checklist
- [ ] New mutation server functions have `.inputValidator(...)`.
- [ ] New `.validator(...)` usage is absent or justified by installed package types.
- [ ] `handler` is last in the chain.
- [ ] Auth-required server functions use middleware or an equivalent checked boundary.
- [ ] `*.functions.ts` and `*.server.ts` are split, and server-only imports do not survive outside recognized boundaries.
- [ ] Server functions are direct static imports, not dynamic imports or mixed-barrel imports.
- [ ] Public/cross-origin/raw HTTP endpoints use server routes, not server functions.
- [ ] Custom `src/start.ts` preserves server-function CSRF middleware when present.
- [ ] Routes do not access ORM/database clients directly.
- [ ] Non-trivial logic is delegated to `modules/<domain>/<feature>/` or domain-specific `lib/<domain>/` folders.
- [ ] No `functions/index.ts` barrel export was introduced.
rules/ssr-hydration.ko.md
# SSR And Hydration
> 라우트 SSR 모드와 hydration 안전성 규칙
---
## Rule Classifications
| Rule | Classification | Enforcement |
|---|---|---|
| route SSR option과 `ClientOnly`는 official Start concept | Official | deliberate usage |
| deterministic first render | Safety policy | hydration-unsafe output 차단 |
| SSR disable 전 stabilization 선호 | Hypercore convention | touched route에 적용 |
---
## 핵심 규칙
서버 HTML과 클라이언트 첫 렌더가 달라질 수 있으면, 단순 경고가 아니라 설계 문제로 취급해야 합니다.
---
## 비타협 규칙
| 확인 항목 | 규칙 |
|------|------|
| 첫 렌더에서 `Date.now()`, random ID, locale 의존 텍스트, viewport 분기 같은 불안정 값을 직접 렌더함? | 안정화되지 않았다면 차단 |
| 브라우저 전용 위젯을 `ClientOnly`나 SSR 제한 없이 SSR에 렌더함? | 차단 |
| `ssr: false` 또는 `ssr: 'data-only'`를 fallback 전략 없이 사용함? | 차단 |
| 루트에서 SSR을 끄면서 `shellComponent` 동작을 이해하지 못함? | 차단 |
---
## 선호하는 해결 순서
1. 서버와 클라이언트 출력이 결정적으로 같게 만든다
2. 서버에서 한 번 계산해서 loader data로 hydration한다
3. 진짜 브라우저 전용 UI만 `ClientOnly`로 감싼다
4. 꼭 필요할 때만 route `ssr: 'data-only'` 또는 `ssr: false`를 쓴다
---
## 허용 패턴
- locale/timezone 민감 UI는 cookie 기반의 결정적 서버 값을 사용합니다
- hydration 후 클라이언트 환경을 cookie로 저장해 이후 SSR 요청에 활용할 수 있습니다
- 불안정한 위젯은 `ClientOnly`로 감쌀 수 있습니다
- SSR 모드가 렌더링 동작을 바꾸는 라우트에는 `pendingComponent`를 둡니다
- 루트 라우트에서 SSR을 줄여도 `shellComponent`는 HTML shell을 렌더한다는 점을 이해해야 합니다
---
## 리뷰 체크리스트
- hydration에 unsafe한 첫 렌더 출력이 없음
- `ClientOnly`가 무분별한 탈출구가 아니라 의도적으로 쓰였음
- 불안정 라우트의 `ssr` 모드가 명시적임
- SSR 축소 라우트의 fallback/shell 동작을 이해하고 있음
rules/ssr-hydration.md
# SSR And Hydration
> Route SSR mode and hydration-safety rules
---
## Rule Classifications
| Rule | Classification | Enforcement |
|---|---|---|
| Route SSR options and `ClientOnly` are official Start concepts | Official | Use deliberately |
| Deterministic first render | Safety policy | Block hydration-unsafe output |
| Prefer stabilization before disabling SSR | Hypercore convention | Apply to touched routes |
---
## Core Rule
If server HTML and client render can differ, treat it as a design problem, not a harmless warning.
---
## Non-Negotiable Rules
| Check | Rule |
|------|------|
| Component renders unstable values on first render (`Date.now()`, random IDs, locale-dependent text, viewport-only branching)? | BLOCKED unless stabilized |
| Browser-only widget rendered during SSR without `ClientOnly` or SSR restriction? | BLOCKED |
| Route uses `ssr: false` or `ssr: 'data-only'` without a deliberate fallback strategy? | BLOCKED |
| Root disables SSR without understanding `shellComponent` behavior? | BLOCKED |
---
## Preferred Fix Order
1. Make server and client output deterministic
2. Compute once on the server and hydrate from loader data
3. Use `ClientOnly` for genuinely browser-only UI
4. Use route `ssr: 'data-only'` or `ssr: false` only when needed
---
## Approved Patterns
- Locale/timezone-sensitive UI should use a deterministic server value, typically cookie-backed
- Client environment discovery may set cookies after hydration for future SSR requests
- Unstable widgets may be wrapped in `ClientOnly`
- Use `pendingComponent` when SSR mode changes route rendering behavior
- If the root route limits SSR, understand that `shellComponent` still renders the HTML shell
---
## Review Checklist
- No hydration-unsafe first render output
- `ClientOnly` is used intentionally, not as a blanket escape hatch
- `ssr` mode is explicit for unstable routes
- Fallback and shell behavior are understood for reduced SSR routes
rules/validation.ko.md
# Validation and Readback
> TanStack Start architecture 작업과 이 스킬 자체 유지보수 완료 검증.
## Project Work Validation
변경 표면에 맞는 check를 실행합니다:
```bash
rg -n "const Route = createFileRoute|export const Route" src/routes 2>/dev/null
rg -n "from ['\"]@/database|from ['\"].*/database|@prisma/client|drizzle-orm" src/routes 2>/dev/null
rg -n "\.validator\(|\.inputValidator\(|createServerFn" src 2>/dev/null
rg -n "server-only|client-only|\.server\.|\.client\.|importProtection|tanstackStart" vite.config.* src 2>/dev/null
rg -n "loader:|beforeLoad:|Date\.now\(|Math\.random\(|localStorage|window\." src/routes src/components 2>/dev/null
test ! -d src/env
test ! -f src/env.ts
test -f src/config/env.ts
rg -n "@t3-oss/env-core|createEnv" src/config/env.ts
rg -n "clientPrefix: ['\"]VITE_|runtimeEnvStrict|runtimeEnv|emptyStringAsUndefined|isServer" src/config/env.ts
rg -n "VITE_.*(SECRET|TOKEN|PASSWORD|DATABASE_URL|PRIVATE)" src/config/env.ts .env* 2>/dev/null
```
grep 결과만으로 판단하지 말고 topic rule file과 함께 해석합니다.
## Skill Anatomy Validation
이 스킬 자체를 수정한 경우:
```bash
find skills/tanstack-start-architecture -maxdepth 3 -type f | sort
wc -l skills/tanstack-start-architecture/SKILL.md skills/tanstack-start-architecture/SKILL.ko.md
rg -n 'architecture-rules|rules/|references/official' skills/tanstack-start-architecture/SKILL.md
rg -n 'last_verified_at|checked_at|2026-06-09|@tanstack/react-start|@tanstack/react-router|source_priority|inputValidator|validator|importProtection|createServerOnlyFn|createMiddleware|createHandlers|excludeFiles' skills/tanstack-start-architecture/references/official
rg -n 'Official|Safety policy|Hypercore convention|publishing-only|Zod v4|enabled by default|server\.handlers|createHandlers|behavior: '\''error'\''|Type-only imports' skills/tanstack-start-architecture/rules skills/tanstack-start-architecture/architecture-rules.md
rg -n 'functions\.ts|server\.ts|same-origin|CSRF|dynamic import|mixed barrel|routeFileIgnorePrefix|src/modules/<domain>|src/db/<domain>|src/integrations/<provider>' skills/tanstack-start-architecture
rg -n 'src/config/env.ts|@t3-oss/env-core|createEnv|clientPrefix: "VITE_"|runtimeEnvStrict|emptyStringAsUndefined|Do not create `src/env/`' skills/tanstack-start-architecture/rules/platform.md
rg -n 'src/config/env.ts|@t3-oss/env-core|createEnv|clientPrefix: "VITE_"|runtimeEnvStrict|emptyStringAsUndefined|`src/env/`' skills/tanstack-start-architecture/rules/platform.ko.md
rg -n 'project-structure|src/routes|routeTree.gen|routesDirectory|src/modules|src/lib|src/integrations|direct leaf|repo-local convention' skills/tanstack-start-architecture
rg -n '@rules/project-structure.md|@rules/project-structure.ko.md' skills/tanstack-start-architecture/SKILL.md skills/tanstack-start-architecture/SKILL.ko.md
```
Must pass:
- `SKILL.md`와 `SKILL.ko.md`가 duplicated rulebook이 아니라 lean entrypoint임.
- core에서 참조하는 support file은 직접 링크되어 있고 indirect reference chain이 없음.
- 공식 TanStack 사실은 긴 core section이 아니라 `references/official/`에 있음.
- current official snapshot `references/official/current-docs-2026-06-02.ko.md`는 `SKILL.ko.md`에서 직접 link되며 API drift가 중요할 때 사용됨.
- hypercore-only convention이 그렇게 label됨.
- `rules/project-structure.md`와 `rules/project-structure.ko.md`가 존재하고 직접 링크됨.
- project-structure guidance가 `src/routes`, custom `routesDirectory`, generated `routeTree.gen.ts`, shared nested folders, touched shared root direct leaf file 금지, route-local/shared server function placement를 다룸.
- server-function-heavy guidance가 `.functions.ts` wrapper, `.server.ts` helper, static direct imports, no mixed barrels, auth/CSRF boundary를 다룸.
- `src/modules`, `src/lib`, `src/integrations` 같은 shared nested folders는 official TanStack law가 아니라 Hypercore/repo-local convention으로 label됨.
- publishing-only route exception과 hook extraction rule이 모순되지 않음.
- search validation guidance가 Zod v4 direct schema와 Zod v3 adapter를 모두 다룸.
- import protection guidance가 default 존재와 custom deny 필요 시 explicit config를 모두 설명함.
- Middleware guidance가 request middleware `createMiddleware()`, server function middleware `createMiddleware({ type: 'function' })`, middleware `.validator(...)`, server function `.validator(...)`를 구분함.
- Server route guidance가 `server.handlers`, `createHandlers`, route-level `server.middleware`, duplicate method collision checks, wildcard/splat route notes를 포함함.
- Import protection guidance가 type-only import behavior, `behavior: 'error'`, `excludeFiles`, diagnostic/scoping options를 포함함.
- env validation guidance가 `src/config/env.ts`를 사용하고, 새 `src/env/` scaffold를 금지하며, `@t3-oss/env-core` / Vite public-prefix boundary를 설명함.
- English/Korean entrypoint의 trigger, boundary, workflow, read order가 일치함.
## Trigger Tests
Positive:
- "Audit this TanStack Start app for server-function, loader, and importProtection violations."
- "Add a TanStack Start route with search params and keep the architecture compliant."
- "Refactor Start route folders, hooks, and server functions to follow hypercore rules."
- "TanStack Start 프로젝트에서 loader 경계랑 server function 구조 점검해줘."
- "TanStack Start folder structure를 검토하고 nested `src/modules` / `src/lib` grouping을 강제해줘."
- "TanStack Start에서 `src/modules/billing/invoices`와 `src/routes/billing` 구조가 맞는지 봐줘."
- "src/lib/utils.ts 말고 src/lib/auth/session.ts처럼 논리 폴더로 묶어줘."
- "TanStack Start server functions를 `src/modules/billing/invoices/invoices.functions.ts`와 `.server.ts`로 정리해줘."
Negative:
- "TanStack Start가 아닌 일반 React/Vite 앱을 리뷰해줘."
- "Codex용 browser QA skill을 새로 만들어줘."
Boundary:
- "정적인 TanStack Start privacy page의 카피만 바꿔줘."
Expected: 빠른 boundary check만 수행하고 빈 route-local folder를 강제하지 않음.
## Completion Checklist
- [ ] project validation으로 이 스킬 적용 여부를 확인하거나 route-away함.
- [ ] 필요한 rule/reference file만 읽음.
- [ ] 적용 규칙을 Official, Safety policy, Hypercore convention으로 분류함.
- [ ] blocking safety gate를 style convention보다 먼저 수정함.
- [ ] env scaffold를 건드렸다면 `src/config/env.ts`를 사용하고 `src/env/`를 만들지 않음.
- [ ] broad migration은 요청 없으면 피함.
- [ ] verification command를 실행하고 결과를 읽음.
- [ ] server function wrapper/helper split, static imports, auth/CSRF boundary, no mixed barrels를 확인함.
- [ ] 남은 risk 또는 TanStack API ambiguity가 정확한 source/date를 인용함.
rules/validation.md
# Validation and Readback
> Completion checks for TanStack Start architecture work and for this skill's own maintainability.
## Project Work Validation
Run checks appropriate to the touched surfaces:
```bash
# Route export and direct DB access checks
rg -n "const Route = createFileRoute|export const Route" src/routes 2>/dev/null
rg -n "from ['\"]@/database|from ['\"].*/database|@prisma/client|drizzle-orm" src/routes 2>/dev/null
# Server function validation and stale API checks
rg -n "\.validator\(|\.inputValidator\(|createServerFn" src 2>/dev/null
# Import boundary checks
rg -n "server-only|client-only|\.server\.|\.client\.|importProtection|tanstackStart" vite.config.* src 2>/dev/null
# Loader and hydration risk checks
rg -n "loader:|beforeLoad:|Date\.now\(|Math\.random\(|localStorage|window\." src/routes src/components 2>/dev/null
# Env config checks when env validation is touched or scaffolded
test ! -d src/env
test ! -f src/env.ts
test -f src/config/env.ts
rg -n "@t3-oss/env-core|createEnv" src/config/env.ts
rg -n "clientPrefix: ['\"]VITE_|runtimeEnvStrict|runtimeEnv|emptyStringAsUndefined|isServer" src/config/env.ts
rg -n "VITE_.*(SECRET|TOKEN|PASSWORD|DATABASE_URL|PRIVATE)" src/config/env.ts .env* 2>/dev/null
```
Interpret results with the topic rule files; grep output alone is not a verdict.
## Skill Anatomy Validation
For edits to this skill itself:
```bash
find skills/tanstack-start-architecture -maxdepth 3 -type f | sort
wc -l skills/tanstack-start-architecture/SKILL.md skills/tanstack-start-architecture/SKILL.ko.md
rg -n 'architecture-rules|rules/|references/official' skills/tanstack-start-architecture/SKILL.md
rg -n 'last_verified_at|checked_at|2026-06-09|@tanstack/react-start|@tanstack/react-router|source_priority|inputValidator|validator|importProtection|createServerOnlyFn|createMiddleware|createHandlers|excludeFiles' skills/tanstack-start-architecture/references/official
rg -n 'Official|Safety policy|Hypercore convention|publishing-only|Zod v4|enabled by default|server\.handlers|createHandlers|behavior: '\''error'\''|Type-only imports' skills/tanstack-start-architecture/rules skills/tanstack-start-architecture/architecture-rules.md
rg -n 'functions\.ts|server\.ts|same-origin|CSRF|dynamic import|mixed barrel|routeFileIgnorePrefix|src/modules/<domain>|src/db/<domain>|src/integrations/<provider>' skills/tanstack-start-architecture
rg -n 'src/config/env.ts|@t3-oss/env-core|createEnv|clientPrefix: "VITE_"|runtimeEnvStrict|emptyStringAsUndefined|Do not create `src/env/`' skills/tanstack-start-architecture/rules/platform.md
rg -n 'src/config/env.ts|@t3-oss/env-core|createEnv|clientPrefix: "VITE_"|runtimeEnvStrict|emptyStringAsUndefined|`src/env/`' skills/tanstack-start-architecture/rules/platform.ko.md
rg -n 'project-structure|src/routes|routeTree.gen|routesDirectory|src/modules|src/lib|src/integrations|direct leaf|repo-local convention' skills/tanstack-start-architecture
rg -n '@rules/project-structure.md|@rules/project-structure.ko.md' skills/tanstack-start-architecture/SKILL.md skills/tanstack-start-architecture/SKILL.ko.md
```
Must pass:
- `SKILL.md` and `SKILL.ko.md` are lean entrypoints, not duplicated rulebooks.
- Support files referenced from the core are directly linked; there is no indirect reference chain.
- Official TanStack facts live in `references/official/`, not in long core sections.
- Current official snapshot `references/official/current-docs-2026-06-02.md` is directly linked from `SKILL.md` and used when API drift matters.
- Hypercore-only conventions are labelled as such.
- `rules/project-structure.md` and `rules/project-structure.ko.md` exist and are directly linked.
- Project-structure guidance handles `src/routes`, custom `routesDirectory`, generated `routeTree.gen.ts`, shared nested folders, no-new-direct-leaf-files under touched shared roots, and route-local/shared server function placement.
- Server-function-heavy guidance covers `.functions.ts` wrappers, `.server.ts` helpers, static direct imports, no mixed barrels, and auth/CSRF boundaries.
- Shared nested folders such as `src/modules`, `src/lib`, and `src/integrations` are labelled as Hypercore/repo-local convention, not official TanStack law.
- Publishing-only route exception and hook extraction rules do not contradict each other.
- Search validation guidance handles both Zod v4 direct schemas and Zod v3 adapter usage.
- Import protection guidance says defaults exist and custom config is required when custom deny rules are needed.
- Middleware guidance distinguishes request middleware `createMiddleware()`, server function middleware `createMiddleware({ type: 'function' })`, middleware `.validator(...)`, and server function `.validator(...)`.
- Server route guidance includes `server.handlers`, `createHandlers`, route-level `server.middleware`, duplicate method collision checks, and wildcard/splat route notes.
- Import protection guidance includes type-only import behavior, `behavior: 'error'`, `excludeFiles`, and diagnostic/scoping options.
- Env validation guidance uses `src/config/env.ts`, forbids new `src/env/` scaffolds, and describes `@t3-oss/env-core` / Vite public-prefix boundaries.
- Deprecated feature-folder guidance is absent from this skill.
- English and Korean entrypoints have aligned trigger, boundary, workflow, and read order.
## Trigger Tests
Positive examples that should trigger this skill:
- "Audit this TanStack Start app for server-function, loader, and importProtection violations."
- "Add a TanStack Start route with search params and keep the architecture compliant."
- "Refactor Start route folders, hooks, and server functions to follow hypercore rules."
- "Check the loader boundaries and server function structure in this TanStack Start project."
- "Review this TanStack Start folder structure and enforce nested `src/modules` / `src/lib` grouping."
- "Check whether `src/modules/billing/invoices` and `src/routes/billing` are organized correctly in TanStack Start."
- "src/lib/utils.ts 말고 src/lib/auth/session.ts처럼 논리 폴더로 묶어줘."
- "Organize TanStack Start server functions under `src/modules/billing/invoices/invoices.functions.ts` and `.server.ts`."
Negative examples that should not trigger this skill:
- "Review this generic React/Vite app that does not use TanStack Start."
- "Create a browser QA skill for Codex."
Boundary example:
- "Make a copy-only edit in a static TanStack Start privacy page."
Expected: quick boundary check only; do not force empty route-local folders.
## Completion Checklist
- [ ] Project validation confirmed this skill applies, or route-away happened.
- [ ] Only relevant rule/reference files were loaded.
- [ ] Applicable rules were classified as Official, Safety policy, or Hypercore convention.
- [ ] Blocking safety gates were fixed before style conventions.
- [ ] Env scaffolds, when touched, use `src/config/env.ts` and do not create `src/env/`.
- [ ] Broad migrations were avoided unless requested.
- [ ] Verification commands were run and read.
- [ ] Server function wrapper/helper split, static imports, auth/CSRF boundary, and no mixed barrels were checked.
- [ ] Remaining risks or TanStack API ambiguities cite exact sources and dates.
SKILL.ko.md
---
name: tanstack-start-architecture
description: 기존 TanStack Start/Router 프로젝트의 routes, loaders, server functions, importProtection, SSR/hydration, `src/modules`, `src/lib`, `src/integrations` 같은 nested shared folders 아키텍처를 리뷰하거나 변경할 때 사용합니다. 일반 React/Vite 프로젝트나 문서 요약 전용 요청에는 사용하지 않습니다.
---
@architecture-rules.md
@rules/project-structure.ko.md
@rules/routes.ko.md
@rules/services.ko.md
@rules/hooks.ko.md
@rules/import-protection.ko.md
@rules/middleware.ko.md
@rules/execution-model.ko.md
@rules/server-routes.ko.md
@rules/ssr-hydration.ko.md
@rules/platform.ko.md
@rules/validation.ko.md
@references/official/tanstack-start-2026-04-30.md
@references/official/tanstack-router-2026-04-30.md
@references/official/api-drift-notes.md
@references/official/current-docs-2026-06-02.ko.md
# TanStack Start Architecture Enforcement
> 공식 TanStack 요구사항과 hypercore 팀 convention을 구분하면서 TanStack Start 아키텍처를 검증합니다.
<output_language>
사용자에게 보이는 모든 산출물, 저장 아티팩트, 리포트, 계획서, 생성 문서, 요약, 인수인계 메모, 커밋/메시지 초안, 검증 메모는 기본적으로 한국어로 작성합니다.
소스 코드 식별자, CLI 명령, 파일 경로, 스키마 키, JSON/YAML 필드명, API 이름, 패키지명, 고유명사, 인용한 원문 발췌는 필요한 언어 또는 원문 그대로 유지합니다.
사용자가 명시적으로 다른 언어를 요청했거나, 기존 대상 산출물의 언어 일관성을 맞춰야 하거나, 기계 판독 계약상 정확한 영어 토큰이 필요한 경우에만 다른 언어를 사용합니다. 사용자-facing 산출물에 쓸 로컬라이즈된 템플릿/참조(`*.ko.md`, `*.ko.json` 등)가 있으면 우선 사용합니다.
</output_language>
<purpose>
- TanStack Start / TanStack Router 프로젝트인지 먼저 확인합니다.
- loader, server function, import protection, middleware, server route, SSR/hydration 안전 경계를 강제합니다.
- route folder, hook 분리, 파일명, 주석, layer 구조 같은 hypercore convention을 적용합니다.
- 변동이 잦은 TanStack 공식 API 사실은 `references/official/`에 두고 코어 스킬은 얇게 유지합니다.
</purpose>
<operating_mode>
이 스킬은 자체 완결형입니다. 적용 전에 전역 스킬이나 외부 orchestration에 의존하지 않습니다.
규칙은 다음처럼 분류합니다:
- **Official** — TanStack 공식 문서/API 요구사항.
- **Safety policy** — 보안/런타임 안전을 위한 로컬 차단 규칙.
- **Hypercore convention** — 공식 기본값보다 엄격할 수 있는 팀 표준.
사용자가 공식 TanStack default만 원한다고 명시하면 hypercore-only convention은 완화할 수 있지만 Official/Safety 규칙은 유지합니다.
</operating_mode>
<routing_rule>
요청 결과가 기존 TanStack Start / TanStack Router 프로젝트의 architecture enforcement, implementation guidance, review일 때 이 스킬을 사용합니다. 범위에는 route structure, route-local folders, loaders, server functions, server routes, middleware, import protection, SSR/hydration, platform setup, shared nested folder organization이 포함됩니다.
다음 경우에는 사용하지 않습니다.
- 프로젝트가 TanStack Start 또는 TanStack Router가 아님
- 사용자가 일반 React/Vite architecture review만 요청함
- project audit 또는 implementation guidance 없이 문서 요약만 요청함
- 주요 작업이 Start architecture와 무관한 security, deployment, test repair임
공식 TanStack guidance와 Hypercore convention이 다르면 official/safety rules를 먼저 강제하고, Hypercore convention은 touched architecture surface에만 적용합니다.
</routing_rule>
<instruction_contract>
| Field | Contract |
|---|---|
| Intent | TanStack Start 프로젝트를 official Start/Router behavior와 label된 Hypercore convention에 맞게 안전하고 유지보수 가능하게 유지합니다. |
| Trigger | routes, loaders, server functions, import boundaries, SSR/hydration, middleware, server routes, platform setup, shared folder layout을 포함한 기존 Start/Router 프로젝트 작업. |
| Scope | touched project architecture, topic rule files, official references, validation notes, 작고 되돌릴 수 있는 architecture fix를 리뷰하고 안내합니다. |
| Authority | 사용자/프로젝트 지시가 이 스킬보다 우선합니다. API 사실은 공식 TanStack 문서가 Hypercore convention보다 우선합니다. Safety policy는 위험한 runtime/import-boundary 변경을 차단합니다. |
| Evidence | project indicators, local config/package files, touched source paths, topic rules, official references, package typecheck, validation command output을 사용합니다. |
| Tools | local search/read/edit/validation commands를 사용합니다. API drift가 중요하면 최신 공식 문서를 확인합니다. destructive migration, credential access, network side effect, production change는 gate합니다. |
| Output | rule classification, 변경 파일, 검증 근거, 남은 risk, official-doc ambiguity note가 포함된 한국어 architecture decision/review. |
| Verification | touched surface에 맞는 `rules/validation.ko.md` checks와, 이 스킬 폴더 변경 시 skill-anatomy checks를 실행합니다. |
| Stop condition | applicable safety gate가 통과하고, Hypercore convention을 적용 또는 명시적으로 보류했으며, 검증 근거와 unresolved API drift의 날짜/출처를 기록하면 멈춥니다. |
</instruction_contract>
<activation_examples>
Positive examples:
- "Audit this TanStack Start app for server-function, loader, and importProtection violations."
- "Add a TanStack Start route with search params and keep the architecture compliant."
- "Refactor Start route folders, hooks, and server functions to follow hypercore rules."
- "TanStack Start 프로젝트에서 loader 경계랑 server function 구조 점검해줘."
- "TanStack Start folder structure를 검토하고 nested src/modules 또는 src/lib grouping을 강제해줘."
Negative examples:
- "TanStack Start가 아닌 일반 React/Vite 앱을 리뷰해줘."
- "Codex용 browser QA skill을 새로 만들어줘."
- "프로젝트 감사 없이 TanStack Router 문서만 요약해줘."
Boundary examples:
- "정적인 TanStack Start privacy page의 카피만 바꿔줘."
이 경우 빠른 boundary check만 수행합니다. publishing-only 페이지는 `-hooks/`, `-components/`, `-functions/` 폴더가 필요 없으며, interactive UI 또는 route-only server action이 생길 때만 route-local folder를 추가합니다.
</activation_examples>
<project_validation>
규칙을 적용하기 전에 아래 Start/Router indicator 중 하나 이상을 확인합니다:
```bash
ls app.config.ts 2>/dev/null
grep -r "@tanstack/react-start" package.json 2>/dev/null
grep -r "@tanstack/react-router" package.json 2>/dev/null
ls src/routes/__root.tsx 2>/dev/null
```
아무 것도 없으면 이 스킬 적용을 중단하고 일반 구현/리뷰 경로로 전환합니다.
</project_validation>
<support_file_read_order>
작업에 필요한 파일만 읽습니다:
1. `architecture-rules.md` — rule taxonomy와 blocking gate 요약.
2. 변경 표면별 topic rules:
- `rules/project-structure.ko.md` — official Start project shape, `src/routes`, route tree generation, custom route directory, shared nested folders.
- `rules/routes.ko.md` — route 조직, search validation, loader, route lifecycle.
- `rules/services.ko.md` — server function, validation, query/mutation layering.
- `rules/hooks.ko.md` — hook 추출, 내부 순서, `useServerFn` wrapper policy.
- `rules/import-protection.ko.md` — client/server import boundary와 `vite.config.ts` deny rules.
- `rules/middleware.ko.md` — function/request middleware와 `sendContext` validation.
- `rules/execution-model.ko.md` — isomorphic loader와 environment-only functions.
- `rules/server-routes.ko.md` — HTTP endpoint와 internal app RPC 구분.
- `rules/ssr-hydration.ko.md` — deterministic first render, `ClientOnly`, route SSR mode.
- `rules/platform.ko.md` — `getRouter()`, env validation, path aliases, operational endpoints.
3. Start API behavior가 중요하면 `references/official/tanstack-start-2026-04-30.md`.
4. Router/file-route/search/loading behavior가 중요하면 `references/official/tanstack-router-2026-04-30.md`.
5. current Start docs, plugin config, import protection, server functions, execution-control API가 판단에 영향을 주면 `references/official/current-docs-2026-06-02.ko.md`.
6. 공식 문서 충돌이나 package behavior가 불확실하면 `references/official/api-drift-notes.md`.
7. 완료 전 `rules/validation.ko.md`.
</support_file_read_order>
<workflow>
| Phase | Task | Output |
|---|---|---|
| 0 | TanStack Start/Router 프로젝트인지 확인 | Scope decision |
| 1 | 변경 표면을 파악하고 필요한 rule/reference만 읽기 | Minimal evidence set |
| 2 | 각 규칙을 Official, Safety policy, Hypercore convention으로 분류 | Enforcement plan |
| 3 | 안전하고 로컬이며 되돌릴 수 있는 수정을 자동 적용 | Code 또는 skill changes |
| 4 | 넓은 migration은 명시 요청이 없으면 backlog/handoff 처리 | Backlog 또는 handoff note |
| 5 | `rules/validation.ko.md` 검증 실행 | Evidence-backed completion |
</workflow>
<blocking_safety_summary>
아래가 touched code에 생기면 진행 전 반드시 차단/수정합니다:
- secret, DB client, filesystem, privileged SDK를 isomorphic loader/client-reachable code에서 직접 읽음.
- `createServerFn` 또는 `createServerOnlyFn` 같은 compiler-recognized boundary 밖에 server-only import가 살아남음.
- import protection을 비활성화하거나 기존 `tanstackStart()` 설정을 확장하지 않고 덮어씀.
- mutation server function에 runtime input validation이 없음.
- 신뢰할 수 없는 `sendContext` 값을 server에서 검증 없이 사용함.
- `Date.now()`, random ID, locale/time-zone 차이 등 hydration-unstable first render output을 안정화 전략 없이 도입함.
</blocking_safety_summary>
<hypercore_conventions_summary>
사용자가 official default만 원한다고 명시하지 않는 한 touched file에 적용합니다:
- 앱 페이지는 flat route보다 route directory를 선호합니다.
- interactive logic이 있는 page/component는 logic을 `-hooks/`로 추출합니다. publishing-only static page는 예외입니다.
- server integration이 있는 페이지는 기본적으로 `src/modules/<domain>/<feature>/`의 server functions를 route-local hooks에서 호출합니다. route-local `-functions/`는 단일 route 전용 action일 때만 예외로 사용합니다.
- file route는 `export const Route = createFileRoute(...)`를 사용합니다.
- route/page UI -> hooks/query -> route-local exception 또는 module server functions -> modules/lib/db/integrations layer 흐름을 유지합니다.
- server functions는 기본적으로 `src/modules/<domain>/<feature>/<resource>.functions.ts`에 둡니다. route-local `-functions/<resource>.functions.ts`는 단일 route 전용 action에만 사용합니다.
- server function wrapper는 `.functions.ts`, DB/secret/filesystem helper는 `.server.ts`, validation/DTO/query-key는 client-safe schema/helper file로 분리합니다.
- touched shared code를 추가하거나 재구성할 때 `src/modules/<domain>/<feature>/`, `src/lib/<domain>/`, `src/db/<area>/`, `src/server/<area>/`, `src/integrations/<provider>/`, `src/config/<area>/` 같은 nested shared folders를 강제합니다. 명시적 project exception을 기록하지 않는 한 `src/modules/foo.ts` 또는 `src/lib/foo.ts` 같은 새 direct leaf file을 만들지 않습니다.
- `functions/index.ts` 또는 `src/modules/<domain>/<feature>/index.ts`에서 safe exports와 server-only exports를 섞지 않습니다.
- kebab-case filename, explicit return type, no `any`, const arrow function, 의미 있는 코드 그룹의 Korean block comments를 유지합니다.
</hypercore_conventions_summary>
<validation>
완료 선언 전:
- `rules/validation.ko.md`의 작업별 검증을 실행합니다.
- 수정한 rule에 official-vs-hypercore label이 유지되는지 확인합니다.
- `SKILL.md`에서 support file이 직접 링크되고 indirect reference chain이 없는지 확인합니다.
- English/Korean entrypoint가 같은 trigger, boundary, workflow, contract, read order를 설명하는지 확인합니다.
- touched `src/modules`, `src/lib`, `src/integrations` 및 유사 shared folders가 logical nested grouping을 쓰는지 또는 explicit exception이 기록됐는지 확인합니다.
- server function-heavy changes가 `.functions.ts` / `.server.ts` split, static direct imports, auth/CSRF boundary를 유지하는지 확인합니다.
- 남은 TanStack API ambiguity는 source link와 정확한 날짜로 기록합니다.
</validation>
SKILL.md
---
name: tanstack-start-architecture
description: "Use this skill when reviewing or changing an existing TanStack Start/Router project architecture, especially routes, loaders, server functions, importProtection, SSR/hydration, and nested shared folders such as src/modules, src/lib, or src/integrations. Do not use for generic React/Vite projects or docs-only summaries."
---
@architecture-rules.md
@rules/project-structure.md
@rules/routes.md
@rules/services.md
@rules/hooks.md
@rules/import-protection.md
@rules/middleware.md
@rules/execution-model.md
@rules/server-routes.md
@rules/ssr-hydration.md
@rules/platform.md
@rules/validation.md
@references/official/tanstack-start-2026-04-30.md
@references/official/tanstack-router-2026-04-30.md
@references/official/api-drift-notes.md
@references/official/current-docs-2026-06-02.md
# TanStack Start Architecture Enforcement
> Apply hypercore's TanStack Start architecture rules without confusing team conventions with official TanStack requirements.
<output_language>
Default all user-facing deliverables, saved artifacts, reports, plans, generated docs, summaries, handoff notes, commit/message drafts, and validation notes to Korean, even when this canonical skill file is written in English.
Preserve source code identifiers, CLI commands, file paths, schema keys, JSON/YAML field names, API names, package names, proper nouns, and quoted source excerpts in their required or original language.
Use a different language only when the user explicitly requests it, an existing target artifact must stay in another language for consistency, or a machine-readable contract requires exact English tokens. If a localized template or reference exists (for example `*.ko.md` or `*.ko.json`), prefer it for user-facing artifacts.
</output_language>
<purpose>
- Validate that the project is a TanStack Start / TanStack Router project before applying this skill.
- Enforce safety boundaries for loaders, server functions, import protection, middleware, server routes, and SSR/hydration.
- Apply hypercore conventions for route folders, hooks, file naming, comments, and layering when they are in scope.
- Keep official TanStack API facts in `references/official/` so rapidly changing framework details can be refreshed without bloating the core skill.
</purpose>
<operating_mode>
This skill is self-contained. Do not depend on global skills or external orchestration before applying it.
Rules are classified as:
- **Official** — documented TanStack behavior or API requirement.
- **Safety policy** — local blocking rule for security/runtime correctness.
- **Hypercore convention** — local/team standard that may be stricter than official TanStack defaults.
If a user explicitly asks for official TanStack defaults, relax hypercore-only conventions but keep official and safety rules.
</operating_mode>
<routing_rule>
Use this skill when the requested output is architecture enforcement, implementation guidance, or review for an existing TanStack Start / TanStack Router project. This includes route structure, route-local folders, loaders, server functions, server routes, middleware, import protection, SSR/hydration, platform setup, and shared nested folder organization.
Do not use this skill when:
- the project is not TanStack Start or TanStack Router
- the user only wants a generic React/Vite architecture review
- the task is a docs-only summary with no project audit or implementation guidance
- the main task is security, deployment, or test repair unrelated to Start architecture
When official TanStack guidance and Hypercore conventions differ, enforce official and safety rules first, then apply Hypercore conventions only to touched architecture surfaces.
</routing_rule>
<instruction_contract>
| Field | Contract |
|---|---|
| Intent | Keep TanStack Start projects architecturally safe, maintainable, and aligned with official Start/Router behavior plus labelled Hypercore conventions. |
| Trigger | Existing Start/Router project work involving routes, loaders, server functions, import boundaries, SSR/hydration, middleware, server routes, platform setup, or shared folder layout. |
| Scope | Review and guide touched project architecture, topic rule files, official references, validation notes, and small reversible architecture fixes. |
| Authority | User/project instructions outrank this skill. Official TanStack docs outrank Hypercore conventions for API facts. Safety policy blocks risky runtime or import-boundary changes. |
| Evidence | Use project indicators, local config/package files, touched source paths, topic rules, official references, package typechecks, and validation command output. |
| Tools | Use local search/read/edit/validation commands; use current official docs when API drift matters; gate destructive migrations, credential access, network side effects, and production changes. |
| Output | Korean architecture decision or review with rule classifications, changed files if any, validation evidence, remaining risks, and official-doc ambiguity notes. |
| Verification | Run `rules/validation.md` checks relevant to touched surfaces and skill-anatomy checks when this skill folder changes. |
| Stop condition | Stop after applicable safety gates pass, Hypercore conventions are applied or explicitly deferred, validation evidence is recorded, and unresolved API drift is dated and sourced. |
</instruction_contract>
<activation_examples>
Positive examples:
- "Audit this TanStack Start app for server-function, loader, and importProtection violations."
- "Add a TanStack Start route with search params and keep the architecture compliant."
- "Refactor Start route folders, hooks, and server functions to follow hypercore rules."
- "Check the loader boundaries and server function structure in this TanStack Start project."
- "Review this TanStack Start folder structure and enforce nested src/modules or src/lib grouping."
Negative examples:
- "Review this generic React/Vite app that does not use TanStack Start."
- "Create a browser QA skill for Codex."
- "Summarize TanStack Router docs without changing or auditing a project."
Boundary examples:
- "Make a copy-only edit in a static TanStack Start privacy page."
Use this skill only for a quick boundary check. Publishing-only pages do not need generated `-hooks/`, `-components/`, or `-functions/` folders; add route-local folders only when interactive UI or route-only server actions are introduced.
</activation_examples>
<project_validation>
Before enforcing rules, confirm at least one Start/Router indicator exists:
```bash
ls app.config.ts 2>/dev/null
grep -r "@tanstack/react-start" package.json 2>/dev/null
grep -r "@tanstack/react-router" package.json 2>/dev/null
ls src/routes/__root.tsx 2>/dev/null
```
If none are present, stop using this skill and route to the normal implementation/review path.
</project_validation>
<support_file_read_order>
Read only what the task needs:
1. `architecture-rules.md` for the rule taxonomy and blocking gate summary.
2. Topic rules by changed surface:
- `rules/project-structure.md` — official Start project shape, `src/routes`, route tree generation, custom route directory, shared nested folders.
- `rules/routes.md` — route organization, search validation, loaders, route lifecycle.
- `rules/services.md` — server functions, validation, query/mutation layering.
- `rules/hooks.md` — hook extraction, internal hook order, `useServerFn` wrapper policy.
- `rules/import-protection.md` — client/server import boundaries and `vite.config.ts` deny rules.
- `rules/middleware.md` — function/request middleware and `sendContext` validation.
- `rules/execution-model.md` — isomorphic loaders and environment-only functions.
- `rules/server-routes.md` — justified HTTP endpoints vs internal app RPC.
- `rules/ssr-hydration.md` — deterministic first render, `ClientOnly`, route SSR modes.
- `rules/platform.md` — `getRouter()`, env validation, path aliases, operational endpoints.
3. `references/official/tanstack-start-2026-04-30.md` when Start API behavior matters.
4. `references/official/tanstack-router-2026-04-30.md` when Router/file-route/search/loading behavior matters.
5. `references/official/current-docs-2026-06-02.md` when current Start docs, plugin config, import protection, server functions, or execution-control APIs affect the decision.
6. `references/official/api-drift-notes.md` when docs conflict or current package behavior is uncertain.
7. `rules/validation.md` before claiming completion.
</support_file_read_order>
<workflow>
| Phase | Task | Output |
|---|---|---|
| 0 | Validate this is a TanStack Start/Router project | Scope decision |
| 1 | Identify touched surfaces and load only relevant rule/reference files | Minimal evidence set |
| 2 | Classify each applicable rule as Official, Safety policy, or Hypercore convention | Enforcement plan |
| 3 | Apply safe, local, reversible fixes automatically | Code or skill changes |
| 4 | Defer broad migrations unless explicitly requested | Backlog or handoff note |
| 5 | Run validation checks from `rules/validation.md` | Evidence-backed completion |
</workflow>
<blocking_safety_summary>
Always block or fix before proceeding when touched code would:
- Read secrets, DB clients, filesystem, or privileged SDKs from isomorphic loader/client-reachable code.
- Keep server-only imports alive outside compiler-recognized boundaries such as `createServerFn` or `createServerOnlyFn`.
- Disable import protection or overwrite an existing `tanstackStart()` config instead of extending it.
- Use server functions for mutations without runtime input validation.
- Treat untrusted `sendContext` values as validated server data.
- Introduce hydration-unstable first render output such as `Date.now()`, random IDs, or locale/time-zone divergence without a stabilization strategy.
</blocking_safety_summary>
<hypercore_conventions_summary>
Apply these to touched files unless the user asks for official defaults only:
- Prefer route directories over flat route files for app pages.
- Pages/components with interactive logic extract logic into `-hooks/`; publishing-only static pages are exempt.
- Server-integrated pages call server functions from `src/modules/<domain>/<feature>/` through route-local hooks by default. Use route-local `-functions/` only as an exception for single-route actions.
- Use `export const Route = createFileRoute(...)` for file routes.
- Keep routes thin: route/page UI -> hooks/query -> route-local exception or module server functions -> modules/lib/db/integrations layer.
- Place server functions in `src/modules/<domain>/<feature>/<resource>.functions.ts` by default. Use route-local `-functions/<resource>.functions.ts` only for single-route actions.
- Split server function wrappers into `.functions.ts`, DB/secret/filesystem helpers into `.server.ts`, and validation/DTO/query-key code into client-safe schema/helper files.
- Enforce nested shared folders such as `src/modules/<domain>/<feature>/`, `src/lib/<domain>/`, `src/db/<area>/`, `src/server/<area>/`, `src/integrations/<provider>/`, and `src/config/<area>/` when touched shared code is added or reorganized; do not add new direct leaf files like `src/modules/foo.ts` or `src/lib/foo.ts` unless an explicit project exception is recorded.
- Do not mix safe exports with server-only exports in `functions/index.ts` or `src/modules/<domain>/<feature>/index.ts`.
- Use kebab-case filenames, explicit return types, no `any`, const arrow functions, and Korean block comments for meaningful code groups.
</hypercore_conventions_summary>
<validation>
Before declaring the work done:
- Run the task-specific checks in `rules/validation.md`.
- Confirm official-vs-hypercore labels are preserved in any edited rule.
- Confirm support files are directly linked from `SKILL.md` and do not require following an indirect reference chain.
- Confirm English and Korean entrypoints still describe the same trigger, boundary, workflow, contract, and read order.
- Confirm touched `src/modules`, `src/lib`, `src/integrations`, and similar shared folders use logical nested grouping or record an explicit exception.
- Confirm server-function-heavy changes preserve `.functions.ts` / `.server.ts` split, static direct imports, and auth/CSRF boundaries.
- Record any unresolved TanStack API ambiguity with a source link and exact date.
</validation>