# UI Page Structure

> Standardize DataConnect route/page layout, logic/JSX separation, tests, and README expectations. Use when organizing pages/routes, refactoring page structure, or discussing file structure conventions. Use when this capability is needed.

- Skill: `tomevault-io/ui-page-structure` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/ui-page-structure`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/ui-page-structure/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/ui-page-structure

---


# UI Page Structure

## Purpose

Keep route-level code predictable: entry files, page-only components (and hooks), tests, and helpers live together. Enforce logic/JSX separation, require tests, and document with a README when the structure settles. Shared UI stays in `src/components`.

## Rules (short)

- **Route entry**: `src/pages/<route>/index.tsx` exports the page component.
- **Tiny single-file exception**: keep `src/pages/<route>.tsx` when the page is small and has no page-local components/hooks/tests/types/utils; once any co-located file is needed, move to `src/pages/<route>/`.
- **Page-only UI + hooks**: `src/pages/<route>/components/*` (hooks live with related components; no standalone `hooks/` dir).
- **Types + utils**: colocate in the route folder (`types.ts`, `utils.ts`, etc.).
- **Logic vs JSX**: keep logic in hooks/logic files, JSX in components (details below).
- **Extraction trigger**: if route `index.tsx` has more than one `useEffect` or includes direct IPC/file-system/network orchestration, extract a single page-local orchestration hook before adding more behavior.
- **Tests**: add enough to give confidence the page works; keep scope tight (no over-engineering).
- **Shared UI**: only in `src/components` (cross-page only).
- **Avoid “sections” folders**: page sections are just components.
- **README required**: when structure is settled, add page README per `ui-page-readme` (can be after-the-fact).
- **Composition + React patterns**: follow `vercel-composition-patterns` and `vercel-react-best-practices` when shaping component APIs and hook usage.

## Recommended layout

```
src/pages/settings/
  index.tsx
  README.md
  types.ts
  utils.ts
  components/
    settings-account.tsx
    settings-apps.tsx
    settings-storage.tsx
    settings-about.tsx
  index.test.tsx
```

```
src/pages/runs/
  index.tsx
  README.md
  components/
    run-item.tsx
    use-run-item.ts
  utils.ts
  index.test.tsx
```

## Logic vs JSX (practical split)

- **Components render; hooks compute.**
- **Components** should be mostly JSX + light glue (props, callbacks, formatting).
- **Components must not** fetch, mutate, or read storage/network directly.
- **Logic-only files** (`use-*.ts`, `*logic.ts`, `*utils.ts`) should not contain JSX or create `ReactNode`s.
- **Container/presenter split**: page entry/containers call hooks, pass data to presentational components.
- **Hooks live with components** when tightly coupled; keep pure logic separate to avoid merge conflicts.
- **Prefer composition** over boolean prop modes; make explicit variants when behavior diverges.
- **State in providers/hooks**; UI reads from hooks and renders.

## Hook placement heuristic

- **Route-level hooks**: routing, store, auth, network, or multi-component orchestration live at the
  route root (`src/pages/<route>/`).
- **Component-level hooks**: logic only used by a single component lives next to that component
  (use `components/<component>/` when a component grows).
- **Root hook cap**: keep 1-3 hooks at the route root; if you need more, split by component folder.

## Tests (minimum bar)

- `index.test.tsx` covering critical wiring and one or two key UI states.
- Add hook/component tests where behavior is non-trivial or risk-prone.
- If runtime capability changes behavior (for example desktop/Tauri vs browser), include at least one test for each branch.
- Avoid snapshots; assert behavior and side effects.
- Follow `react-testing` for test scope, commands, and reporting.

## Ownership moves

- If a route becomes the canonical owner of a feature surface, move both the page-owned UI surface and the page-level data-loading/readiness trigger in the same diff.
- Do not leave fetch ownership behind on a previously related route after UI ownership moves.
- When deciding whether two surfaces should share an implementation, compare user-facing actions first. Different actions mean different surfaces even if the rows or layout look similar.

## URL-backed page state

- When adding URL-backed page state (for example tabs, filters, or modes), add non-mocked page tests for:
  - param-to-state derivation on first render
  - invalid-value fallback/canonicalization
  - write/remove behavior that preserves unrelated search params

## Notes

- Keep imports direct (avoid barrel files).
- Prefer `@/` path alias over long relative imports.

---
> Converted and distributed by [TomeVault](https://tomevault.io/claim/vana-com) — claim your Tome and manage your conversions.
<!-- tomevault:4.0:skill_md:2026-04-13 -->

