Contributing

Last updated on May 16, 2026

Contributing

OrangeRails is Apache 2.0 open source. PRs welcome, repo conventions and branch model below so your contribution lands smoothly.


Branch model

Two branches, two URLs. There is no main.

dev   ← Lovable + agents + PRs land here; auto-deploys to dev.orangerails.com
prod  ← merged from dev when ready; auto-deploys to orangerails.com (live)

Promotion is explicit — a fast-forward merge from dev to prod and a push. Full mental model: Branch flow — dev and prod.


PR conventions

  • Open against dev as the base branch (it's the GitHub default — should auto-select).
  • One commit per logical change is preferred; the maintainer squashes on merge anyway.
  • Commit message style: type(scope): subject — see existing git log --oneline for examples. Types we use: feat, fix, chore, docs, ci, copy, refactor, test.
  • CI must pass before merge (bun run build, type-check, stress test).

Setting up locally

gh repo clone MorningRevolution/orangerails
cd orangerails
bun install
bun run dev    # starts the Vite dev server at localhost:8080

For backend work (edge functions), you'll need a Supabase project. Either:

  • Use the hosted dev project (ask a maintainer for read access)
  • Run Supabase locally via supabase start (uses the supabase/config.toml in the repo)

Set environment variables in .env:

VITE_SUPABASE_URL=https://gposxxmxenrdvewrprle.supabase.co
VITE_SUPABASE_PUBLISHABLE_KEY=<your-anon-key>
VITE_SUPABASE_PROJECT_ID=gposxxmxenrdvewrprle

.env.example has the canonical values to copy.


Repo layout

src/
  routes/             TanStack Router file-based routes
  components/         Reusable UI components
  components/landing/ Marketing-page components
  hooks/              React hooks
  lib/                Pure utilities (encryption, providers fetch, etc.)
  integrations/       Supabase client + types
  stealth/            Stealth Sync widget (postMessage protocol)

supabase/
  functions/          Edge functions (or-providers, or-sync, or-connection-*, etc.)
  functions/_shared/  Shared types + adapter framework + sink dispatch
  migrations/         Versioned SQL (idempotent guards required)

scripts/
  generate-ccxt-manifest.mjs    Regenerates _ccxt-manifest.ts from CCXT
  stress-test-ccxt.mjs          Catches CCXT version drift
  prerender-plugin.ts           Vite plugin for SEO-friendly static HTML

Adding a feature

Frontend-only

  1. Branch from dev: git checkout -b feat/your-feature
  2. Write the code under src/
  3. Run bun run build to type-check
  4. Open PR against dev

Backend-only

  1. Edit edge function under supabase/functions/<fn>/index.ts
  2. If schema changes, add a migration under supabase/migrations/<timestamp>_<slug>.sql (use idempotent guards: CREATE TABLE IF NOT EXISTS, DROP POLICY IF EXISTS before each CREATE POLICY, etc.)
  3. Test locally: supabase functions serve <fn>
  4. Open PR

New source adapter

See the Adapter SDK guide. Short version: implement ProviderAdapter in supabase/functions/_shared/providers/<slug>.ts, register in dispatch.ts, ship.


Code style

  • TypeScript everywhere. No any unless there's a comment explaining why.
  • Plain English in user-facing copy. No "rotate", "encrypt", "decrypt", "ciphertext" — say "lock", "open the box", "scrambled bytes" instead.
  • No em-dashes in user-facing copy. Commas, periods, parentheses, or restructure.
  • No compound-word hyphens in user-facing copy ("customer facing" not "customer-facing"). Hyphens stay in identifiers and slugs.
  • ESLint runs in CI but is continue-on-error: true — fix warnings if you see them but don't let them block.

What we don't accept (yet)

  • PRs that break zero-knowledge. The architecture rule is server stores ciphertext only for credentials, transaction details, and Stealth Sync data. PRs that move plaintext server-side will be rejected.
  • PRs that add hard dependencies on a non-free service without a self-host fallback.
  • PRs that change the public API in breaking ways without a deprecation cycle (additive changes only, per the OpenAPI versioning policy — Phase 1 work).

Discussion


License

Apache 2.0. See LICENSE in the repo root. By contributing, you agree your contribution is licensed under Apache 2.0.