From 9baa04398beb282ea0e7f51c41a453672c37fa57 Mon Sep 17 00:00:00 2001 From: Andrew Nguyen Date: Fri, 19 Dec 2025 02:05:47 -0800 Subject: [PATCH 1/8] Add local setup to README --- README.md | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 06e04e9..43d6d34 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,110 @@ NEXT_PUBLIC_SUPABASE_URL= NEXT_PUBLIC_SUPABASE_ANON_KEY= ``` -These keys are safe to expose to the browser but should be scoped to the realtime channel only via Supabase RLS/policies. +### Local Supabase Development + +The repo includes a Supabase CLI project under `supabase/` with config and migrations, so you can run the full stack locally. + +#### 1. Prerequisites + +- Docker Desktop + - **macOS**: https://docs.docker.com/desktop/install/mac-install/ + - **Windows**: https://docs.docker.com/desktop/install/windows-install/ + - After installing, start Docker Desktop and wait until it reports that Docker is running. +- Supabase CLI + + - **macOS (Homebrew)**: + + ```sh + brew install supabase/tap/supabase + ``` + + - **Windows (npm)** – requires Node.js: + + ```sh + npm install -g supabase + ``` + + - Verify install (all platforms): + + ```sh + supabase --version + ``` + +#### 2. GitHub OAuth (local-only) + +To log in with GitHub against your local Supabase instance, you need a GitHub OAuth app: + +1. Go to `https://github.com/settings/developers` → **OAuth Apps** → **New OAuth App** +2. Use these settings: + - **Application name**: `DEVx Local` + - **Homepage URL**: `http://localhost:3000` + - **Authorization callback URL**: `http://127.0.0.1:54321/auth/v1/callback` +3. After creating the app, you'll see the **Client ID** immediately on the app's page. For the **Client secret**, click **"Generate a new client secret"** if you don't see one, then copy both values. +4. Create `supabase/.env` (this file is git-ignored): + + ```sh + cd supabase + cat > .env << 'EOF' + SUPABASE_AUTH_EXTERNAL_GITHUB_CLIENT_ID=your_client_id_here + SUPABASE_AUTH_EXTERNAL_GITHUB_SECRET=your_client_secret_here + EOF + ``` + +> Note: The **Client ID** is visible on your OAuth app's page at `https://github.com/settings/developers` immediately after creating the app. The **Client secret** must be generated (or regenerated if lost) by clicking "Generate a new client secret" on the same page. If you've already created the app, you can find it listed under **OAuth Apps** and click on it to view or regenerate the credentials. + +`supabase/config.toml` is already configured to read these env vars via: + +```toml +[auth.external.github] +enabled = true +client_id = "env(SUPABASE_AUTH_EXTERNAL_GITHUB_CLIENT_ID)" +secret = "env(SUPABASE_AUTH_EXTERNAL_GITHUB_SECRET)" +``` + +#### 3. Start the local Supabase stack + +From the repo root: + +```sh +supabase start +``` + +On success, you should see output including: + +- **Project URL**: `http://127.0.0.1:54321` +- **Studio**: `http://127.0.0.1:54323` +- **Database**: `postgresql://postgres:postgres@127.0.0.1:54322/postgres` + +If you change migrations or want a clean slate: + +```sh +supabase stop +supabase db reset # WARNING: destroys local data, reapplies migrations +supabase start +``` + +#### 4. Point the Next.js app at local Supabase + +Update `.env.local` in the project root: + +```sh +NEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321 +NEXT_PUBLIC_SUPABASE_ANON_KEY=sb_publishable_ACJWlzQHlZjBrEguHvfOxg_3BJgxAaH +``` + +> Note: the `sb_publishable_...` key is printed in the `supabase start` output under “Authentication Keys → Publishable”. + +Restart the dev server after changing `.env.local`. + +#### 5. Common local issues + +- **`"no Route matched with those values"` at `127.0.0.1:54321`** + This is normal for the bare API root. Use Studio (`http://127.0.0.1:54323`) or `http://localhost:3000` instead. +- **`"Unsupported provider: provider is not enabled"` when logging in with GitHub** + Ensure `[auth.external.github]` is present and `enabled = true` in `supabase/config.toml`, that `SUPABASE_AUTH_EXTERNAL_GITHUB_CLIENT_ID` and `SUPABASE_AUTH_EXTERNAL_GITHUB_SECRET` are set in `supabase/.env`, then run `supabase stop && supabase start`. +- **Docker daemon errors (`Cannot connect to the Docker daemon`)** + Make sure Docker Desktop is installed and running before you call `supabase start`. **Note: This project is being refactored to use styled-components exclusively. Please do not add new Tailwind classes. See [styling guidelines](./docs/conventions/styling-guidelines.md) for details.** From 5d32f5019182cf02e06f16bd908b1f18e113e496 Mon Sep 17 00:00:00 2001 From: Sam Holmes Date: Thu, 22 Jan 2026 08:00:32 -0800 Subject: [PATCH 2/8] Fix supabase migration file names The dates in the names were incorrect causing failure to setup/migrate databases. One file in particular was ordered incorrectly causing the failure. --- ..._id_to_member.sql => 20251121200000_add_user_id_to_member.sql} | 0 ...ine_to_profiles.sql => 20251121200001_combine_to_profiles.sql} | 0 ...torage_bucket.sql => 20251121200002_create_storage_bucket.sql} | 0 ..._skills.sql => 20251121200003_create_interests_and_skills.sql} | 0 ...s.sql => 20251121200004_seed_default_interests_and_skills.sql} | 0 ..._to_profiles.sql => 20251122000000_add_handle_to_profiles.sql} | 0 ..._profile_links.sql => 20251122000001_create_profile_links.sql} | 0 ...rder_to_tags.sql => 20251122000002_add_sort_order_to_tags.sql} | 0 ...submissions.sql => 20251122000003_create_talk_submissions.sql} | 0 ...es_bucket.sql => 20251122000004_create_talk_slides_bucket.sql} | 0 ...ofiles.sql => 20251122000005_add_phone_number_to_profiles.sql} | 0 ... 20251122000006_remove_phone_number_from_talk_submissions.sql} | 0 ...d_constraints.sql => 20251122000007_add_field_constraints.sql} | 0 ...ql => 20251122000008_add_file_size_and_format_constraints.sql} | 0 ..._tables.sql => 20251122000009_enable_rls_on_public_tables.sql} | 0 ...5_add_rls_policies.sql => 20251122000010_add_rls_policies.sql} | 0 ...pattern.sql => 20251124000000_update_handle_regex_pattern.sql} | 0 17 files changed, 0 insertions(+), 0 deletions(-) rename supabase/migrations/{20250122000000_add_user_id_to_member.sql => 20251121200000_add_user_id_to_member.sql} (100%) rename supabase/migrations/{20250122000001_combine_to_profiles.sql => 20251121200001_combine_to_profiles.sql} (100%) rename supabase/migrations/{20250122000002_create_storage_bucket.sql => 20251121200002_create_storage_bucket.sql} (100%) rename supabase/migrations/{20250122000003_create_interests_and_skills.sql => 20251121200003_create_interests_and_skills.sql} (100%) rename supabase/migrations/{20250122000004_seed_default_interests_and_skills.sql => 20251121200004_seed_default_interests_and_skills.sql} (100%) rename supabase/migrations/{20250122000005_add_handle_to_profiles.sql => 20251122000000_add_handle_to_profiles.sql} (100%) rename supabase/migrations/{20250122000006_create_profile_links.sql => 20251122000001_create_profile_links.sql} (100%) rename supabase/migrations/{20250122000007_add_sort_order_to_tags.sql => 20251122000002_add_sort_order_to_tags.sql} (100%) rename supabase/migrations/{20250122000008_create_talk_submissions.sql => 20251122000003_create_talk_submissions.sql} (100%) rename supabase/migrations/{20250122000009_create_talk_slides_bucket.sql => 20251122000004_create_talk_slides_bucket.sql} (100%) rename supabase/migrations/{20250122000010_add_phone_number_to_profiles.sql => 20251122000005_add_phone_number_to_profiles.sql} (100%) rename supabase/migrations/{20250122000011_remove_phone_number_from_talk_submissions.sql => 20251122000006_remove_phone_number_from_talk_submissions.sql} (100%) rename supabase/migrations/{20250122000012_add_field_constraints.sql => 20251122000007_add_field_constraints.sql} (100%) rename supabase/migrations/{20250122000013_add_file_size_and_format_constraints.sql => 20251122000008_add_file_size_and_format_constraints.sql} (100%) rename supabase/migrations/{20250122000014_enable_rls_on_public_tables.sql => 20251122000009_enable_rls_on_public_tables.sql} (100%) rename supabase/migrations/{20250122000015_add_rls_policies.sql => 20251122000010_add_rls_policies.sql} (100%) rename supabase/migrations/{20250122000016_update_handle_regex_pattern.sql => 20251124000000_update_handle_regex_pattern.sql} (100%) diff --git a/supabase/migrations/20250122000000_add_user_id_to_member.sql b/supabase/migrations/20251121200000_add_user_id_to_member.sql similarity index 100% rename from supabase/migrations/20250122000000_add_user_id_to_member.sql rename to supabase/migrations/20251121200000_add_user_id_to_member.sql diff --git a/supabase/migrations/20250122000001_combine_to_profiles.sql b/supabase/migrations/20251121200001_combine_to_profiles.sql similarity index 100% rename from supabase/migrations/20250122000001_combine_to_profiles.sql rename to supabase/migrations/20251121200001_combine_to_profiles.sql diff --git a/supabase/migrations/20250122000002_create_storage_bucket.sql b/supabase/migrations/20251121200002_create_storage_bucket.sql similarity index 100% rename from supabase/migrations/20250122000002_create_storage_bucket.sql rename to supabase/migrations/20251121200002_create_storage_bucket.sql diff --git a/supabase/migrations/20250122000003_create_interests_and_skills.sql b/supabase/migrations/20251121200003_create_interests_and_skills.sql similarity index 100% rename from supabase/migrations/20250122000003_create_interests_and_skills.sql rename to supabase/migrations/20251121200003_create_interests_and_skills.sql diff --git a/supabase/migrations/20250122000004_seed_default_interests_and_skills.sql b/supabase/migrations/20251121200004_seed_default_interests_and_skills.sql similarity index 100% rename from supabase/migrations/20250122000004_seed_default_interests_and_skills.sql rename to supabase/migrations/20251121200004_seed_default_interests_and_skills.sql diff --git a/supabase/migrations/20250122000005_add_handle_to_profiles.sql b/supabase/migrations/20251122000000_add_handle_to_profiles.sql similarity index 100% rename from supabase/migrations/20250122000005_add_handle_to_profiles.sql rename to supabase/migrations/20251122000000_add_handle_to_profiles.sql diff --git a/supabase/migrations/20250122000006_create_profile_links.sql b/supabase/migrations/20251122000001_create_profile_links.sql similarity index 100% rename from supabase/migrations/20250122000006_create_profile_links.sql rename to supabase/migrations/20251122000001_create_profile_links.sql diff --git a/supabase/migrations/20250122000007_add_sort_order_to_tags.sql b/supabase/migrations/20251122000002_add_sort_order_to_tags.sql similarity index 100% rename from supabase/migrations/20250122000007_add_sort_order_to_tags.sql rename to supabase/migrations/20251122000002_add_sort_order_to_tags.sql diff --git a/supabase/migrations/20250122000008_create_talk_submissions.sql b/supabase/migrations/20251122000003_create_talk_submissions.sql similarity index 100% rename from supabase/migrations/20250122000008_create_talk_submissions.sql rename to supabase/migrations/20251122000003_create_talk_submissions.sql diff --git a/supabase/migrations/20250122000009_create_talk_slides_bucket.sql b/supabase/migrations/20251122000004_create_talk_slides_bucket.sql similarity index 100% rename from supabase/migrations/20250122000009_create_talk_slides_bucket.sql rename to supabase/migrations/20251122000004_create_talk_slides_bucket.sql diff --git a/supabase/migrations/20250122000010_add_phone_number_to_profiles.sql b/supabase/migrations/20251122000005_add_phone_number_to_profiles.sql similarity index 100% rename from supabase/migrations/20250122000010_add_phone_number_to_profiles.sql rename to supabase/migrations/20251122000005_add_phone_number_to_profiles.sql diff --git a/supabase/migrations/20250122000011_remove_phone_number_from_talk_submissions.sql b/supabase/migrations/20251122000006_remove_phone_number_from_talk_submissions.sql similarity index 100% rename from supabase/migrations/20250122000011_remove_phone_number_from_talk_submissions.sql rename to supabase/migrations/20251122000006_remove_phone_number_from_talk_submissions.sql diff --git a/supabase/migrations/20250122000012_add_field_constraints.sql b/supabase/migrations/20251122000007_add_field_constraints.sql similarity index 100% rename from supabase/migrations/20250122000012_add_field_constraints.sql rename to supabase/migrations/20251122000007_add_field_constraints.sql diff --git a/supabase/migrations/20250122000013_add_file_size_and_format_constraints.sql b/supabase/migrations/20251122000008_add_file_size_and_format_constraints.sql similarity index 100% rename from supabase/migrations/20250122000013_add_file_size_and_format_constraints.sql rename to supabase/migrations/20251122000008_add_file_size_and_format_constraints.sql diff --git a/supabase/migrations/20250122000014_enable_rls_on_public_tables.sql b/supabase/migrations/20251122000009_enable_rls_on_public_tables.sql similarity index 100% rename from supabase/migrations/20250122000014_enable_rls_on_public_tables.sql rename to supabase/migrations/20251122000009_enable_rls_on_public_tables.sql diff --git a/supabase/migrations/20250122000015_add_rls_policies.sql b/supabase/migrations/20251122000010_add_rls_policies.sql similarity index 100% rename from supabase/migrations/20250122000015_add_rls_policies.sql rename to supabase/migrations/20251122000010_add_rls_policies.sql diff --git a/supabase/migrations/20250122000016_update_handle_regex_pattern.sql b/supabase/migrations/20251124000000_update_handle_regex_pattern.sql similarity index 100% rename from supabase/migrations/20250122000016_update_handle_regex_pattern.sql rename to supabase/migrations/20251124000000_update_handle_regex_pattern.sql From a77135b7b5c34817180a3dc9e5ff3cf849852bac Mon Sep 17 00:00:00 2001 From: Sam Holmes Date: Thu, 22 Jan 2026 08:05:01 -0800 Subject: [PATCH 3/8] Match all .env file names in gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 393c77a..034ae03 100644 --- a/.gitignore +++ b/.gitignore @@ -26,7 +26,7 @@ yarn-debug.log* yarn-error.log* # local env files -.env* +.env** # vercel .vercel From 81bf8057472356985457b6547752936ca4a8355b Mon Sep 17 00:00:00 2001 From: Sam Holmes Date: Thu, 22 Jan 2026 08:06:31 -0800 Subject: [PATCH 4/8] docs(readme): link to official Supabase CLI install docs Instead of duplicating installation instructions that may become outdated, link directly to the official documentation. --- README.md | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 43d6d34..666be5e 100644 --- a/README.md +++ b/README.md @@ -50,29 +50,8 @@ The repo includes a Supabase CLI project under `supabase/` with config and migra #### 1. Prerequisites -- Docker Desktop - - **macOS**: https://docs.docker.com/desktop/install/mac-install/ - - **Windows**: https://docs.docker.com/desktop/install/windows-install/ - - After installing, start Docker Desktop and wait until it reports that Docker is running. -- Supabase CLI - - - **macOS (Homebrew)**: - - ```sh - brew install supabase/tap/supabase - ``` - - - **Windows (npm)** – requires Node.js: - - ```sh - npm install -g supabase - ``` - - - Verify install (all platforms): - - ```sh - supabase --version - ``` +- **Docker Desktop** – [Install Docker Desktop](https://docs.docker.com/desktop/) and ensure it's running before starting Supabase. +- **Supabase CLI** – [Install the Supabase CLI](https://supabase.com/docs/guides/local-development/cli/getting-started#installing-the-supabase-cli) for your platform. #### 2. GitHub OAuth (local-only) From f60fde17c360a4c6506a674e32a5ff4e0515ba7d Mon Sep 17 00:00:00 2001 From: Sam Holmes Date: Thu, 22 Jan 2026 08:07:24 -0800 Subject: [PATCH 5/8] docs: recommend username/password auth, move OAuth setup to separate guide - Username/password auth works out of the box for local testing - OAuth setup (GitHub, Google) moved to docs/local-oauth-setup.md - Removed incorrect reference to config.toml having GitHub OAuth (it wasn't actually configured) Addresses PR #66 review comments. --- README.md | 43 +++++------------------ docs/local-oauth-setup.md | 74 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 35 deletions(-) create mode 100644 docs/local-oauth-setup.md diff --git a/README.md b/README.md index 666be5e..023d885 100644 --- a/README.md +++ b/README.md @@ -53,38 +53,7 @@ The repo includes a Supabase CLI project under `supabase/` with config and migra - **Docker Desktop** – [Install Docker Desktop](https://docs.docker.com/desktop/) and ensure it's running before starting Supabase. - **Supabase CLI** – [Install the Supabase CLI](https://supabase.com/docs/guides/local-development/cli/getting-started#installing-the-supabase-cli) for your platform. -#### 2. GitHub OAuth (local-only) - -To log in with GitHub against your local Supabase instance, you need a GitHub OAuth app: - -1. Go to `https://github.com/settings/developers` → **OAuth Apps** → **New OAuth App** -2. Use these settings: - - **Application name**: `DEVx Local` - - **Homepage URL**: `http://localhost:3000` - - **Authorization callback URL**: `http://127.0.0.1:54321/auth/v1/callback` -3. After creating the app, you'll see the **Client ID** immediately on the app's page. For the **Client secret**, click **"Generate a new client secret"** if you don't see one, then copy both values. -4. Create `supabase/.env` (this file is git-ignored): - - ```sh - cd supabase - cat > .env << 'EOF' - SUPABASE_AUTH_EXTERNAL_GITHUB_CLIENT_ID=your_client_id_here - SUPABASE_AUTH_EXTERNAL_GITHUB_SECRET=your_client_secret_here - EOF - ``` - -> Note: The **Client ID** is visible on your OAuth app's page at `https://github.com/settings/developers` immediately after creating the app. The **Client secret** must be generated (or regenerated if lost) by clicking "Generate a new client secret" on the same page. If you've already created the app, you can find it listed under **OAuth Apps** and click on it to view or regenerate the credentials. - -`supabase/config.toml` is already configured to read these env vars via: - -```toml -[auth.external.github] -enabled = true -client_id = "env(SUPABASE_AUTH_EXTERNAL_GITHUB_CLIENT_ID)" -secret = "env(SUPABASE_AUTH_EXTERNAL_GITHUB_SECRET)" -``` - -#### 3. Start the local Supabase stack +#### 2. Start the local Supabase stack From the repo root: @@ -106,7 +75,7 @@ supabase db reset # WARNING: destroys local data, reapplies migrations supabase start ``` -#### 4. Point the Next.js app at local Supabase +#### 3. Point the Next.js app at local Supabase Update `.env.local` in the project root: @@ -119,12 +88,16 @@ NEXT_PUBLIC_SUPABASE_ANON_KEY=sb_publishable_ACJWlzQHlZjBrEguHvfOxg_3BJgxAaH Restart the dev server after changing `.env.local`. +#### 4. Authentication + +For local testing, **username/password authentication** works out of the box – just sign up with any email and password in the app. + +For OAuth providers (GitHub, Google), see the [Local OAuth Setup Guide](./docs/local-oauth-setup.md). + #### 5. Common local issues - **`"no Route matched with those values"` at `127.0.0.1:54321`** This is normal for the bare API root. Use Studio (`http://127.0.0.1:54323`) or `http://localhost:3000` instead. -- **`"Unsupported provider: provider is not enabled"` when logging in with GitHub** - Ensure `[auth.external.github]` is present and `enabled = true` in `supabase/config.toml`, that `SUPABASE_AUTH_EXTERNAL_GITHUB_CLIENT_ID` and `SUPABASE_AUTH_EXTERNAL_GITHUB_SECRET` are set in `supabase/.env`, then run `supabase stop && supabase start`. - **Docker daemon errors (`Cannot connect to the Docker daemon`)** Make sure Docker Desktop is installed and running before you call `supabase start`. diff --git a/docs/local-oauth-setup.md b/docs/local-oauth-setup.md new file mode 100644 index 0000000..3c9aafb --- /dev/null +++ b/docs/local-oauth-setup.md @@ -0,0 +1,74 @@ +# Local OAuth Setup Guide + +This guide explains how to set up OAuth providers (GitHub, Google, etc.) for local Supabase development. This is **optional** – username/password authentication works out of the box. + +## GitHub OAuth + +To log in with GitHub against your local Supabase instance: + +### 1. Create a GitHub OAuth App + +1. Go to https://github.com/settings/developers → **OAuth Apps** → **New OAuth App** +2. Use these settings: + - **Application name**: `DEVx Local` + - **Homepage URL**: `http://localhost:3000` + - **Authorization callback URL**: `http://127.0.0.1:54321/auth/v1/callback` +3. After creating the app, copy the **Client ID** from the app's page +4. Click **"Generate a new client secret"** and copy the secret + +### 2. Configure Supabase + +Add GitHub OAuth configuration to `supabase/config.toml`: + +```toml +[auth.external.github] +enabled = true +client_id = "env(SUPABASE_AUTH_EXTERNAL_GITHUB_CLIENT_ID)" +secret = "env(SUPABASE_AUTH_EXTERNAL_GITHUB_SECRET)" +``` + +### 3. Set Environment Variables + +Create `supabase/.env` (this file is git-ignored): + +```sh +SUPABASE_AUTH_EXTERNAL_GITHUB_CLIENT_ID=your_client_id_here +SUPABASE_AUTH_EXTERNAL_GITHUB_SECRET=your_client_secret_here +``` + +### 4. Restart Supabase + +```sh +supabase stop && supabase start +``` + +## Google OAuth + +Similar steps apply for Google OAuth: + +1. Create OAuth credentials in the [Google Cloud Console](https://console.cloud.google.com/apis/credentials) +2. Set the authorized redirect URI to `http://127.0.0.1:54321/auth/v1/callback` +3. Add to `supabase/config.toml`: + +```toml +[auth.external.google] +enabled = true +client_id = "env(SUPABASE_AUTH_EXTERNAL_GOOGLE_CLIENT_ID)" +secret = "env(SUPABASE_AUTH_EXTERNAL_GOOGLE_SECRET)" +skip_nonce_check = true +``` + +4. Add credentials to `supabase/.env` + +## Troubleshooting + +### "Unsupported provider: provider is not enabled" + +- Ensure the provider section exists in `supabase/config.toml` with `enabled = true` +- Verify environment variables are set in `supabase/.env` +- Restart Supabase: `supabase stop && supabase start` + +### OAuth callback errors + +- Verify the callback URL in your OAuth app matches exactly: `http://127.0.0.1:54321/auth/v1/callback` +- Note: Use `127.0.0.1` not `localhost` for the callback URL From 007e8b583c00d3b1798a52fc2cfddf7f98866eb9 Mon Sep 17 00:00:00 2001 From: Sam Holmes Date: Thu, 22 Jan 2026 08:12:22 -0800 Subject: [PATCH 6/8] docs(readme): move styled-components note to Footnotes section --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 023d885..8daada3 100644 --- a/README.md +++ b/README.md @@ -101,8 +101,6 @@ For OAuth providers (GitHub, Google), see the [Local OAuth Setup Guide](./docs/l - **Docker daemon errors (`Cannot connect to the Docker daemon`)** Make sure Docker Desktop is installed and running before you call `supabase start`. -**Note: This project is being refactored to use styled-components exclusively. Please do not add new Tailwind classes. See [styling guidelines](./docs/conventions/styling-guidelines.md) for details.** - ## Contributing We welcome contributions from the community! If you have suggestions or improvements, feel free to open an issue or submit a pull request. @@ -141,3 +139,7 @@ For detailed code style and organization guidelines: git push origin feature-name ``` 5. **Open a pull request on Github** + +## Footnotes + +> **Note:** This project is being refactored to use styled-components exclusively. Please do not add new Tailwind classes. See [styling guidelines](./docs/conventions/styling-guidelines.md) for details. From ea528ed001189459b15221ca65c03cefb2968d37 Mon Sep 17 00:00:00 2001 From: Sam Holmes Date: Thu, 22 Jan 2026 08:23:26 -0800 Subject: [PATCH 7/8] feat(auth): auto-detect email confirmation requirement on signup If email confirmation is disabled (local dev), Supabase returns a session immediately after signup. The code now checks for this and redirects to /setup instead of showing 'Check your email'. In production where email confirmation is enabled, the success message is shown as before. --- app/login/page.tsx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/app/login/page.tsx b/app/login/page.tsx index 2e3d4b4..0eaf641 100644 --- a/app/login/page.tsx +++ b/app/login/page.tsx @@ -188,9 +188,18 @@ export default function Login() { if (signUpError) throw signUpError - // Email confirmation required - show success message - setError(null) - setSignupSuccess(true) + // Check if email confirmation is required by checking if session exists + // Supabase only returns a session on signup if email confirmation is disabled + if (data.session) { + // No email confirmation required - redirect to setup + const setupUrl = redirectUrl + ? `/setup?redirect=${encodeURIComponent(redirectUrl)}` + : "/setup" + router.push(setupUrl) + } else { + // Email confirmation required - show success message + setSignupSuccess(true) + } } catch (err: any) { setError(err.message) } finally { From b940433cf3bee5f21b4f7bbc18efa6692b6cfd7c Mon Sep 17 00:00:00 2001 From: Sam Holmes Date: Thu, 22 Jan 2026 08:28:22 -0800 Subject: [PATCH 8/8] feat(auth): add 'Continue with Email' button to streamline login UI - Show OAuth buttons (Google, GitHub) by default with tertiary 'Continue with Email' button below - Email form only appears when user clicks 'Continue with Email' - Added 'Back to sign in options' link to return to OAuth view - Removed divider and form title for cleaner interface --- app/login/page.tsx | 190 ++++++++++++++++++++++++--------------------- 1 file changed, 103 insertions(+), 87 deletions(-) diff --git a/app/login/page.tsx b/app/login/page.tsx index 0eaf641..331f251 100644 --- a/app/login/page.tsx +++ b/app/login/page.tsx @@ -17,6 +17,7 @@ export default function Login() { const [signingIn, setSigningIn] = useState(false) const [signingUp, setSigningUp] = useState(false) const [signupSuccess, setSignupSuccess] = useState(false) + const [showEmailForm, setShowEmailForm] = useState(false) const router = useRouter() useEffect(() => { @@ -81,7 +82,7 @@ export default function Login() { checkAuth() }, [router]) - const handleLogin = async (provider: "google" | "github") => { + const handleLogin = (provider: "google" | "github") => async () => { try { setError(null) // Get redirect URL from query params to preserve it through OAuth flow @@ -207,6 +208,16 @@ export default function Login() { } } + const handleBackClick = () => { + setError(null) + setShowEmailForm(false) + } + + const handleContinueEmailClick = () => { + setError(null) + setShowEmailForm(true) + } + return ( <> @@ -228,80 +239,83 @@ export default function Login() { {error && {error}} - - - - - - - - - { - e.preventDefault() - handleEmailSignIn(e) - }} - > - Sign In with Email - - setEmail(e.target.value)} - placeholder="Email" - required - disabled={signingIn || signingUp} - /> - - - setPassword(e.target.value)} - placeholder="Password" - required - minLength={6} - disabled={signingIn || signingUp} - /> - - Password must be at least 6 characters with lowercase, uppercase, digits, and - symbols - - - - + + + + ← Back to sign in options + + + ) : ( + + - + + - - + + )} )} @@ -363,12 +377,6 @@ const ErrorMessage = styled.div` width: 100%; ` -const Divider = styled.hr` - border: none; - border-top: 1px solid rgba(255, 255, 255, 0.2); - width: 100%; -` - const EmailForm = styled.form` display: flex; flex-direction: column; @@ -390,14 +398,6 @@ const ButtonWrapper = styled.div` } ` -const FormTitle = styled.h2` - font-size: 1.25rem; - font-weight: 600; - color: rgba(255, 255, 255, 0.9); - margin: 0; - text-align: center; -` - const InputGroup = styled.div` display: flex; flex-direction: column; @@ -415,3 +415,19 @@ const PasswordHelpText = styled.p` const SuccessContainer = styled.div` width: 100%; ` + +const BackButton = styled.button` + background: none; + border: none; + color: rgba(255, 255, 255, 0.6); + font-size: 0.875rem; + cursor: pointer; + padding: 0.5rem; + margin-top: 0.5rem; + transition: color 0.2s ease; + font-family: inherit; + + &:hover { + color: rgba(255, 255, 255, 0.9); + } +`