Source: https://www.hype-stack.dev/docs/frontend

# Frontend Overview

The frontend lives in `apps/frontend/` and runs as a React SPA. It uses TanStack Router for navigation, Tailwind CSS for
styling, and HyperFetch for API communication.

## Folder structure

```
apps/frontend/
  messages/en.json   # Paraglide message catalog
  src/
    api/           # HyperFetch client, SDK, and socket setup
    assets/        # Styles, images, fonts
    components/    # Shared UI components (layouts, navigation, ui/)
    config.ts      # App name, constants
    constants/     # nav entries, navbar actions, settings tabs (packs patch these)
    features/      # Domain-organized feature code
    hooks/         # Global hooks
    lib/           # Shared frontend libraries
    paraglide/     # Compiled messages, generated
    routes/        # TanStack Router file-based routes
```

## Key patterns

- **Features own their code.** Components, hooks, types, and queries for a feature live together in
  `src/features/<domain>/<feature>/`. See [How to organize features](/docs/frontend/organize-features).

- **Routes are thin.** Route files in `src/routes/` import feature components and render them. Business logic stays in
  features, not route files.

- **Styling uses semantic tokens.** All colors come from CSS custom properties defined in `assets/styles.css`.
  Components use Tailwind classes like `bg-primary`, `text-muted-foreground` instead of raw palette colors.

- **Data flows through the SDK.** The HyperFetch SDK (`src/api/sdk.ts`) provides typed API calls. Components use
  `useFetch` for reads and `useSubmit` for mutations. See [Working with HTTP](/docs/frontend/http).

- **Copy lives in the message catalog.** User-visible strings come from `messages/en.json` through Paraglide, called as
  `m.teams_page_title()`. Packs merge their keys into the same file on install, so adding a locale is one more
  `messages/<locale>.json`. See [Translations](/docs/cli/add-pack#translations).

## shadcn/ui components

Pre-built, accessible UI primitives live in `src/components/ui/`. Button, Input, Card, Dialog, and dozens more. Use them
before building custom components.

Compose variants with `class-variance-authority` (`cva`) and merge conditional class names with `cn()` from
`@/lib/utils`.
