Skip to content
Open
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
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,10 @@ app.*.map.json
.netlify

# FVM Version Cache
.fvm/
.fvm/

# Supabase local stack (CLI-managed runtime artifacts; config.toml,
# migrations/ and seed.sql are committed, everything else is local-only)
supabase/.branches
supabase/.temp
supabase/.env
19 changes: 19 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Flutter (Web server, port 8080)",
"request": "launch",
"type": "dart",
"deviceId": "web-server",
"args": ["--web-port=8080"]
},
{
"name": "Flutter (Web server, port 8080, local Supabase)",
"request": "launch",
"type": "dart",
"deviceId": "web-server",
"args": ["--web-port=8080", "--dart-define=USE_LOCAL_SUPABASE=true"]
}
]
}
87 changes: 87 additions & 0 deletions docs/DEV_SETUP.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,92 @@
# Dev Setup Notes

## Local Supabase Stack

Test schema / RLS / RPC changes against a local database before running any
SQL against prod. This spins up a full local Supabase stack (Postgres,
GoTrue, PostgREST, Studio) in Docker. Nothing here touches the prod project.

### One-time prerequisites

- Supabase CLI: `brew install supabase/tap/supabase`
- A container runtime, either:
- Docker Desktop, **or**
- Podman (start the VM and point Docker's client API at Podman's socket,
since the Supabase CLI talks to whatever `DOCKER_HOST` points at):
```
podman machine init # first time only
podman machine start
export DOCKER_HOST=unix://$(podman machine inspect --format '{{.ConnectionInfo.PodmanSocket.Path}}')
```
Add the `export DOCKER_HOST=...` line to your shell profile so it's set
in every new terminal. If `supabase start` still can't find a runtime,
fall back to Docker Desktop or `colima` (`brew install colima && colima
start`).

### Bringing the DB up

The repo already tracks everything the CLI needs — `supabase/config.toml`
and `supabase/migrations/` — so no `supabase init` is required. Seed data
(the trick catalog) loads from `supabase/import_tricks2.sql`, wired via
`config.toml` → `[db.seed] sql_paths`.

1. `supabase start` — boots the stack and prints the local API URL, DB URL,
and Studio URL. Defaults:
- API: `http://127.0.0.1:54321`
- DB: `postgresql://postgres:postgres@127.0.0.1:54322/postgres`
- Studio: `http://127.0.0.1:54323`
2. `supabase db reset` — drops and rebuilds the DB from
`supabase/migrations/` in order, then loads the seed (trick catalog).
Run this whenever migrations change to get a clean, deterministic DB.

### Running the app against it

```
flutter run -d web-server --web-port=8080 --dart-define=USE_LOCAL_SUPABASE=true
```

`web-server` doesn't auto-open a browser — open `http://localhost:8080`
yourself once it's serving.

Or use the "Flutter (Web server, port 8080, local Supabase)" VS Code launch
config. This flips `SupabaseConfig` (`lib/supabase_config.dart`) over to the
local instance's fixed default URL/anon key — nothing to hand-edit, and
nothing that risks getting committed pointed at the wrong project. Omit the
`--dart-define` to run against prod.

### Schema source of truth

`supabase/migrations/` is authoritative for the CLI (`db reset` /
`db push`). `supabase/schema.sql` is the human-readable consolidated
snapshot of the same schema — keep the two in sync when adding a migration.
The older loose `add_*.sql` / `migrate_*.sql` files are historical one-offs
already folded into the baseline migration; kept for reference only.

Adding a schema change: create a new timestamped file under
`supabase/migrations/` (`supabase migration new <name>`), then `supabase db
reset` to verify it applies cleanly locally before it ever reaches prod.

**Prod already has the baseline.** `00000000000000_initial_schema.sql` is a
snapshot of the schema prod already runs — it is only replayed onto fresh
*local* DBs. Never `supabase db push` it to prod (its `create table`s would
conflict). When first linking migrations to the prod project, mark it as
already-applied so only *future* migrations push:
`supabase migration repair --status applied 00000000000000`.

## Flutter Web Should Use Port 8080

The VS Code launch configs and the local Supabase auth redirect URLs
(`config.toml` → `[auth] additional_redirect_urls`) assume Flutter web runs
on port 8080. A random port (the default for `flutter run -d chrome`) can
break auth redirects locally.

```
flutter run -d web-server --web-port=8080
```

The `.vscode/launch.json` "Flutter (Web server, port 8080)" configuration
does this automatically if you run/debug from VS Code instead of the CLI.

## Testing Flutter Web on a Physical Device

Run the dev server bound to all network interfaces so a phone on the same WiFi can reach it:
Expand Down
19 changes: 15 additions & 4 deletions lib/supabase_config.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
class SupabaseConfig {
// Replace these with your project values from:
// Supabase Dashboard → Project Settings → API
static const String url = 'https://ubsmdiesqofnfxuicwxj.supabase.co';
static const String anonKey = 'sb_publishable_EHLEMf4zv4Im0u3O6cwhXA_WzIuNDT9';
// Run with --dart-define=USE_LOCAL_SUPABASE=true to point at a local
// `supabase start` instance instead of prod. See docs/DEV_SETUP.md.
static const bool useLocal = bool.fromEnvironment('USE_LOCAL_SUPABASE');

static const String _prodUrl = 'https://ubsmdiesqofnfxuicwxj.supabase.co';
static const String _prodAnonKey = 'sb_publishable_EHLEMf4zv4Im0u3O6cwhXA_WzIuNDT9';

// Fixed defaults every `supabase start` local instance uses out of the
// box - not a secret, safe to hardcode.
static const String _localUrl = 'http://127.0.0.1:54321';
static const String _localAnonKey =
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0';

static String get url => useLocal ? _localUrl : _prodUrl;
static String get anonKey => useLocal ? _localAnonKey : _prodAnonKey;
}
50 changes: 50 additions & 0 deletions supabase/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Local Supabase stack config. Regenerate with `supabase init` if your CLI
# version rejects any field below.
project_id = "freestyle"

[api]
enabled = true
port = 54321
schemas = ["public", "graphql_public"]
extra_search_path = ["public", "extensions"]
max_rows = 1000

[db]
port = 54322
shadow_port = 54320
major_version = 15

# Seed runs through the CLI's SQL driver (not psql), so files must be plain
# SQL - no `\i` / meta-commands. Point directly at the data files.
# import_tricks2.sql is the fuller catalog (positions + 391 tricks).
[db.seed]
enabled = true
sql_paths = ["./import_tricks2.sql", "./seed_users.sql"]

[studio]
enabled = true
port = 54323

[inbucket]
enabled = true
port = 54324

[auth]
enabled = true
site_url = "http://127.0.0.1:8080"
additional_redirect_urls = ["http://127.0.0.1:8080", "http://localhost:8080"]
jwt_expiry = 3600
enable_signup = true

[auth.email]
enable_signup = true
enable_confirmations = false

[storage]
enabled = true
file_size_limit = "50MiB"

# Analytics (logflare) + its vector log shipper bind-mount the Docker
# socket, which Podman can't mount as a volume. Not needed for local dev.
[analytics]
enabled = false
Loading