# The Claimwick Screen

## Intent

The expenses screen is one screen of the Claimwick product, the example product these pages follow: it shows each employee their expenses at one address. This page follows that screen from the folder serving its address, through its data read with the API client generated from the published contract, the shared UI package it composes, and the drawn list option it starts from, naming the frontend rule each step applies.

## The Expenses Route

The screen lives at `apps/web/src/routes/expenses/+page.svelte` in the Claimwick example. A Svelte frontend holds one folder per address under `src/routes`, with the frame and the use-case code in `src/lib/app` and `src/lib/modules`, as [Web Structure](https://litespec.dev/4.0.0/frontend/web/structure.md) states. The use-case code mirrors its backend path in kebab case, per `litespec/frontend/structure#mirror-the-backend-use-case-path-in-kebab-case` on [Frontend Structure](https://litespec.dev/4.0.0/frontend/structure.md): `lib/modules/spending/expenses/list-expenses` mirrors the List expenses use case path that [Modules and Records](https://litespec.dev/4.0.0/example/modules-and-records.md) describes. The route folder names the address, not the use case. The screen record file lives at `.litespec/behavior/entry-points/claimwick-app/screens/expense-list.yaml`. Its mark sits in the `<script module>` of `apps/web/src/routes/expenses/+page.svelte`, naming `screen/claimwick-app.expense-list`, and the browser specification at `apps/web/tests/expenses/list-expenses.spec.ts` proves `scenario/list-expenses.listing-own-expenses-succeeds`.

A route file holds its input, its load, and its component, with no reusable logic and no import of another route file, per `litespec/frontend/structure#keep-a-route-entry-thin`. The expenses route therefore validates its search, prefetches its read, and composes its view, while shared code lives in the module folder or the frame. Imports point from the route to a module to the frame to a shared package, per `litespec/frontend/structure#order-imports-from-routes-to-shared-packages`, so the route reads the client from the frame and the generated operations from the shared API package.

## Reading Through the Generated Client

The screen never duplicates the API contract. The workspace generates its client, types, schemas, and query options from the published OpenAPI document, per `litespec/frontend/data#generate-the-client-from-the-published-contract` on [Frontend Data and State](https://litespec.dev/4.0.0/frontend/data.md). The generated client lives in `packages/api`, and the list reads through its `listExpenses` operation in `packages/api/src/generated/sdk.gen.ts`, which returns the `rows` include group the List expenses query declares: identity, amount, state, and submission time, newest first, read fresh:

```ts
export const listExpenses = <ThrowOnError extends boolean = false>(options: Options<never, ThrowOnError> = {}) =>
  (options.client ?? client).get<ListExpensesResponse, unknown, ThrowOnError>({
    url: "/api/expenses",
    ...options,
  });
```

The route's load prefetches the read through the query cache before the component runs, per `litespec/frontend/rendering#load-route-data-before-rendering` on [Frontend Rendering and Routes](https://litespec.dev/4.0.0/frontend/rendering.md), and the component reads the same cache key with a suspense query, per `litespec/frontend/rendering#read-route-data-from-the-route-cache`. Written the way the stack pages require, the load looks like this:

```ts
export async function load({ parent, url }) {
  const { queryClient } = await parent();
  const search = expensesSearch.parse(Object.fromEntries(url.searchParams));
  await queryClient.ensureQueryData(listExpensesQuery(search.page));
  return { search };
}
```

The search schema keeps the filters and the page in the address, per `litespec/frontend/rendering#keep-address-parameters-validated-by-a-schema`, so a filtered list stays a link the team can share. The example page itself is smaller: it calls `listExpenses` from `@claimwick/api` directly and renders the rows in the `ListPage` floorplan and the `DataTable` composite from `@claimwick/ui/floorplans`, so the model builder joins the screen to the list use case through the generated client. The load above shows what the stack pages require once the query cache is wired.

## The Shared UI Package

The screen composes the shared UI package `@claimwick/ui` at `packages/ui`, which the project declares in `paths.uiPackage` of `.litespec/project.json`. The package pins its baseline in the source lock at `packages/ui/ui-source-lock.json`: generator `shadcn-svelte`, CLI `1.7.0`, with the `button` and `skeleton` components at baseline status. `litespec model check` runs the controlled UI pass over the package, its source lock and digests, its design contract, its stylesheets, each frontend boundary, and each route suite, per [Model Builder](https://litespec.dev/4.0.0/tools/model.md), and reports its findings in the same shape. Against the Claimwick example it reports this, and exits zero:

```text
0 findings, 0 blocking, 0 known.
```

The pass covers the one controlled frontend: the `web` frontend at `apps/web`, which declares `platform: svelte`. Its route suite lives at `tests/routes/every-route.spec.ts`.

## The List Pattern Behind the Screen

The screen starts from the `litespec/frontend/patterns/lists-and-tables#choosing-the-columns` pattern on [List and Table Patterns](https://litespec.dev/4.0.0/frontend/patterns/lists-and-tables.md). That pattern asks which columns the table shows, and its default option `five-columns-nothing-removable` shows five columns with nothing removable: which item, who, when, what state, and what value. The expenses screen adapts that set to the facts the Expense record holds: the expense, the employee, the expense state, and the amount, which [Modules and Records](https://litespec.dev/4.0.0/example/modules-and-records.md) describes.

A consumer keeps one pattern catalog holding its interface decisions, per `litespec/frontend/patterns#keep-one-pattern-catalog` on [UI Patterns](https://litespec.dev/4.0.0/frontend/patterns.md). Each entry records at least 2 options with rationale and cost and names the chosen option, and each decision records its source as `owner` or `recommended`, per `litespec/frontend/patterns#record-who-chose`. The example keeps its catalog at `.litespec/implementation/entry-points/claimwick-app/pattern-catalog.json` with 2 entries, the orders list page and table sorting, and both decisions record `recommended` sources, standing until an owner chooses.

## The Frontend Rules the Screen Follows

Each step of the screen answers to one frontend rule. [Frontend Structure](https://litespec.dev/4.0.0/frontend/structure.md) places the route folder, keeps the route entry thin, and orders its imports toward the shared packages. [Frontend Data and State](https://litespec.dev/4.0.0/frontend/data.md) generates the client from the contract and routes the read through it. [Frontend Rendering and Routes](https://litespec.dev/4.0.0/frontend/rendering.md) prefetches the list in the load, reads it from the cache in the component, and keeps the view in the address. [Model Builder](https://litespec.dev/4.0.0/tools/model.md) checks the shared package, its source lock, and each frontend boundary. [List and Table Patterns](https://litespec.dev/4.0.0/frontend/patterns/lists-and-tables.md) gives the columns decision its options, and [UI Patterns](https://litespec.dev/4.0.0/frontend/patterns.md) records the choice. The [Svelte Stack](https://litespec.dev/4.0.0/frontend/web/svelte/stack.md) selects the rendering mode for the Claimwick app by its audience. A screen that keeps each of these rules reads the same way as every other screen, so the next route is a small variation on this one. [The Model and Its Checks](https://litespec.dev/4.0.0/example/model-and-checks.md) shows how the model proves the screen, its use case, and its handler agree.
