Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .claude/reference/feature-flags.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,31 @@ if (features.platform) {

Deployment flavors map to flag sets roughly as: **cloud** = all on; **OSS** = `auth`/`platform`/`acl` off; **enterprise** = `acl` on, `auth`/`platform` off (engine enforces auth without a login UI). Do not treat `platform`/`auth` as "engine requires credentials" — that is `acl`. **`compute` is opt-in even on cloud** — each Railway service adds it to `VITE_FEATURE_FLAGS` per-environment (e.g. staging on, prod off) rather than inheriting the cloud default-on set.

## Testing across flavors (required for frontend changes)

A bug can exist in only one flavor. Whatever flavor your dev server happens to default to hides breakage in the others, so testing a single flavor is not enough. **OSS is the most important and the most commonly regressed flavor** because it turns the most off (`auth`/`platform`/`acl` all off), so any code that assumes cloud context (org/project params, auth session, cloud data providers) silently breaks there. The OSS namespace dropdown, sidebar, context switcher, and onboarding all take different code paths than cloud.

**Before considering any frontend change done, verify it in at least OSS and cloud.** If a surface renders conditionally on `features.*` (or differs by flavor at all: sidebar, context switcher, onboarding, settings, auth, billing), exercise each affected flavor in the browser, not just the default.

Switch flavors in dev without restarting the server by setting the `localStorage` override and reloading (the dev build reads `localStorage.FEATURE_FLAGS` ahead of `VITE_FEATURE_FLAGS`):

```js
// OSS self-host: everything off
localStorage.setItem("FEATURE_FLAGS", ""); location.reload();

// Full cloud: all flags on (see the commented canonical list in frontend/.env.local)
localStorage.setItem(
"FEATURE_FLAGS",
"compute,platform,acl,auth,captcha,branding,support,billing,datacenter,danger-zone,multitenancy",
);
location.reload();

// Enterprise: acl on, no login UI
localStorage.setItem("FEATURE_FLAGS", "acl,branding,support,datacenter,danger-zone"); location.reload();
```

In an agent-browser / DevTools session, paste those into the page console. `localStorage` persists across reloads, so run `localStorage.removeItem("FEATURE_FLAGS")` to return to the env default when finished. Confirm the active flavor with `JSON.stringify(features)` after importing, or just observe whether auth/cloud chrome is present.

## When to add a new flag

**A new pack of features must ship behind a feature flag whenever it is significant or not universally available across deployment flavors.** The goal is that every flavor can freely enable or disable it.
Expand Down
3 changes: 2 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ docker-compose up -d

- For any frontend visual change, use the `agent-browser` skill to view the result in a browser instead of working blind. If it is not installed, prompt the user to install it.
- The frontend dashboard dev server always runs at `http://localhost:43708/`. Check that it is already serving there before starting a new one.
- The same change can render differently per deployment flavor. Verify visual changes in OSS and cloud (at minimum), not just whichever flavor the dev server defaults to. See [Frontend Feature Flags](#frontend-feature-flags).

## Frontend Forms

Expand All @@ -105,7 +106,7 @@ docker-compose up -d
- The dashboard serves multiple deployment flavors (cloud / OSS / enterprise) from one build via flags in `frontend/src/lib/features.ts`; consume them through `import { features } from "@/lib/features"`, never by reading `VITE_FEATURE_FLAGS` directly.
- Ship a new pack of features behind a feature flag whenever it is significant (a whole panel/page/subsystem) or not universally available across flavors, so each flavor can freely enable or disable it. Do not gate small universal changes, and do not make flags for everything.
- If unsure whether a feature needs a flag, confirm the need with the user before adding or omitting one.
- See [Feature flags](.claude/reference/feature-flags.md) for the flag list, flavor mapping, and consistency rules.
- Test frontend changes across flavors before calling them done, especially OSS (it turns the most off and regresses most often). Switch flavors in dev by setting `localStorage.FEATURE_FLAGS` and reloading. See [Feature flags](.claude/reference/feature-flags.md) for the flag list, flavor mapping, the per-flavor flag sets, and consistency rules.

## Frontend Routing (TanStack Router)

Expand Down
3 changes: 3 additions & 0 deletions frontend/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Frontend

- The frontend build embedded into `rivet-engine` must use `pnpm build:engine` / `npx turbo build:engine -F @rivetkit/engine-frontend`, which sets `BASE_URL=/ui/`. Do not compensate for a root `/assets/*` build by adding root asset routes to the engine; fix the embedded build base instead.
- The dashboard serves multiple deployment flavors (cloud / OSS / enterprise) from one build via `features.*`. Test frontend changes in more than one flavor before calling them done. **OSS especially**, since it disables `auth`/`platform`/`acl` and takes different code paths (context switcher, sidebar, onboarding, data providers) that the cloud default never exercises. Switch flavors in the browser console with `localStorage.setItem("FEATURE_FLAGS", "")` (OSS) / `localStorage.removeItem("FEATURE_FLAGS")` then reload. See [Feature flags](../.claude/reference/feature-flags.md#testing-across-flavors-required-for-frontend-changes).
- **OSS and platform (cloud/EE) layouts must not visually diverge.** The same screens take different code paths per flavor (engine vs cloud routes/data providers), but they should look the same. Known parallel pairs that must be kept in sync: the namespace landing (engine [src/app/engine-namespace-landing.tsx](src/app/engine-namespace-landing.tsx) vs cloud [src/app/actors-grid.tsx](src/app/actors-grid.tsx), sharing `ActorBuildCard` / `ActorGridCardSkeleton`) and the namespace settings drawer (one flavor-aware [src/app/settings-drawer.tsx](src/app/settings-drawer.tsx) where engine shows only the Namespace section). When you change one side of a pair, mirror the other, and prefer sharing the presentational component over duplicating markup.
- Engine and cloud namespace index routes both render the Actor-grid landing when no Actor name (`n`) is selected; do not auto-redirect into the first build/actor. Selecting a build sets `n` and shows the Actor list/detail.
- Ship a Ladle story alongside any new UI component, but only when the story would teach something a reader can't see from the component's source or the design system's existing stories. Run with `pnpm dev:ladle` from `frontend/`. Existing example: [src/app/runner-pool-error-popover.stories.tsx](src/app/runner-pool-error-popover.stories.tsx).
- **Story the integration unit, not the wrapper.** If a component is a thin wrapper over a primitive (e.g. a `<Badge>` with three label variants), do not write a story for it — story the parent that combines it with other state. The interesting states live where data shapes interact: row + cell + tooltip, form + validation + submit. A trivial wrapper's "three near-identical renders" is noise, not coverage.
- **Drive stories from realistic data fixtures, not prop permutations.** Build fixtures that mirror real API responses (empty result, single item, multi-region, partial failure, mixed kinds). Each story should answer "what does this look like when the backend returns X?" Listing every prop combination produces stories that pass design review but miss bugs like an empty endpoint set falling through to "Multiple endpoints".
Expand Down
100 changes: 52 additions & 48 deletions frontend/src/app/actors-grid.tsx

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading