## Conversation Overview A single user message. The user pasted a large, partially garbled/mangled unified diff of changes to a **Next.js self‑hosted board/to‑do web app** and asked the assistant to *"Generate a concise and descriptive git commit message for the selected code changes. The message should summarize the changes made, their purpose, and any relevant context. Do not edit any files, just provide the commit message as output."* No assistant reply has been produced yet. ## Subject of the Diff (what the changes do) The diff introduces two related **AI features** plus shared AI plumbing: 1. **Per‑group "Status Update" feature** - New `components/board/status-update-dialog.tsx` — a dialog that generates a group status update, supports a follow‑up chat list (`ChatMessageList`, `MarkdownPreview`), copy‑to‑clipboard, and calls `converseAboutGroupStatus(group.id, next)`. - `components/board/group-card.tsx` (modified) — imports `ClipboardList` + `StatusUpdateDialog`, adds `statusUpdateOpen` state, and a **"Status Update"** dropdown item gated on `aiConfigured`. - New `lib/actions/group-status-ai.ts` (`"use server"`) — backing server action(s) incl. `converseAboutGroupStatus`. 2. **"Global Chat" feature** - New `lib/actions/global-chat.ts` (`"use server"`) — `sendChatMessage(messages: ChatMessage[])`: free‑form Q&A across every board the user owns (Home + all Projects). Re‑fetches/re‑serializes context each turn; uses `requireUserId()`, `getAllGroupsForUser()`, `formatAllGroupsForPrompt()`, and a shared `callChatCompletion` helper. Includes a `SYSTEM_PROMPT_HEADER` instructing the model to answer only from provided context. 3. **Shared AI context/formatting layer** - New `lib/ai/context.ts` (`server-only`) — `formatAllGroupsForPrompt`, truncation with hard caps: `NOTE_CHAR_CAP=4,000`, `DETAILS_CHAR_CAP=300`, `TOTAL_CHAR_CAP=60,000`. Comment notes single‑user scale (no RAG; whole dataset goes into the prompt, capped by these limits). - New `types/ai.ts` — `AiGroupContext` interface (group + scope label + category + archived flag + todos). **Deliberately includes archived groups** so historical questions are answerable. - `lib/board.ts` (modified) — new `getAllGroupsForUser(userId)` using one Prisma query with `categoryAccessFilter`, flattening all categories/groups/todos (unlike `getBoard`, it does **not** filter archived groups). ## Key Technical Details - Stack: Next.js, React, Tailwind, shadcn‑style UI (Dialog/Button), `MarkdownPreview`/`ChatMessageList`. - `"use server"` server actions; `"server-only"` context module; Prisma ORM; `requireUserId()` auth; `categoryAccessFilter` access control. - A shared `callChatCompletion` helper is referenced (handles provider errors, 401/403 API‑key rejection, empty/invalid JSON responses) — its full definition is not cleanly visible in the pasted diff. - The pasted diff/file contents contain visible corruption (broken lines, garbled characters), but the feature intent is clearly discernible. ## User Request (deliverable) Produce **only** a concise, descriptive git commit message (no file edits). The expected message should summarize: adding per‑group AI "Status Update" + a global cross‑board "Chat", along with shared AI context formatting (`lib/ai/context.ts`, `types/ai.ts`, `getAllGroupsForUser`) and new server actions (`global-chat.ts`, `group-status-ai.ts`). A representative phrasing would be something like: *"Add AI status updates per group and a global chat across all boards, backed by shared AI context formatting."* ## Current State / Next Steps - No assistant response exists yet. - Next step is to emit the commit message as plain text output (no code/file changes). |
||
|---|---|---|
| .agents/skills | ||
| .claude/skills | ||
| .windsurf/skills | ||
| app | ||
| components | ||
| hooks | ||
| lib | ||
| prisma | ||
| public | ||
| types | ||
| .dockerignore | ||
| .env.example | ||
| .gitattributes | ||
| .gitignore | ||
| AGENTS.md | ||
| CLAUDE.md | ||
| Dockerfile | ||
| README.md | ||
| auth.ts | ||
| components.json | ||
| docker-compose.yml | ||
| docker-entrypoint.sh | ||
| eslint.config.mjs | ||
| next.config.ts | ||
| package-lock.json | ||
| package.json | ||
| postcss.config.mjs | ||
| prisma.config.ts | ||
| proxy.ts | ||
| skills-lock.json | ||
| software.md | ||
| tsconfig.json | ||
README.md
Organize
A self-hosted, installable PWA for staying organized: an extended to-do list and notes organizer laid out as a Kanban-style board.
- Categories are the board's lanes (e.g. "To Do", "In Progress", "Done").
- Groups are the cards within a lane — each has a color, a markdown notes panel, and a to-do list, and can be dragged between lanes.
- To-Dos live inside a Group, with an optional details field.
Accounts are required (there's no anonymous/local-only mode — the board needs a database to persist to), and the first account ever created on a given instance automatically becomes its administrator.
Features
- Kanban board with drag-and-drop: reorder Categories, and drag Groups between/within Categories
- Per-Group markdown notes and a to-do list with a completion progress indicator
- Light/dark theme (follows system by default)
- Installable PWA (add-to-home-screen); requires a live connection to the server for its database, so there's no offline mode
- Credentials-based accounts (email + password), with an Admin page to:
- change a user's role (Administrator / User / Pending), email, or password, or delete their account
- control how the site handles new sign-ups (see Sign-up modes below)
Tech stack
Next.js 16 (App Router) · React 19 · TypeScript · Tailwind CSS 4 · PostgreSQL via Prisma 7 · Auth.js v5 (Credentials provider, JWT sessions) · dnd-kit · base-ui
Quick start (Docker)
This is the recommended way to run Organize. All you need is Docker with the Compose plugin.
-
Clone the repo
git clone https://git.brianfertig.com/brianfertig/Organize.git cd Organize -
Create your
.envcp .env.example .envThen open
.envand:- Generate a real
AUTH_SECRET(used to sign session cookies) — for example withopenssl rand -base64 32— and paste it in. - Optionally change
POSTGRES_PASSWORDfrom the placeholder.
See Configuration below for what each variable does.
- Generate a real
-
Start everything
docker compose up -dThis builds the app image, starts Postgres, waits for it to be healthy, then starts the app — which applies any pending database migrations automatically on every boot before serving traffic. No separate migration or setup step is needed.
-
Open the app at http://localhost:3000 (or whatever
APP_PORTyou set) and sign up. The very first account created becomes the site's administrator; everyone after that follows whatever sign-up mode is currently set (Open, by default).
Updating
git pull
docker compose up -d --build
--build matters here: without it, Compose will keep running whatever
image it already built and won't notice that the source changed.
Stopping
docker compose down
Postgres's data lives in ./data/postgres on the host (a bind mount, not
a Docker volume), so it survives docker compose down — back up that
directory if you want a safety net before major upgrades.
Configuration
All configuration is via environment variables, read from .env by
Docker Compose (see .env.example for the template).
| Variable | Used by | Purpose |
|---|---|---|
AUTH_SECRET |
app |
Encrypts/signs session cookies. Required in production — generate with openssl rand -base64 32. |
POSTGRES_USER |
db |
Postgres superuser created on first init. |
POSTGRES_PASSWORD |
db |
Password for POSTGRES_USER. Change this from the .env.example placeholder. |
POSTGRES_DB |
db |
Database name created on first init. |
APP_PORT |
app (host mapping only) |
Host port the app is published on, e.g. 3000 for http://localhost:3000. Defaults to 3000 if unset. The container always listens on 3000 internally regardless of this value. |
DATABASE_URL |
host-side tooling only | Prisma connection string for running things like npx prisma studio from your own machine. Not used by the app container itself — see note below. |
Note on
DATABASE_URL: insidedocker-compose.yml, theappservice is given its ownDATABASE_URLthat points at thedbservice over the Compose network (db:5432), built from thePOSTGRES_*variables — it ignores theDATABASE_URLin.env. The.envvalue (pointed atlocalhost:5432) is only there for convenience if you want to run Prisma commands, or the app itself, directly on the host. Since the bundleddbservice doesn't publish port 5432 to the host by default, that only works once you either add aports: ["5432:5432"]mapping to thedbservice, or pointDATABASE_URLat a Postgres instance you're running yourself.
Sign-up modes
The Admin page (/admin, administrators only) has a "New sign-ups"
setting with four modes:
- Open (default) — anyone can sign up and immediately gets the
Userrole. - Approved — anyone can sign up, but starts as
Pendingand can't log in until an administrator changes their role toUserorAdministrator. - Confirmed — not implemented yet (shown disabled in the UI); intended to gate new accounts on email confirmation instead of manual approval.
- Closed — sign-ups are turned off entirely: the sign-up form and any links to it are removed, and the sign-up action itself refuses new accounts even if called directly.
The very first account on a fresh instance always becomes an administrator, regardless of the current sign-up mode — otherwise there'd be no one able to approve anyone.
Local development (without Docker)
Running the app directly on your host is mainly useful for editing code with hot reload. You'll still need a Postgres instance it can reach.
- Node 24 (matching the Docker image; no
enginesfield enforces this, but it's what's tested) andnpm install. - A reachable Postgres. The simplest option is to add a port mapping
to the
dbservice indocker-compose.yml(ports: ["5432:5432"]) and run just that service:docker compose up -d db. Then setDATABASE_URLin.envto match (the.env.exampledefault ofpostgresql://organize:organize@localhost:5432/organizewill work as-is if you keep the default Postgres credentials). - Apply migrations:
Against a fresh database this also runsnpx prisma migrate devprisma/seed.tsautomatically, creatingdev@example.com/password123as an administrator with a small sample board. If it doesn't (e.g. you'd already applied every migration before), runnpx prisma db seedto trigger it explicitly. Don't run either against a database you care about. - Run the dev server:
Open http://localhost:3000.npm run dev
Other useful scripts: npm run build (production build), npm run start
(serve a production build), npm run lint.
Project structure
app/ Next.js App Router routes: (app) is the signed-in board + admin,
(auth) is login/signup
components/board/ The Kanban board: categories, groups, to-dos, drag-and-drop
components/admin/ Admin page: user table, role menu, sign-up mode settings
lib/actions/ Server Actions (auth, categories, groups, todos, notes, admin)
lib/ Shared server helpers (db client, auth helpers, settings, colors)
prisma/ Schema, migrations, and the dev-only seed script
auth.ts Auth.js configuration (Credentials provider, JWT session callbacks)
proxy.ts Route protection (redirects signed-out users to /login, etc.)