feat: full plan execution - CI/CD, critical fixes, UX polish, secondary/advanced features, E2E + docs

Phase 0 (CI/CD): fix root typecheck to cover api+worker+web; reconcile migration
story into idempotent db:migrate (db:sync + db:triggers); add Gitea Actions
quality/deploy/smoke workflow; rewrite README/AGENTS/DEPLOY docs; add
requireWorkspaceAccess + recordActivityForEntity conventions.

Phase 1 (critical fixes): calendar delete + drag/resize DnD; canvas card CRUD +
bulk save + debounced autosave; logout route; graph edge workspaceId derivation;
real analytics endpoints (drop Math.random); task board droppable columns +
reorder persistence; Tiptap notes editor with sanitized HTML rendering; remove
insecure passkey auth; domain/owner scoping (IDOR) on all by-ID routes + search/
export/realtime scoping; command palette routing + agent mention fetch; agent
activity SSE handler; graph fly-to with tracked positions.

Phase 2 (UX polish): login on design system; Sonner toasts app-wide; shared
Loading/Empty/Error state components; working density/sidebarPos/reduce-motion
settings; Inter typography; consolidated status-colors lib; unified detail
routes; dashboard sort/realtime/responsive fixes; mobile responsive; a11y
(radiogroups, sanitized snippets, badge labels).

Phase 3 (features): daily notes timezone fix + delete + autosave + mood/energy
create; active-domain store + topbar picker; graph domain picker + navigable
entity links; tag assign/remove UI + server-side tag filter; real CSV export +
import validation; custom fields on tasks.

Phase 4 (advanced): migrate job worker into apps/worker (webhook delivery with
HMAC, recurring spawn, ai_dispatch disabled); webhook queue helper + entity
event enqueuing + test endpoint fix; recurring scheduledJobs pipeline; agents
CRUD + permission editing + activity filters; real notifications feed; MCP
polish (validation, error codes, domain scoping, dead sql leftover).

Phase 5 (E2E + docs): rewrite Playwright suite for the Vite SPA (15 specs, new
auth helpers, chromium-only in CI); add ephemeral-Postgres e2e CI job; rewrite
docs/API.md for the real Hono API.
This commit is contained in:
2026-08-10 08:53:18 +00:00
parent 6cb4b9f1b5
commit a60b75f075
99 changed files with 6238 additions and 2954 deletions
+115 -205
View File
@@ -1,274 +1,209 @@
# Project E
A personal project, habit, and task tracker built for the AI-agent era. Track tasks, build habits, manage projects, write notes, generate reports, and let AI agents work alongside you through a native MCP (Model Context Protocol) server.
A personal project, habit, and task tracker built for the AI-agent era. Track tasks and habits, manage projects, write notes, and let AI agents read and write your data through a built-in MCP (Model Context Protocol) server.
## Features
- **Tasks:** Kanban boards, priorities, due dates, subtasks, time tracking, recurring tasks, dependencies, and attachments
- **Habits:** Daily/weekly/custom frequencies, streak tracking, mood logging, skip days, and completion scoring
- **Projects:** Organize work by domain, track progress through milestones, set deadlines, and manage team members
- **Notes:** Rich text editor with wikilinks, note graph visualization, bookmarks, and AI-generated content support
- **Reports:** Weekly, monthly, project, and habit reports with templates and AI-assisted generation
- **Notes:** Rich text editor with wikilinks, note graph visualization, and bookmarks
- **Reports:** Weekly, monthly, project, and habit reports with templates
- **Milestones:** Plan project phases, set dependencies, and track completion
- **Domains & Tags:** Organize everything across life domains (work, personal, health) with flexible tagging
- **AI Agents:** Register agents with API keys, assign permission tiers, and dispatch work via @mentions
- **Webhooks:** Subscribe to events, deliver payloads with HMAC signatures, and track delivery history
- **Analytics:** Task completion rates, habit consistency, time summaries, and streak tracking
- **Realtime:** Server-sent events proxy keeps the UI in sync across devices
- **Background Worker:** Processes webhook deliveries, agent mentions, report generation, recurring tasks, and data cleanup
- **MCP Server:** 61 tools for AI agents to read and write data through the Model Context Protocol
- **Realtime:** SSE feed backed by PostgreSQL LISTEN/NOTIFY keeps the UI in sync across devices
- **Background Worker:** Bun process for webhook deliveries, agent mentions, recurring tasks, and data cleanup
- **MCP Server:** 18 tools for AI agents to read and write data through the Model Context Protocol
## Architecture
```
┌─────────────────────────────────────────────────────────────┐
│ Frontend (Next.js)
│ React 19 · App Router · shadcn/ui · Tailwind · Zustand
└──────────────────────────┬──────────────────────────────────┘
┌───────────────────────────────────────────────────────────────
│ Frontend (Vite SPA)
React 19 · TanStack Router/Query · shadcn/ui · Tailwind │
└──────────────────────────┬────────────────────────────────────
│ REST API + SSE
┌──────────────────────────▼──────────────────────────────────┐
│ API Layer (Next.js Routes) │
Auth · Validation (Zod) · Realtime SSE Proxy · MCP Server
└──────────────────────────┬──────────────────────────────────┘
│ Drizzle ORM
┌──────────────────────────▼──────────────────────────────────┐
│ Data Layer (PostgreSQL + Drizzle ORM) │
│ PostgreSQL · Drizzle migrations · NextAuth credentials
└─────────────────────────────────────────────────────────────┘
│ (Vite dev proxy → :3001)
┌──────────────────────────▼────────────────────────────────────┐
API (Hono on Bun, apps/api)
│ Auth (JWT) · Routes · Realtime SSE · MCP server · Webhooks │
└──────────────────────────┬────────────────────────────────────┘
│ Drizzle ORM (postgres driver)
┌──────────────────────────▼────────────────────────────────────┐
PostgreSQL 16 + Drizzle ORM
│ Schema in packages/db/src/schema.ts · migrations in drizzle/ │
└────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
Background Worker
│ Webhook Delivery · Agent Mentions · Report Generation
Recurring Tasks · Data Cleanup │
└─────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────
│ Background Worker (Bun, apps/worker)
Webhook delivery · Agent mentions · Recurring tasks ·
│ Data cleanup
└────────────────────────────────────────────────────────────────
```
## Tech Stack
| Layer | Technology |
|-------|-----------|
| Frontend | Next.js 15, React 19, TypeScript 5.9 |
| Frontend | Vite 5, React 19, TypeScript 5.9 |
| Routing / Data | TanStack Router, TanStack Query, TanStack Table |
| UI Components | shadcn/ui, Radix UI, Lucide icons |
| Styling | Tailwind CSS 3.4, tailwind-merge, class-variance-authority |
| State Management | Zustand 5 |
| Rich Text | Tiptap 3 |
| Forms | React Hook Form 7, Zod 4 validation |
| Forms | React Hook Form, Zod 4 validation |
| Calendar | react-big-calendar, date-fns |
| Charts | Recharts 3 |
| Graph Visualization | react-force-graph-2d |
| Drag & Drop | @dnd-kit |
| Backend | Next.js API routes (App Router) |
| Database | PostgreSQL 16 with Drizzle ORM |
| Authentication | NextAuth 4 with credentials authentication |
| Background Jobs | Node.js worker with polling and exponential backoff |
| MCP Server | @modelcontextprotocol/sdk 1.29 |
| Monorepo | Turborepo 2.5, npm workspaces |
| Testing | Jest (unit/component), Playwright 1.61 (E2E) |
| Backend | Hono 4 on Bun 1.3 (`apps/api`) |
| Database | PostgreSQL 16 with Drizzle ORM and the `postgres` driver |
| Authentication | JWT (jose) in an httpOnly session cookie; API keys for agents |
| Background Jobs | Bun worker (`apps/worker`) |
| MCP Server | JSON-RPC over HTTP at `/api/mcp`, served by the API |
| Monorepo | Turborepo 2.5, Bun workspaces |
| Testing | Playwright (E2E in `e2e/`) |
## Prerequisites
- **Node.js** 22.13.0 or later
- **npm** 10.0.0 or later
- **PostgreSQL** 16 or later
- **Bun** 1.3.14 or later (the repo pins `bun@1.3.14`)
- **PostgreSQL** 16 (local install, or the Docker container from the compose file)
- **Docker + Docker Compose** for the production stack (see [DEPLOY.md](DEPLOY.md))
## Quick Start
### Development Setup
1. **Clone the repository**
```bash
git clone <repository-url>
git clone https://git.buzzbee.dev/Vibing/ProjectE.git
cd ProjectE
```
2. **Install dependencies**
```bash
npm install
bun install
```
3. **Create the database**
3. **Start PostgreSQL**
```bash
createuser -P project_e
createdb -O project_e project_e
```
```bash
docker compose up -d db
```
Or point `DATABASE_URL` at an existing PostgreSQL 16 instance.
4. **Set environment variables**
Create a `.env.local` file in the root:
```bash
cp .env.example .env
```
```bash
DATABASE_URL=postgresql://project_e:your_postgres_password@localhost:5432/project_e
POSTGRES_PASSWORD=your_postgres_password
NEXTAUTH_SECRET=your_long_random_secret
INITIAL_ADMIN_EMAIL=admin@example.com
INITIAL_ADMIN_PASSWORD=your_initial_admin_password
```
`INITIAL_ADMIN_EMAIL` and `INITIAL_ADMIN_PASSWORD` create the first admin account when you sign in with those credentials.
Fill in `DATABASE_URL`, `POSTGRES_PASSWORD`, `AUTH_SECRET`, `INITIAL_ADMIN_EMAIL`, and `INITIAL_ADMIN_PASSWORD`.
5. **Apply the database schema**
```bash
psql "postgresql://project_e:your_postgres_password@localhost:5432/project_e" -f drizzle/0000_postgres.sql
```
6. **Start the development server**
```bash
npm run dev
bun run db:migrate
```
This starts all packages via Turborepo:
- Web app at `http://localhost:3000`
- Worker (if configured)
Pushes the schema (`drizzle-kit push --force`) and applies the search-vector triggers. Idempotent, safe to re-run.
6. **Start the development servers**
```bash
bun run dev
```
- API (Hono) on `http://localhost:3001`
- Web (Vite) on `http://localhost:3000`, proxying `/api` and `/mcp` to :3001
7. **Sign in as the initial admin**
Open `http://localhost:3000` and sign in with `INITIAL_ADMIN_EMAIL` and `INITIAL_ADMIN_PASSWORD`.
Open `http://localhost:3000` and sign in with `INITIAL_ADMIN_EMAIL` and `INITIAL_ADMIN_PASSWORD`. The first login creates the admin account.
## Project Structure
```
project-e/
├── apps/
── web/ # Next.js application
├── app/ # App Router pages and API routes
│ ├── (auth)/ # Auth pages (login, signup)
│ ├── (dashboard)/ # Dashboard pages
│ │ ├── api/ # REST API endpoints
│ │ │ ├── auth/ # Login, logout, refresh, me
│ │ │ ├── tasks/ # Task CRUD + bulk operations
│ │ │ ├── habits/ # Habit CRUD
│ │ │ ├── projects/ # Project CRUD
│ │ │ ├── notes/ # Note CRUD
│ │ │ ├── reports/ # Report CRUD
│ │ │ ├── milestones/ # Milestone CRUD
│ │ │ ├── domains/ # Domain CRUD
│ │ │ ├── tags/ # Tag CRUD
│ │ │ ├── agents/ # Agent CRUD
│ │ │ ├── webhooks/ # Webhook CRUD
│ │ │ ├── analytics/ # Analytics data
│ │ │ ├── realtime/ # SSE updates
│ │ │ ├── mcp/ # MCP server endpoint
│ │ │ └── health/ # Health check
│ │ └── layout.tsx # Root layout
│ ├── components/ # React components (shadcn/ui)
│ ├── hooks/ # Custom React hooks
│ ├── lib/ # Utilities, services, and NextAuth config
│ │ ├── mcp/ # MCP server and tools
│ │ ├── services/ # Business logic services
│ │ ├── stores/ # Zustand stores
│ │ ├── events/ # Event bus
│ │ ├── auth-config.ts # NextAuth configuration
│ │ └── errors.ts # Error handling
│ └── types/ # TypeScript type definitions
── api/ # Hono + Bun API server (routes, middleware, auth)
├── web/ # Vite + React 19 SPA (TanStack Router, shadcn/ui)
├── worker/ # Bun background worker (src/index.ts)
└── web-legacy/ # Old Next.js app, kept for reference only
├── packages/
│ ├── db/ # Drizzle schema and PostgreSQL client
│ └── shared/ # Shared package
│ └── src/
│ ├── schemas/ # Zod validation schemas
├── types/ # TypeScript types
│ └── constants/ # Shared constants
├── drizzle/ # Generated PostgreSQL migrations
├── worker/
│ └── index.ts # Background job worker
├── e2e/ # Playwright E2E tests
├── tests/ # Unit and component tests
├── drizzle.config.ts # Drizzle Kit configuration
├── turbo.json # Turborepo configuration
└── package.json # Root package.json
│ ├── db/ # Drizzle schema, client, and ORM access
│ └── shared/ # Shared types, schemas, and constants
├── drizzle/ # Drizzle migrations (00000005)
├── script/ # deploy.sh, apply-triggers.ts
├── e2e/ # Playwright E2E tests
├── .gitea/workflows/ # Gitea Actions CI/CD (ci.yml)
├── docker-compose.yml # Production stack (db, api, spa, worker)
├── Caddyfile # SPA serving + /api reverse proxy
├── Dockerfile.api # API image
├── Dockerfile.spa # SPA build + Caddy image
├── Dockerfile.worker # Worker image
├── bunfig.toml
├── drizzle.config.ts
└── package.json
```
## Available Scripts
| Command | Description |
|---------|-------------|
| `npm run dev` | Start all packages in development mode |
| `npm run build` | Build all packages for production |
| `npm run lint` | Run linting across all packages |
| `npm run test` | Run unit and component tests (Jest) |
| `npm run test:e2e` | Run Playwright E2E tests |
| `npm run test:e2e:ui` | Run Playwright tests with UI mode |
| `npm run test:e2e:report` | Show Playwright test report |
| `npm run typecheck` | Run TypeScript type checking |
| `npm run db:generate` | Generate Drizzle migrations |
| `bun run dev` | Run the API (watch) and the Vite dev server concurrently |
| `bun run dev:api` | API server with watch on :3001 |
| `bun run dev:web` | Vite dev server on :3000 |
| `bun run build` | Production build of the web SPA (`vite build`) |
| `bun run typecheck` | `tsc --noEmit` across api, worker, and web |
| `bun run db:push` | Push schema changes to the database (`drizzle-kit push`) |
| `bun run db:sync` | Push schema with `--force` (idempotent) |
| `bun run db:generate` | Generate a new Drizzle migration from schema changes |
| `bun run db:triggers` | Apply the search-vector triggers (idempotent) |
| `bun run db:migrate` | `db:sync` + `db:triggers`; what deploys run |
| `bun run db:studio` | Open Drizzle Studio |
| `bun run deploy` | Run `script/deploy.sh` (see DEPLOY.md) |
## Environment Variables
Variables live in a root `.env` file (not `.env.local`). Copy from `.env.example`.
| Variable | Description | Default |
|----------|-------------|---------|
| `DATABASE_URL` | PostgreSQL connection string | (required) |
| `POSTGRES_PASSWORD` | Password for the `project_e` PostgreSQL user | (required) |
| `NEXTAUTH_SECRET` | Secret used to sign NextAuth sessions | (required) |
| `POSTGRES_PASSWORD` | Password for the `project_e` user (used by docker-compose) | (required) |
| `AUTH_SECRET` | Secret that signs JWT sessions (`NEXTAUTH_SECRET` is accepted as a fallback) | (required) |
| `INITIAL_ADMIN_EMAIL` | Email for the account created on first sign-in | (required) |
| `INITIAL_ADMIN_PASSWORD` | Password for the account created on first sign-in | (required) |
| `NODE_ENV` | Environment (`development`, `production`) | `development` |
Create a `.env.local` file in the root directory for local development.
| `NODE_ENV` | `development` or `production` | `development` |
| `PUBLIC_URL` | Absolute URL used for emails and webhooks | `http://localhost:3000` |
| `COOKIE_SECURE` | Set `true` behind HTTPS | `false` |
| `ALLOWED_HOSTS` | Comma-separated list of allowed hostnames | `localhost` |
## Testing
### Unit and Component Tests
Playwright E2E tests live in `e2e/` (config at the repo root). Start the dev stack (`bun run dev`) in one terminal, then run:
```bash
npm run test
# Full suite
bunx playwright test
# Interactive UI mode
bunx playwright test --ui
# Plain list reporter
bunx playwright test --reporter=list
```
Runs Jest tests across all packages. Tests are located in `tests/` and alongside components.
### E2E Tests
```bash
# Run all E2E tests
npm run test:e2e
# Run with UI mode (interactive)
npm run test:e2e:ui
# View test report
npm run test:e2e:report
```
Playwright tests are in `e2e/` and cover:
- Authentication flows
- Task management
- Habit tracking
- Project organization
- Note editing
- Report generation
- Analytics dashboards
- Navigation and settings
Tests run against five browser configurations: Chromium, Firefox, WebKit, Mobile Chrome, and Mobile Safari.
Tests run against Chromium, Firefox, WebKit, Mobile Chrome, and Mobile Safari, and cover authentication, tasks, habits, projects, notes, reports, analytics, calendar, dashboard, search, settings, webhooks, realtime, MCP, and import/export.
## Deployment
### Environment Configuration
Provision PostgreSQL, apply `drizzle/0000_postgres.sql`, and set these in your deployment environment:
```bash
DATABASE_URL=postgresql://project_e:your_postgres_password@your-postgres-host:5432/project_e
POSTGRES_PASSWORD=your_postgres_password
NEXTAUTH_SECRET=your_long_random_secret
INITIAL_ADMIN_EMAIL=admin@example.com
INITIAL_ADMIN_PASSWORD=your_initial_admin_password
```
Start the web app and worker after the database is available:
```bash
npm run build
npm run --workspace @project-e/web start
npm run --workspace @project-e/worker start
```
### Health Checks
Use `GET /api/health` to check the web app.
Production runs as a docker-compose stack (db, api, spa, worker) on the host. Gitea Actions drives deploys: a `quality` gate runs on every push and PR, a `deploy` job on pushes to `main` runs `script/deploy.sh`, and a `smoke` job verifies health afterwards. Manual steps, rollback, and troubleshooting are in [DEPLOY.md](DEPLOY.md).
## Documentation
@@ -280,36 +215,11 @@ Use `GET /api/health` to check the web app.
## Contributing
1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Make your changes
4. Run tests (`npm run test && npm run test:e2e`)
5. Commit your changes (`git commit -m 'Add amazing feature'`)
6. Push to the branch (`git push origin feature/amazing-feature`)
7. Open a Pull Request
### Development Guidelines
- Write tests for new features
- Follow existing code style (TypeScript, functional components)
- Update documentation for API changes
- Keep commits atomic and well-described
- Use conventional commit messages
### Code Review Process
- All PRs require at least one review
- CI must pass (lint, typecheck, tests)
- Keep PRs focused on a single concern
- Write clear PR descriptions explaining the "why"
1. Fork the repository on Gitea and create a feature branch
2. Make your changes
3. Run `bun run typecheck` and `cd apps/web && bun run build` before committing
4. Push the branch and open a pull request. CI runs the same quality gate on every push and PR.
## License
This project is private and proprietary.
## Support
For issues and questions:
- Open an issue on GitHub
- Check the documentation in `docs/`
- Review existing issues for similar problems