# 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](#sign-up-modes) below) - **Profile page** (`/profile`): set a first/last name and a profile photo, shown in the menu on the left (the photo replaces the initial-letter avatar when set) ## 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. 1. **Clone the repo** ```bash git clone https://git.brianfertig.com/brianfertig/Organize.git cd Organize ``` 2. **Create your `.env`** ```bash cp .env.example .env ``` Then open `.env` and: - Generate a real `AUTH_SECRET` (used to sign session cookies) — for example with `openssl rand -base64 32` — and paste it in. - Optionally change `POSTGRES_PASSWORD` from the placeholder. See [Configuration](#configuration) below for what each variable does. 3. **Start everything** ```bash docker compose up -d ``` This 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. 4. **Open the app** at [http://localhost:3000](http://localhost:3000) (or whatever `APP_PORT` you set) and sign up. The very first account created becomes the site's administrator; everyone after that follows whatever [sign-up mode](#sign-up-modes) is currently set (Open, by default). ### Updating ```bash 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 ```bash 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`:** inside `docker-compose.yml`, the `app` > service is given its own `DATABASE_URL` that points at the `db` service > over the Compose network (`db:5432`), built from the `POSTGRES_*` > variables — it ignores the `DATABASE_URL` in `.env`. The `.env` value > (pointed at `localhost:5432`) is only there for convenience if you want > to run Prisma commands, or the app itself, directly on the host. Since > the bundled `db` service doesn't publish port 5432 to the host by > default, that only works once you either add a `ports: ["5432:5432"]` > mapping to the `db` service, or point `DATABASE_URL` at 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 `User` role. - **Approved** — anyone can sign up, but starts as `Pending` and can't log in until an administrator changes their role to `User` or `Administrator`. - **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. 1. **Node 24** (matching the Docker image; no `engines` field enforces this, but it's what's tested) and `npm install`. 2. **A reachable Postgres.** The simplest option is to add a port mapping to the `db` service in `docker-compose.yml` (`ports: ["5432:5432"]`) and run just that service: `docker compose up -d db`. Then set `DATABASE_URL` in `.env` to match (the `.env.example` default of `postgresql://organize:organize@localhost:5432/organize` will work as-is if you keep the default Postgres credentials). 3. **Apply migrations:** ```bash npx prisma migrate dev ``` Against a fresh database this also runs `prisma/seed.ts` automatically, creating `dev@example.com` / `password123` as an administrator with a small sample board. If it doesn't (e.g. you'd already applied every migration before), run `npx prisma db seed` to trigger it explicitly. Don't run either against a database you care about. 4. **Run the dev server:** ```bash npm run dev ``` Open [http://localhost:3000](http://localhost:3000). 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.) ```