Changelog
5 entries · showing 5 after filters
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 ---
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`.
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
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
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.