Skip to main content

Feature workflow

The full lifecycle for shipping a change: branch → build → test → review → staging → production.

For local setup itself see local-setup.md. For the deploy mechanics (Vercel, GitHub Actions, secrets, rollback) see deploy.md.

1. Start a feature branch

git checkout staging
git pull --ff-only
git checkout -b <username>/<AIM-NNN>-<short-description>

Branch-name convention (per CLAUDE.md):

  • Prefix with your GitHub handle: petter/...
  • Include the Linear ticket ID if there is one: petter/AIM-815-fix-emissions-sorting
  • No ticket? Just describe the change: petter/docs-feature-workflow

Never commit on staging or production directly.

2. Develop

npm run dev # http://localhost:3000

Where things live (see architecture.md):

  • Routes / pages → app/routes/
  • Reusable UI → app/components/ (domain) or app/@/components/ui/ (design system)
  • Server-only services → app/.server/
  • Background jobs → tasks/<service>/
  • Schema changes → npm run migr <name> then edit supabase/migrations/<timestamp>_<name>.sql

If you change the schema:

  • Always enable RLS on new public tables, with an account-scoped policy. See architecture.md for the template.
  • Use SECURITY_INVOKER on views and prefer SECURITY INVOKER on functions.
  • Test the migration from scratch: npm run reset. If it errors, fix the migration — never edit a previously-merged one.

3. Test locally

Cheap iteration:

npm run typecheck # TS errors
npm run fix # eslint --fix .

Before you push, run the full gate the CI mirrors:

npm run precommit

That runs, in order: check-if-production-databasefixsupabase db reset (re-applies every migration on a clean DB) → supabase test dbgentypesgendocsfixbuild.

If precommit fails, fix it locally. CI will run the same checks on your PR and reject it for the same reason.

Manual smoke test in the browser: log in (see local-setup.md#login), exercise the feature path, hit edge cases. Type-checking and tests verify correctness of code, not correctness of feature.

4. Open a PR

git push -u origin <branch>
gh pr create --base staging \
--title "<short, imperative>" \
--body "<what changed, why, how to test>"

PR target is always staging, never production directly.

PR description should include:

  • Summary — 1–3 bullets, what and why
  • Test plan — checklist of what to verify on the staging deploy
  • Migrations / RLS — if you added either, call out the impact

What CI will run on the PR (ci.yml, database-tests.yml):

JobWhat it checks
CI / testgentypes + gendocs produce no diff → PR fails if app/types/supabase/, tasks/*/src/supabase.d.ts, or docs/schema/ is stale
database-testsRuns every .sql test in supabase/tests/database/ against a fresh DB

If either fails, fix and push again — the workflows re-run automatically.

5. Review and merge to staging

  • Self-review the diff on GitHub — easier to spot mistakes in the rendered view than in your editor.
  • Request review from a teammate via Linear or Slack.
  • Address comments by pushing more commits to the same branch (don't force-push unless you have to).
  • Once approved and CI is green, merge the PR (squash unless the commits are individually meaningful).

The merge triggers, on staging:

WorkflowWhat it does
VercelBuilds and deploys frontend to https://app-staging.aimabel.ai/
staging.ymlsupabase db push (applies new migrations) + supabase functions deploy
update-docs.ymlRegenerates types + schema docs; auto-commits if anything drifted

Watch them land:

gh pr checks <pr-number> # CI / deploys for the merged PR
gh run watch # follow the next workflow run

6. Verify on staging

  • Open https://app-staging.aimabel.ai/ and exercise your feature.
  • Walk through the test plan from your PR.
  • Watch for anything that might regress in other features.
  • For schema or RLS changes, double-check from a non-super-admin account that you can only see what you're supposed to.
  • Let it bake at least one working day before promoting (per deploy.md).

If something is broken on staging, fix it on a new feature branch and PR back to staging — don't push a fix directly to staging to "save time".

For risky features, ship behind a flag and roll out gradually:

  • Account-level flags live in basejump.accounts.public_metadata.feature_flags as a string array.
  • Read them via the same loader pattern used in other guarded routes (grep for feature_flags in app/).
  • Default off, opt-in for testing accounts first.

7. Promote to production

When you're satisfied staging is healthy:

gh pr create --base production --head staging \
--title "Promote staging → production (<date>)" \
--body "Includes: <list of PRs since last promotion>"

Merge that PR. The merge triggers:

WorkflowWhat it does
VercelDeploys frontend to https://app.aimabel.ai/
production.ymlsupabase db push + supabase functions deploy on the production project
update-docs.ymlSame as on staging — keeps generated files current

Verify on https://app.aimabel.ai/ immediately after deploy.

8. After ship

  • Mark the Linear ticket done.
  • Delete the feature branch (GitHub does this automatically if you ticked the checkbox).
  • If anything went wrong, see deploy.md#rolling-back.

TL;DR

staging ──────────────────────────────►
│ ▲
└─► petter/AIM-NNN-thing ──PR──► staging │ (auto-deploy to app-staging)

└──PR──► production (auto-deploy to app)

Direct pushes to staging or production are not part of this flow. Feature branches and PRs are the only path.