Skip to main content
vly’s React structure follows mainstream patterns. This page is the cheat sheet for the conventions worth following.

File and folder structure

Composition over duplication

When you find yourself copying JSX, extract:
Use shadcn primitives (<Button>, <Card>, <Input>) for UI atoms; extract domain-specific components (<TaskRow>, <UserAvatar>) into components/{domain}/.

Prop drilling vs. context

Three-deep prop passing is fine. Five-deep is the point to consider context.

Use props for data

Anything that changes per render — list items, form values, IDs.

Use context for ambient state

Theme, current user, active workspace. Things that rarely change but are read everywhere.

Use Convex queries for server state

Don’t hand-roll a server-state context. useQuery is the cache.

Use Zustand for ephemeral UI state

Modal open/closed, sidebar collapse, multi-step form draft. State that doesn’t need to live in the URL or DB.

When to extract

  • 3+ uses of the same JSX: extract a component.
  • 5+ lines of JSX inside a JSX expression: probably extract.
  • A useEffect with non-trivial logic: extract a custom hook.

Naming

  • Components: PascalCase. Files match the component (TaskRow.tsx exports TaskRow).
  • Hooks: useCamelCase. Files match (useDebouncedValue.ts).
  • Utilities: camelCase. Files often grouped (utils/format.ts).

Tips

Start with a single file, extract when needed. Premature extraction is the most common mistake. A 200-line component is fine if it’s read together.
Use shadcn slots and composition. Most “I need a custom button” situations are solved with a Button variant, not a new component.

State management

Where to put state.

shadcn/ui components

The primitive library.

Components panel

Browse and reuse.
Last modified on April 18, 2026