Locate the change

Use the narrowest current owner:

  • route and URL behaviour: src/routes;
  • feature presentation: its src/components/<feature> folder;
  • reusable interaction or surface: src/components/ui;
  • Packbase read or mutation state: src/hooks/packbase;
  • API URL, errors, cache, or token refresh: src/lib or the SDK provider;
  • user-facing language: Lingui macros and src/locales;
  • deployment-time HTML behaviour: worker/index.ts.

Do not edit src/routeTree.gen.ts. Do not thread product data through the desktop layout when a route, feature adapter, or hook can own it beside the consumer.

Implement the complete state

For a data-backed view, design these states before polishing the happy path:

  1. initial loading with stable space;
  2. ready with ordinary and difficult content;
  3. genuinely empty;
  4. unauthenticated or forbidden where relevant;
  5. not found;
  6. retryable failure without destroying useful stale data;
  7. pending mutation with duplicate action prevented;
  8. failed optimistic mutation restored with a useful retry; and
  9. success with the correct cache updated or invalidated.

Read through usePackbaseClientState(scope) or an existing typed hook. Use the preferred scope for ordinary reads that may be public or signed in, and reserve public or authenticated for the contracts that require them. Never infer a default pack, permission, or identity from array order or visual position when the API provides an explicit source.

Preserve interface contracts

  • Use semantic links and buttons.
  • Keep keyboard focus visible and return focus after a dialog or nested surface closes.
  • Maintain at least the repository’s documented pointer targets.
  • Check long names, unbroken content, narrow screens, short screens, 200% zoom, dark and light themes, touch, and reduced motion.
  • Make selected, warning, rating, moderation, and follow states understandable without colour alone.
  • Keep animation local, interruptible, and absent when reduced motion is requested.
  • Sanitize user HTML at the rendering boundary even when the server also sanitizes it.

Copy is code

Use Lingui macros for visible strings. Run extraction after copy changes and inspect en, it, and ja catalogs:

bun run lingui:extract

Do not translate product terminology inconsistently merely to fill a catalog. Preserve placeholders and message meaning; mark uncertainty on the task.

Stories and tests

Add a provider-free story for new reusable or stateful UI. Include difficult intrinsic content and the failure states most likely to regress. Use a story play test for interaction or accessibility behaviour and a colocated unit test for pure state, parsing, or contract logic.

During work, run the smallest relevant test, typecheck, or story. Before merge, run:

bun run check
git diff --check

That full command includes headless Chromium Storybook checks. If the browser dependency is unavailable, run and report the non-browser checks separately; do not describe the full suite as passing.

Never test a mutation against the default by accident

The local web client defaults to the production Packbase API. Before publishing, deleting, following, moderating, uploading, changing settings, or creating an account from local code, set the Advanced API URL to the isolated environment intended by the task and verify the visible data is disposable.