Docs
KEd Studio
Applications
KEd Studio
Overview
IntroductionArchitectureDevelopment setup
KEd JSON contractKEd language assistDesktop integration planCloud books auth planBook editor data integration
Platform integration
HomeBrowse applications

© 2026 Wekify LLC · Kifuliiru Lab

Homellms.txtkifuliiru.com

GuidesCloud books auth plan

Cloud books auth plan

Authentication plan for cloud-hosted books.

Plan for saving .ked.json books in the database so hosted-web users do not lose work on refresh or a closed tab.

Related: KED_JSON_CONTRACT.md · NEXT_STEPS.md · DESKTOP_INTEGRATION_PLAN.md

Status: Planning only — not implemented yet.


Problem

| Today | Gap | |-------|-----| | Book lives in memory while editing | Refresh / closed tab → lost | | Save book… downloads .ked.json | Easy to forget; not cross-device | | Desktop / local can keep files on disk | Hosted web has no durable store | | Supabase project + env keys + installer buckets | No books table yet; Auth not wired in Studio UI |

Goal: Signed-in users get cloud-backed books (create, autosave, reopen) while .ked.json download and desktop export stay available.

Auth is required for this feature. Anonymous cloud rows without accounts are fragile (device loss, shared computers, no ownership) and are out of scope for v1.


Principles

  1. .ked.json remains the source of truth for content — the DB stores the same payload buildSavedPackagePayload() already builds (package + book_settings + pages).
  2. Auth before cloud save — no signed-in user → keep download-only save; prompt to sign in for cloud.
  3. Download is never removed — backup, offline, desktop/DOCX handoff, generators workflow.
  4. Desktop stays file-first — local files and Puppeteer export; optional later: “Open from cloud” when signed in.
  5. Reuse the existing Supabase project — URL/keys and installer storage are already wired; add Auth + a books table in that same project (no second vendor for v1).

Recommended stack

Supabase is already configured in this repo (same project as desktop installers):

| Already in place | Notes | |------------------|--------| | NEXT_PUBLIC_SUPABASE_URL | Project URL (.env / deploy env) | | NEXT_PUBLIC_SUPABASE_ANON_KEY | Public anon key | | SUPABASE_SERVICE_ROLE_KEY | Server-only (installer uploads today — never expose to the browser) | | lib/supabase/storage.ts | Installer bucket helpers | | @supabase/supabase-js | Available for books + Auth clients |

Cloud books reuse this project. Do not create a second Supabase project for v1.

| Still to add | Choice | Why | |--------------|--------|-----| | Auth | Supabase Auth on the existing project | RLS ties books to auth.uid() | | DB | books table + RLS | JSONB for full .ked.json | | App clients | lib/supabase/client.ts (+ server helper if needed) | Browser session for Auth/CRUD; service role stays off the client |

Why auth cannot be skipped

  • Row Level Security: user_id = auth.uid() so users only see their books.
  • Cross-device restore needs a stable identity.
  • Future sharing / lab review needs ownership.

Data model (v1)

Code
-- Enable Auth in Supabase dashboard (email magic link and/or OAuth).

create table public.books (
 id uuid primary key default gen_random_uuid(),
 user_id uuid not null references auth.users (id) on delete cascade,
 title text not null default '',
 book_type text,
 ked_json jsonb not null,
 created_at timestamptz not null default now(),
 updated_at timestamptz not null default now()
);

create index books_user_updated_idx
 on public.books (user_id, updated_at desc);

alter table public.books enable row level security;

create policy "Users read own books"
 on public.books for select
 using (auth.uid() = user_id);

create policy "Users insert own books"
 on public.books for insert
 with check (auth.uid() = user_id);

create policy "Users update own books"
 on public.books for update
 using (auth.uid() = user_id);

create policy "Users delete own books"
 on public.books for delete
 using (auth.uid() = user_id);
```text

### What goes in `ked_json`

Exactly the object produced by `buildSavedPackagePayload()` today:

- Package fields (`title`, `rows`, `columns`, `book_type`, …)
- `book_settings`
- `pages` (saved HTML for WYSIWYG reopen)
- `template` / `book_design_template_id` when present

Denormalize `title` and `book_type` columns for list UI without parsing JSONB every time; keep them in sync on save.

### Size notes

- Packages with many rows + page HTML can be large. Set a soft limit early (e.g. warn above ~2–5 MB; hard reject above a configured max).
- Do not put Puppeteer PDFs in the row; export remains on demand.

---

## Product UX (v1)

### Auth

- Sign in / sign out in the toolbar or a small account menu (hosted web first).
- Providers for v1: **email magic link**; add Google/GitHub later if needed.
- Signed-out: current behavior (import, edit, download, print PDF, cover PNG).

### Books

| Action | Behavior | |--------|----------| | **My books** | List cloud books (title, type, updated); open loads `ked_json` via existing `loadPackage` | | **Save to cloud** | Upsert current book; create `id` on first save | | **Autosave** | Debounced (e.g. 2–5s after edits) when signed in and book has a cloud `id` | | **Save book…** (download) | Unchanged `.ked.json` file download | | **Delete** | Confirm, then delete row |

### Session restore (nice-to-have in v1.1)

- Remember last opened `book_id` in `localStorage` → reopen after refresh when still signed in.

### Desktop

- v1: no change required (file download / import).
- Later: “Sign in” + “Open from cloud” if we want one account across web and desktop.

---

## Runtime split (align with export)

| Runtime | Cloud books | |---------|-------------| | **Hosted web** | Primary target — auth + DB | | **Local web** | Same code path if env has Supabase keys (useful for testing) | | **Desktop** | Optional later; file save remains default |

---

## Architecture sketch

```mermaid
sequenceDiagram
 participant User
 participant Studio as KEd Studio (web)
 participant Auth as Supabase Auth
 participant DB as Postgres books

 User->>Studio: Edit book
 Studio->>Studio: buildSavedPackagePayload()
 alt Signed in + cloud book id
 Studio->>DB: Upsert ked_json (RLS)
 else Signed out
 Studio->>User: Download .ked.json only
 end
 User->>Studio: My books → Open
 Studio->>Auth: Session
 Studio->>DB: Select own rows
 Studio->>Studio: loadPackage(ked_json)
```text

### App modules (suggested)

| Path | Role | |------|------| | `lib/supabase/client.ts` | Browser Supabase client | | `lib/supabase/server.ts` | Server client if Route Handlers needed | | `lib/books/api.ts` | list / get / upsert / delete | | `hooks/useAuth.ts` | Session, sign-in, sign-out | | `hooks/useCloudBook.ts` | Current `bookId`, autosave, dirty state | | `components/AccountMenu.tsx` | Sign in / out | | `components/MyBooksDialog.tsx` | List + open + delete |

Keep persistence logic out of `useKedStudio` where possible: call `buildSavedPackagePayload` / `loadPackage` from a thin cloud hook.

---

## Implementation phases

### Phase A — Auth shell

- [ ] Enable Supabase Auth on the **existing** project (magic link); add redirect URLs for local + production.
- [ ] Browser client (`lib/supabase/client.ts`) using existing `NEXT_PUBLIC_*` keys.
- [ ] Account menu: sign in / sign out / email shown.
- [ ] Guard: cloud APIs no-op or prompt when signed out.
- [ ] Keep `SUPABASE_SERVICE_ROLE_KEY` server-only (installers); never use it for user book CRUD in the browser.

### Phase B — Schema + CRUD

- [ ] Migration for `books` + RLS (as above).
- [ ] `listBooks` / `getBook` / `upsertBook` / `deleteBook`.
- [ ] Wire **Save to cloud** and **My books** to load via `loadPackage`.
- [ ] Sync `title` / `book_type` columns from payload on write.

### Phase C — Autosave + UX polish

- [ ] Debounced autosave when `bookId` is set.
- [ ] Status line: “Saved” / “Saving…” / “Save failed”.
- [ ] Conflict policy v1: last write wins (document; no OT).
- [ ] Payload size warning / max.

### Phase D — Hardening (after v1)

- [ ] Optional book sharing / lab role (separate policies).
- [ ] Desktop “Open from cloud”.
- [ ] Soft delete / trash.
- [ ] Version history (new `book_revisions` table) if needed.

---

## Security checklist

- [ ] RLS on for all book policies; no service-role key in the browser.
- [ ] Validate `ked_json` shape server-side or via constrained client upsert (at least `title` string + object).
- [ ] Auth redirect allowlist: production host + `localhost`.
- [ ] Rate-limit abuse via Supabase / edge if needed later.

---

## Explicit non-goals (v1)

- Real-time multiplayer editing.
- Replacing `.ked.json` file handoff with generators.
- Storing exported PDF/DOCX blobs in the DB.
- Anonymous / passwordless-without-email cloud books.

---

## Success criteria

- Signed-in user edits a book on hosted web, refreshes, and the book reopens from **My books** (or last-session restore) with pages and cover intact.
- Signed-out user can still download `.ked.json` and is never blocked from editing.
- A user cannot read or mutate another user’s `books` rows (RLS verified).
- Download + desktop DOCX handoff still work unchanged.

---

## Open decisions

| Topic | Options | Lean | |-------|---------|------| | Auth providers | Magic link only vs + OAuth | Magic link first | | New book default | Always create cloud row vs “Save to cloud” explicit | Explicit first save, then autosave | | Local draft before sign-in | Discard vs stash in `localStorage` then upload | Stash one draft on sign-in (v1.1) | | Desktop sync | Skip vs same Auth | Skip in v1 |
PreviousDesktop integration planNextBook editor data integration

On this page

  • Problem
  • Principles
  • Recommended stack
  • Why auth cannot be skipped
  • Data model (v1)