Changelog

5 entries · showing 5 after filters

  1. v0.5 — Marketplace, AI customizer, public APIs, list refactor, email infra (2026-05-08)

    lessons learned
    ### Added
    - **Marketplace** (`src/routes/marketplace.tsx`, `src/services/marketplace.ts`) — discoverable list directory with the "marketplace" flag promoted to a first-class list attribute. Existing lists can be marked as marketplace entries (e.g. the "Hawaii Trip" demo).
    - **AI list customizer** (`src/components/AiListCustomizer.tsx`, `src/services/list-ai.ts`, edge function `supabase/functions/customize-list`) — Lovable AI–backed flow that personalizes a marketplace list to the visitor's intent, with optional **voice dictation** (`src/hooks/use-voice-dictation.ts`) for hands-free input. Tests in `src/routes/-marketplace-ai.test.ts`.
    - **Fork-as-draft intent** (`src/routes/-fork-draft-intent.test.ts`, `src/components/ShareModeToggle.tsx`, `src/lib/share-origin.ts`) — visitors can fork a marketplace list into a draft of their own, with share-origin attribution preserved.
    - **Public read-only APIs** under `/api/public/`:
      - `share.$slug.ts` — canonical share JSON for a list.
      - `lists.$slug.ts` — public list payload for external consumers.
    - **Due dates on list items** (`src/components/DueDatePicker.tsx`, `src/lib/due-date.ts` + tests) — per-item due date with formatting helpers.
    - **List view refactor** — extracted `src/routes/l.$slug.tsx` into focused pieces: `ListHeaderBar`, `ListMetaCard`, `SortableListItem`, `TrashSection` (under `src/components/list/`), `useListData` hook, and supporting libs (`src/lib/attribution.ts`, `src/lib/list-export.ts`, `src/types/list.ts`). Service layer at `src/services/lists.ts` + `lists.test.ts`.
    - **Admin SEO page** (`src/routes/admin.seo.tsx`) for editing per-page metadata.
    - **CMS surface** introduced (`src/services/cms-config.ts`, `src/hooks/useCmsConfig.ts`, `src/components/AdminRoute.tsx`) — `app_config`-backed admin-only writes with public reads. Used by Footer, SEO, and the new HTML editor flow.
    - **Changelog viewer** (`src/routes/changelog.tsx`) — paginated viewer (1,000 per page) with text search and `#lessonslearned` filter, parsed from this file. Linked from the site footer next to **System Status**.
    - **Email infrastructure** for `notify.stratalist.net` — Lovable Emails domain provisioned, queue/cron/Vault deployed, queue worker at `src/routes/lovable/email/queue/process.ts`, migration `20260508175341_email_infra.sql`. Wires up future collaborator-invite and notification emails.
    - **Ask-Self docs** (`ASK_SELF.md`) — local-agent retrieval protocol per AGENTS.md §0.7.
    
    ### Changed
    - "Your lists" → **"My lists"** in the dashboard header.
    - List rows on the dashboard now open the list view on row click (not just on the title link).
    - Spacing tightened on the AI customizer box.
    - `toastError` call sites adjusted for the normalized `AppError` contract.
    - Refactored admin config hooks to use the new `useCmsConfig` pattern.
    
    ### #lessonslearned
    - 2026-05-08: [§3] Stratalist now has an editable CMS surface (`app_config` for footer, SEO, and admin-managed copy) — the v0.1 "no CMS, mark §3 N/A" decision is reversed. -> Outcome: §3 is now in scope; all reads must go through `useCmsConfig` and writes through the admin-only service. -> Next action: update DASHBOARD snapshot and audit any direct `app_config` reads outside the service. #lessonslearned
    - 2026-05-08: [§2.2 / §15] The list view (`l.$slug.tsx`) had grown into a single 1k+ line route mixing data, UI, drag-drop, export, and trash UI. Splitting into `useListData` + `src/components/list/*` + `src/lib/list-*` made the next round of features (due dates, share mode, fork-as-draft) tractable without touching the route shell. -> Next action: apply the same shape pre-emptively on any new route that crosses ~400 lines. #lessonslearned
    
    ---
  2. v0.4 — CI + architectural regression tests (2026-05-03)

    ### Added
    - **`.github/workflows/ci.yml`** — runs on push + PR to `main`. Stages: install (Bun, frozen lockfile) → architecture check → typecheck → lint → test → production build. The build stage is the one that exercises Vite's `import-protection` rollup hook, which catches client/server boundary breaks the dev server misses.
    - **`scripts/check-architecture.mjs`** — fast static checker for the AGENTS.md §2.2 boundary contract: no `.functions.ts` inside `src/server/`, no top-level `.server` value imports from wrappers, `client.server` quarantined to `src/server/**`, `@tanstack/react-start/server` quarantined to `src/server/**` or `src/routes/api/**`, routes/components must import RPC wrappers from `@/server-fns/*`. Wired up as `bun run check:architecture`.
    - **`bun run typecheck`** (`tsc --noEmit`) and **`bun run verify`** (full local gate) added to `package.json`.
  3. v0.3 — Server-function boundary fix (2026-05-03)

    lessons learned
    ### Changed
    - **Server-function folder split.** Moved all `createServerFn` RPC wrappers out of `src/server/` and into `src/server-fns/`. The Lovable Vite preset's `import-protection` plugin denies the entire `**/server/**` folder in the client environment, so even thin wrappers there caused `Import denied in client environment` build failures when imported by routes. The new layout is: `src/server-fns/*.functions.ts` (client-importable RPC), `src/server/*.server.ts` (implementation, server-only), `src/server/*.types.ts` (shared types).
    - Wrappers now dynamically import their `.server.ts` sibling inside `.handler()` and use `import type` for shared types from `*.types.ts`.
    - Documented the convention + future debugging steps in AGENTS.md §2.2 (new section). ARCHITECTURE.md and the ESLint config were updated to match.
    
    ### #lessonslearned
    - 2026-05-03: [§2.2] The original split (`*.server.ts` + `*.functions.ts` both inside `src/server/`) looked correct against the generic `tss-serverfn-split` guidance but failed against the Lovable preset's folder-scoped import-protection. -> Outcome: every new build attempt surfaced a different file because each fix was symptom-local. -> Next action: when a build error names a *folder* pattern (`**/server/**`), do not patch the named file — restructure so client-reachable code never resolves through that folder. #lessonslearned
  4. v0.2 — Lovable dev login + AGENTS realignment (2026-05-03)

    lessons learned
    ### Added
    - **Lovable dev login**: passwordless one-click sign-in on `/login` when running on `*.lovable.app`, `*.lovable.dev`, or `localhost`. Implemented as `src/server/dev-login.functions.ts` (`devLogin`) which provisions / rotates the password for a fixed `dev@lovable.local` user and returns one-time credentials to the browser. The host check runs both server-side (via `getRequestHost()`) and client-side (button visibility).
    - **AGENTS.md v2.0**: rewritten to match the actual Stratalist architecture — TanStack Start file-based routing under `src/routes/`, React Context auth (`useAuth()`), no Zustand, no CMS / `app_config`. Added §2.1 Lovable Dev Login Contract, corrected §10 RLS rules to reference `lists` / `list_items` / `has_role()` / `list_owner()` / `list_is_open()`, and updated §12 Key Paths.
    
    ### #lessonslearned
    - 2026-05-03: [§2.1] Dev login origin allow-list MUST be hard-coded and validated server-side — relying on a client check alone would let any caller mint a session for the dev user. -> Outcome: `getRequestHost()` enforced inside `devLogin()`. -> Next action: add a CRUD test that asserts the function returns 403 for non-Lovable hosts. #lessonslearned
  5. v0.1 — Initial build (2026-05-03)

    lessons learned
    ### Added
    - Auth: email + password signup with native Supabase OTP verification, login, forgot-password, reset-password.
    - Show/hide password toggle (`PasswordInput` component) on signup and reset flows.
    - Lists: create/edit/delete with 12-char slugs, 600-char descriptions, open vs. semi-private privacy.
    - List items: 200-char text, completion checkboxes, drag-to-reorder (`@dnd-kit`), inline edit.
    - YouTube auto-embed and URL linkification in description and item text.
    - Anonymous edit attribution as `anon@<ip>` via `/api/whoami`.
    - Real-time updates via Supabase Realtime on `lists` and `list_items`.
    - Admin dashboard for slug overrides.
    - `UnifiedLayout` (`src/components/layouts/UnifiedLayout.tsx`) — single source of truth for page chrome and `max-width`.
    - `AppError` contract + `withBoundary()` async-boundary helper (`src/lib/errors.ts`) per AGENTS.md §7 baseline tier.
    - DASHBOARD.md, QUICKHELP.md, this CHANGELOG.
    
    ### Architecture decisions / `#lessonslearned`
    
    - 2026-05-03: [§12 Key Paths] AGENTS.md names `src/pages/`; Stratalist uses TanStack Start file-based routing under `src/routes/` -> renaming to `src/pages/` would break the router and require swapping frameworks -> keep `src/routes/`, document the deviation here, treat the rule as "page-level route files live under the framework's conventional folder." #lessonslearned
    - 2026-05-03: [§3, §10] AGENTS.md mandates an `app_config` CMS table + `useCmsConfig` -> Stratalist has no CMS surface -> sections marked N/A in DASHBOARD; revisit if/when editable Terms/Footer copy is introduced. #lessonslearned
    - 2026-05-03: [§4] AGENTS.md mandates `useAuthStore()` (Zustand) -> Stratalist has only one cross-page concern (auth) and uses React Context (`useAuth()`) which satisfies the spirit (single source of truth, no hardcoded IDs) -> revisit if a second shared store appears. #lessonslearned
    - 2026-05-03: [§7] `withBoundary` + `AppError` are defined but not yet retrofitted into every Supabase call site -> partial coverage acknowledged in DASHBOARD; adopt incrementally on touched files. #lessonslearned
    - 2026-05-03: [§10.5] Public SELECT on `lists` and `list_items` is **intentional** for the share-by-link product model and is not a tenant-isolation violation -> documented in DASHBOARD snapshot. #lessonslearned
    
    ### Refactor (2026-05-03)
    - Migrated all page routes (`/`, `/login`, `/signup`, `/verify-otp`, `/forgot-password`, `/reset-password`, `/dashboard`, `/admin`, `/l/$slug`) from inline `<div className="min-h-screen"><Header /><main ...>` chrome to `<UnifiedLayout width="…">`. Removed all per-page `max-w-*` from page-level wrappers.