# Building an "Auth-Required" Version (No Guest, Free + Paid Only)

This doc describes the best way to produce a variant of the app where **everyone must have an account** (free or paid)—no guest/localStorage-only mode.

## Recommended approach: single codebase + feature flag

Use one codebase and a **runtime or build-time flag** (e.g. `BLUEPRINT_REQUIRE_AUTH`). When the flag is true:

- Unauthenticated users see an **auth gate** (Sign in / Create free account) and cannot use the app.
- The "guest" path is never used: no "Continue as guest", no localStorage-only mode.
- Free and paid plans behave as they do today; only the guest option is removed.

**Why this over a fork or separate branch**

- One codebase to maintain and one place to fix bugs.
- Same deployment pipeline; you can build two outputs (e.g. `index.html` for "with guest" and `index-auth-required.html` or a different subdomain with different config).
- Easy to roll out or A/B test by toggling the flag per deploy or URL.

---

## 1. Add the flag

**Option A – Runtime (config or query param)**  
Set the flag when the app loads, before `app-init` runs.

In `index.html` (or in the same place you set `window.BLUEPRINT_SUPABASE`), add:

```html
<script>
  window.BLUEPRINT_REQUIRE_AUTH = true;  // set to true for the "no guest" build
</script>
```

**Option B – Build-time**  
If you use a bundler or build step, define a global (e.g. `BLUEPRINT_REQUIRE_AUTH`) so that the "auth-required" build has it set to `true` and the default build to `false`.

**Option C – Per-deploy**  
Serve a small `config.json` or set the flag from environment (e.g. in a server-rendered snippet) so the same codebase can be "guest allowed" on one URL and "auth required" on another.

Then in **core.js** (or early in app-init), ensure the app reads it:

```js
Blueprint.requireAuth = !!(window.BLUEPRINT_REQUIRE_AUTH || Blueprint.requireAuth);
```

Use `Blueprint.requireAuth` everywhere you need to branch on "auth-required mode".

---

## 2. Auth gate UI

Add a single block that is shown when `requireAuth && !session` and hides the main app.

**In `index.html`** (e.g. right after the auth header, before `<main>`):

```html
<div id="auth-required-gate" class="auth-gate" hidden>
  <div class="auth-gate-card">
    <h1>Sign in or create a free account</h1>
    <p class="muted">Use Blueprint with a free or paid account. No guest mode.</p>
    <div class="auth-gate-actions">
      <button type="button" class="code-btn" id="auth-gate-signin">Sign in</button>
      <button type="button" class="code-btn download-btn" id="auth-gate-signup">Create free account</button>
    </div>
  </div>
</div>
```

Style `.auth-gate` so it covers or replaces the main content (e.g. full-width card or centered overlay). When the gate is visible, hide `<main class="main-content">` (e.g. via a class or `hidden`).

---

## 3. Session handling when `requireAuth` is true

**In `app-init.js`, inside `setAuthUI(session)`:**

- **When `session` exists**  
  Keep current behavior: set `useSupabaseData = true`, show signed-in UI, load app as today.

- **When `session` is null/undefined and `Blueprint.requireAuth` is true**  
  - Do **not** set `useSupabaseData = false` and do **not** show the guest UI.
  - Hide the main content (e.g. `document.querySelector('.main-content').hidden = true` or add a class).
  - Show the auth gate: `document.getElementById('auth-required-gate').hidden = false`.
  - Hide the normal auth header "guest" section; optionally show a minimal header with only "Sign in" / "Sign up" (or reuse the same buttons that open the auth modal).

- **When `session` is null and `requireAuth` is false**  
  Keep current behavior: set `useSupabaseData = false`, show guest UI, show main content.

**3s timeout (session check doesn’t resolve):**  
If you currently call `setAuthUI(null)` after 3s so the user sees guest mode, change it so that when `requireAuth` is true you still show the auth gate (treat "no session yet" as unauthenticated and show the gate instead of guest).

---

## 4. Wire the gate buttons

In `app-init.js`, after the auth gate exists in the DOM:

- `#auth-gate-signin` → open the existing login modal (e.g. `openAuthModal('auth-login-modal')`).
- `#auth-gate-signup` → go to pricing/signup (e.g. `showSection('pricing')` and/or open signup modal) so the user can "Create free account".

---

## 5. Guest-only UI to hide or remove when `requireAuth` is true

- **Auth header**  
  When `requireAuth` is true, never show the "guest" block (e.g. `#auth-guest`). Keep it hidden so only "Sign in" / "Create account" (or the gate) are visible when not signed in.

- **Guest nudge modal**  
  Do not show the "Continue as guest" / "Create free account" nudge when `requireAuth` is true; you can hide the nudge trigger or the modal when the flag is set.

- **Hints like "Saved on this device. Sign in to sync…"**  
  Optional: hide these when `requireAuth` is true, since there is no guest mode.

---

## 6. Storage and data layer

No change to storage or Supabase logic is required. When `requireAuth` is true you never run the app in guest mode: you either have a session (and use Supabase as today) or you show the gate and do not load main app content. So `useSupabaseData` is only ever set to `true` (when signed in) in the auth-required variant.

---

## 7. Deploying the B version

- **Same repo, two deploy targets**  
  - Build A: `BLUEPRINT_REQUIRE_AUTH` false or unset → current app (guest allowed).  
  - Build B: `BLUEPRINT_REQUIRE_AUTH` true → auth-required app (no guest).  
  Deploy to two URLs (e.g. `app.example.com` and `dashboard.example.com`) or two paths.

- **Single deploy, config-driven**  
  Set `BLUEPRINT_REQUIRE_AUTH` from your server or config (e.g. by subdomain or query param) so one build can serve both behaviors.

---

## Summary checklist

| Step | Action |
|------|--------|
| 1 | Add `window.BLUEPRINT_REQUIRE_AUTH` (and/or `Blueprint.requireAuth`) and set it in core/early init. |
| 2 | Add the auth gate HTML and styles; hide main content when gate is shown. |
| 3 | In `setAuthUI` when `!session && requireAuth`: show gate, hide main content, do not set guest state. |
| 4 | On 3s timeout with no session and `requireAuth`: show gate instead of guest. |
| 5 | Wire gate buttons to Sign in and Create free account. |
| 6 | When `requireAuth`, keep `#auth-guest` hidden and optionally disable guest nudge. |
| 7 | Use the flag in your build or deploy to produce the "no guest, free + paid only" version. |

This gives you a single codebase with a clear "B version" that has no guest, only free account and paid options.
