- New `/profile` page lets users set first/last name and upload a
profile photo (resized to 256x256 JPEG server-side via sharp, stored
as a data URL in Postgres since the container FS is ephemeral)
- Sidebar user block now shows the profile photo (or initial-letter
fallback) and display name, and links to `/profile`
- Migration adds `firstName`, `lastName`, `avatar` columns to User and
backfills them from the legacy `name` field; seed updated to match
- Bump Next.js server-action body limit to 11 MB so avatar uploads up
to the 10 MB cap aren't silently rejected with a 413
- Expose Postgres port on the host in docker-compose for local tooling
- Extract theme constants (THEMES, THEME_CLASSES, DARK_SURFACES) into a new
framework-free lib/themes.ts so server and client code share one source of
truth; re-export from theme-provider for backward compatibility.
- Add nullable `theme` column to Project (Prisma migration + schema), plus
ProjectThemeSchema validation and a setProjectTheme server action.
- Introduce a ThemeScope context in the provider: a subtree can temporarily
override the global preference via useThemeScope().setScope(name); the
scoped theme wins for resolvedTheme/DOM while active, then lifts on cleanup.
- Render an inline no-FOUC script (themeSwitchScript) on project pages that
applies the theme class before first paint and leaves a data-project-theme
marker the provider reads at hydration.
- Add ProjectThemeScope component that sets/clears the scope from live
ProjectsContext state, so picking a new theme updates instantly without
waiting for the server re-render.
- Add ProjectThemePicker dropdown (Default + light/dark options) rendered
beside the project title in the kanban board header.
- Wire optimistic setProjectTheme into ProjectsContext with rollback and
error toast on failure.
- Update use-dark-theme hooks to read resolvedTheme from context instead of
resolving locally, so they reflect scoped themes correctly.
- Scheduled to-dos: new ScheduledTodo + ScheduledTodoCompletion models
(owner-XOR-project ownership like Category, per-occurrence completion
so a recurring to-do tracks done state per calendar date), recurrence
built server-side from validated parts via rrule-utils, CRUD +
occurrence-toggle server actions, add/edit dialog, and a collapsible
Scheduled side panel (overdue / today / upcoming) with UTC-safe
date-key formatting.
- AI to-dos: group-level AI dialog (lib/actions/todo-ai.ts) that chats
then proposes a finalize list of to-dos; editable proposals and bulk
add via BoardProvider.addTodos; speech recognition gains better error
handling (network/firewall message, error logging).
- Building upgrades: new `upgradesFrom` rule — Nuclear Power Plant can
replace a friendly Energy Generator and Advanced Metal Generator a
Mass Generator (same tile + footprint, per TALogic.findUpgradeTarget),
crediting a 50% refund of the replaced building's OWN cost;
compileRules validates the references, topperFrame gets a generic
spinning-glyph fallback in TAArt.
- Movement rework: pushOutOfObstacles replaces the hard tile-snap with a
damped circle-vs-tile overlap push, and pathfinding routes at exact-fit
clearance instead of +1 padding (fixes corner grinding/stalling).
- New map m06 "Annihilation" (medium, snowfields, Klaxon skill 5, seed
90123 — pre-vetted for early-economy balance).
- Tests: upgrade placement (ownership, type match, exact footprint,
refund, army-less fallback), obstacle routing/settling, corridor
moves; sprites.md updated for upgradesFrom and toppers.
- Add `AiSettingsCard` component and server actions for configuring an
OpenAI-compatible AI endpoint (e.g. OpenWebUI) from the admin panel
- Introduce `AiSettings` Prisma model with masked API key display and
connection testing UI
- Track `completedAt` on todos with a migration and backfill for existing
completed items
- Surface `createdAt`, `updatedAt`, and `completedAt` in the todo edit
dialog via a new `formatDateTime` utility
- Update `TodoDTO`, `getBoard`, `createTodo`, `toggleTodo`, and the board
context to carry and optimistically update timestamp fields
- Add `Select` UI component built on `@base-ui/react`
- Add Project model with owner-based access and cascade delete
- Restructure Category to belong to either Home (userId) or a Project (projectId), enforced by DB constraints and access filters
- Scope all board operations (create, update, delete, reorder) to the correct board context using `categoryAccessFilter` and `projectAccessFilter`
- Replace hardcoded `revalidatePath("/")` with dynamic `boardPath()` for proper cache invalidation
- Add `ProjectsProvider` and `ProjectsNavSection` for project sidebar navigation
- Make KanbanBoard accept `projectId` and `title` props to render Home or Project boards
- Extract `getBoard()` utility to centralize board data fetching
- Refactor group/todo/notes actions to derive board context from category membership rather than trusting caller input