Kanban Studio is a local-first project management MVP with a Next.js frontend, a FastAPI backend, and a SQLite database. It lets users sign up, sign in, manage a single Kanban board, move cards across fixed columns, edit board content, and use an AI sidebar for project-management assistance.
The application is designed to run locally as one web app served from the FastAPI backend at http://127.0.0.1:8000.
- User signup and sign in
- Session-based authentication
- One Kanban board per user
- Fixed board columns that can be renamed
- Cards that can be created, edited, moved, and deleted
- Drag-and-drop card movement
- SQLite persistence
- AI sidebar backed by OpenRouter, with mock fallback when no API key is available
- Backend serves both API routes and the built static frontend
- Docker configuration for single-container deployment
- Start and stop scripts for Windows, macOS, and Linux
- Next.js
- React
- TypeScript
- Tailwind CSS
- dnd-kit for drag and drop
- Vitest for unit tests
- Playwright for end-to-end tests
- Python
- FastAPI
- Uvicorn
- SQLite
- httpx
- python-dotenv
- OpenRouter API
- Current implementation model:
openai/gpt-3.5-turbo - Project requirement target model:
openai/gpt-oss-120b
.
+-- backend/
| +-- ai_service.py # OpenRouter integration and mock fallback
| +-- db.py # SQLite schema, seed data, and database operations
| +-- kanban.db # Local SQLite database
| +-- main.py # FastAPI app, API routes, static frontend serving
| +-- requirements.txt # Python dependencies
+-- docs/
| +-- PLAN.md # Main implementation plan and status
| +-- DATABASE_SCHEMA.md # Database design notes
| +-- schema.json # Schema reference
+-- frontend/
| +-- src/app/ # Next.js app shell
| +-- src/components/ # UI components
| +-- src/lib/ # API, auth, and Kanban utilities
| +-- tests/ # Playwright tests
| +-- package.json # Frontend scripts and dependencies
+-- scripts/
| +-- start-backend.bat # Windows start script
| +-- start-backend.sh # macOS/Linux start script
| +-- stop-backend.bat # Windows stop script
| +-- stop-backend.sh # macOS/Linux stop script
+-- Dockerfile
+-- docker-compose.yml
+-- README.md
- Python 3.11 or newer
- Node.js and npm
- Docker, optional
- OpenRouter API key, optional for AI live mode
The app can run without an OpenRouter key. In that case, AI endpoints return mock development responses.
Create a .env file in the project root when using AI live mode:
OPENROUTER_API_KEY=your_openrouter_api_key
ENVIRONMENT=developmentENVIRONMENT is optional. In development mode, the backend allows all CORS origins.
Run these commands from the project root.
scripts\start-backend.batchmod +x scripts/start-backend.sh
./scripts/start-backend.shThe start script:
- Installs frontend dependencies.
- Builds the Next.js static frontend.
- Installs backend dependencies.
- Starts FastAPI on
http://127.0.0.1:8000.
Open the app at:
http://127.0.0.1:8000
scripts\stop-backend.batchmod +x scripts/stop-backend.sh
./scripts/stop-backend.shThis is useful for UI development, but API-backed features require the FastAPI backend.
cd frontend
npm install
npm run devBy default, Next.js runs on:
http://localhost:3000
python -m pip install -r backend/requirements.txt
python -m uvicorn backend.main:app --host 127.0.0.1 --port 8000 --reloadBefore serving the full frontend from the backend, build the frontend:
cd frontend
npm install
npm run build
cd ..Build and run with Docker Compose:
docker compose up --buildThe app will be available at:
http://localhost:8000
The compose file mounts ./backend into the container so the SQLite database persists between restarts.
The app supports:
- Signup for new local test users
- Login for existing users
- Logout
- Session persistence in browser localStorage
The seeded default user is:
Username: user
Password: password
Newly signed-up users automatically receive one board with five default columns:
- Backlog
- Discovery
- In Progress
- Review
- Done
Passwords are stored in the current MVP database field named password_hash, but they are not yet hashed. This is acceptable only for local MVP testing.
The SQLite database lives at:
backend/kanban.db
The database is created automatically when the backend starts if it does not already exist.
Main tables:
users: login accountsboards: one board per user for the MVPcolumns: fixed board columnscards: Kanban task cardsactivity_log: activity records for future workflow history
The schema is documented in:
docs/DATABASE_SCHEMA.md
docs/schema.json
All API routes are served under /api.
POST /api/auth/signup
POST /api/auth/login
POST /api/auth/logout?session_id={session_id}Signup and login request body:
{
"username": "user",
"password": "password"
}Successful response:
{
"session_id": "uuid-session-id",
"username": "user"
}GET /api/board?session_id={session_id}Returns the signed-in user's board, columns, and cards.
POST /api/board/cards?session_id={session_id}&column_id={column_id}
PUT /api/board/cards/{card_id}?session_id={session_id}
DELETE /api/board/cards/{card_id}?session_id={session_id}Create card body:
{
"title": "Write launch notes",
"details": "Draft concise release notes for the MVP.",
"priority": "medium",
"due_date": null,
"assignee": null
}Move card body:
{
"column_id": 3,
"position": 0
}Update card body:
{
"title": "Updated title",
"details": "Updated details",
"priority": "high",
"due_date": "2026-06-30",
"assignee": "Alex"
}POST /api/board/columns/{column_id}?session_id={session_id}Rename column body:
{
"title": "In Review"
}GET /api/ai/test
POST /api/ai/ask?session_id={session_id}&question={question}The AI service uses OpenRouter when OPENROUTER_API_KEY is configured. Without a key, it returns mock responses for local development.
GET /health
GET /api/testRun frontend unit tests:
cd frontend
npm run test:unitRun end-to-end tests:
cd frontend
npm run test:e2eRun all frontend tests:
cd frontend
npm run test:allRun a Python syntax check for backend files:
python -m py_compile backend/main.py backend/db.py backend/ai_service.pyThe frontend uses next/font/google for Manrope and Space Grotesk. A production build requires network access to fetch those fonts unless the fonts are changed to local assets.
If npm run build fails with a Google Fonts fetch error, the root cause is network access rather than application code.
- Passwords are not hashed yet.
- Sessions are stored in memory, so they reset when the backend restarts.
- The SQLite database is local to the machine or container volume.
- The MVP supports one board per user.
- AI board-editing behavior is still limited and partially mocked depending on OpenRouter access.
- The project requirement names
openai/gpt-oss-120b, but the current code usesopenai/gpt-3.5-turbo. - Full lint currently scans generated output unless the command is scoped to source files.
- Read
docs/PLAN.mdbefore starting new feature work. - Keep changes small and aligned with the existing frontend and backend patterns.
- Prefer the existing API client in
frontend/src/lib/api.tsfor frontend/backend calls. - Prefer
DatabaseOpsinbackend/db.pyfor database changes. - Keep documentation in
docs/for planning and implementation notes.