Disclaimer: I started this project to see how far I could get with Claude Code on a stack I've never worked with before. I deliberately chose Rust, Leptos, and Diesel so I'd have less temptation to write the code myself — I lead the architecture and design, and Claude Code writes the implementation, which turns out to be pretty close to a tech lead job. I've been quite impressed with the results, though I've also learned a lot about what AI-assisted development can and can't do. For context, I have 15 years of experience in web development — I know how to write code, design systems, deploy, and maintain things — but this project is an exercise in agentic coding. I do aim to bring it to a stable release, though it's not there yet. Use it at your own risk.
A self-hosted, GTD-inspired task management system built entirely in Rust. North combines a full-stack Rust architecture with practical Getting Things Done workflows — sequential subtask execution, structured review cycles, and a powerful query language for filtering tasks.
- Inbox & Today views — capture tasks quickly, then focus on what's actionable today
- Sequential subtasks — configurable N-next visibility so you only see the tasks you should work on now
- Recurring tasks — flexible recurrence rules (daily, weekly, monthly, yearly) with fixed-schedule or after-completion modes
- GTD review cycles — per-task review tracking with configurable intervals to keep your system current
- Projects & tags — organize work with colored projects (list or kanban view) and user-defined tags
- Filter DSL — JQL-like query language with autocomplete for building saved filters (
status = 'ACTIVE' AND tags =~ 'work:*' ORDER BY due_date ASC) - Keyboard-driven task management — full keyboard navigation with tree-aware cursor, inline editing, task creation, and reordering (press
?to see all shortcuts) - Inline parsing — type
#tagor@projectdirectly in task titles to assign tags and projects on the fly - Markdown support — full CommonMark rendering in task descriptions
- Drag and drop — reorder tasks, nest subtasks, and organize with drag-and-drop or keyboard shortcuts
- Dark & light themes — respects system preference with manual toggle
- Timezone support — per-user timezone setting for accurate scheduling and recurrence display
- REST API — full CRUD API for external integrations alongside the web UI
- Single binary — one Rust binary serves both the server-rendered pages and the WASM-hydrated client
North is a full-stack Rust application — no JavaScript runtime, no Node.js, no npm.
| Layer | Technology |
|---|---|
| Language | Rust (stable, edition 2021) |
| Frontend | Leptos 0.7 (SSR + WASM hydration) |
| Backend | Axum |
| Database | PostgreSQL 17 via Diesel (async) |
| Styling | TailwindCSS 4 |
| Auth | JWT (httpOnly cookies) with Argon2 password hashing |
- Docker & Docker Compose
# Clone the repository
git clone https://github.com/zorya-development/north.git
cd north
# Build and start all services
docker compose up -d
# Run database migrations and seed the admin account
docker compose exec app just migrate
docker compose exec app just seedThe application will be available at http://localhost:5000.
Default admin credentials: admin@north.local / admin
There is no self-registration. The admin account creates all other users.
The included Helm chart deploys North to any Kubernetes cluster with PostgreSQL, automatic migrations, uploads persistence, and optional ingress/TLS.
- Kubernetes 1.24+
- Helm 3.x
kubectlconfigured for your cluster
# From OCI registry (published automatically on chart changes)
helm install north oci://ghcr.io/zorya-development/north/charts/north \
-n north --create-namespace
# Or from a local clone
helm install north ./chart -n north --create-namespaceThe admin account is seeded automatically on first install. Default credentials: admin@north.app / admin. Password change is not yet implemented — do not expose this to the public internet.
helm install north ./chart -n north --create-namespace \
--set ingress.enabled=true \
--set ingress.className=nginx \
--set ingress.hosts[0].host=tasks.example.com \
--set ingress.hosts[0].paths[0].path=/ \
--set ingress.hosts[0].paths[0].pathType=Prefix \
--set ingress.tls[0].hosts[0]=tasks.example.com \
--set ingress.tls[0].secretName=north-tlshelm install north ./chart -n north --create-namespace \
--set postgresql.enabled=false \
--set externalDatabase.host=postgres.example.com \
--set externalDatabase.password=secretkubectl create secret generic north-secrets -n north \
--from-literal=database-url='postgres://user:pass@host:5432/north' \
--from-literal=jwt-secret='your-secret-here'
helm install north ./chart -n north \
--set existingSecret.name=north-secrets| Value | Default | Description |
|---|---|---|
image.tag |
Chart appVersion | Docker image tag |
postgresql.enabled |
true |
Deploy in-cluster PostgreSQL (Bitnami) |
postgresql.auth.password |
auto-generated | PostgreSQL password |
secret.jwtSecret |
auto-generated | JWT signing secret (preserved across upgrades) |
secret.databaseUrl |
— | Explicit DATABASE_URL (overrides all other DB config) |
existingSecret.name |
— | Use a pre-created Secret (keys: database-url, jwt-secret) |
externalDatabase.host |
— | External PostgreSQL host (when postgresql.enabled=false) |
ingress.enabled |
false |
Create an Ingress resource |
ingress.className |
— | Ingress class (e.g. nginx, traefik) |
persistence.enabled |
true |
PVC for uploads (/app/uploads) |
persistence.size |
5Gi |
Uploads volume size |
migration.enabled |
true |
Run Diesel migrations as a pre-install/pre-upgrade hook |
autoscaling.enabled |
false |
Enable HPA (scales 1–3 replicas on CPU) |
resources.requests.memory |
128Mi |
Memory request |
resources.limits.memory |
512Mi |
Memory limit |
Full values reference: chart/values.yaml
- Docker & Docker Compose
# Build the base and dev images
docker compose build
# Start the database
docker compose up -d db
# Enter the app container
docker compose run --rm -ti --service-ports app bash
# Inside the container:
just migrate # Apply database migrations
just seed # Seed admin account
just dev # Start dev server with hot reloadAll commands run inside the app container via just:
| Command | Description |
|---|---|
just dev |
Dev server with hot reload (cargo-leptos) |
just test |
Run all tests |
just test crate_name |
Run tests for a specific crate |
just fmt |
Format code |
just lint |
Run clippy |
just check |
fmt + lint + test |
just migrate |
Apply database migrations |
just migration name |
Create a new migration |
just migrate-revert |
Revert last migration |
just migrate-redo |
Revert + reapply last migration |
just build |
Release build |
just seed |
Seed admin account |
For CI or non-interactive use: docker compose exec app just <command>
E2E tests use Playwright and run against the full app in Docker. Commands run from the host (not inside the app container):
just playwright # Start test stack + Playwright UI mode (port 8080)
just playwright-exec # Run tests headless in already-running containers
just playwright-down # Tear down test containers and volumes
# Rebuild test containers (needed after migrations, schema changes, or new features)
just playwright-down && docker compose -p north-test -f docker-compose.test.yml up -d --buildNorth is organized as a Cargo workspace with layered crates:
north/
├── crates/
│ ├── dto/ # Shared data types (no IO) — compiled for server and WASM
│ ├── db/ # Diesel schema, models, connection pool
│ ├── core/ # Business logic, services, filter DSL engine
│ ├── server-fns/ # Leptos #[server] RPC boundary
│ ├── repositories/ # Thin async facade over server functions
│ ├── stores/ # Reactive client state (signals, memos, optimistic updates)
│ ├── ui/ # Generic UI component library (no domain deps)
│ ├── app/ # Leptos pages, containers, components (SSR + WASM)
│ └── server/ # Axum binary, REST API, auth middleware
├── migrations/ # Diesel reversible migrations (up.sql + down.sql)
├── style/ # TailwindCSS entry point
├── public/ # Static assets
├── chart/ # Helm chart for Kubernetes deployment
├── docker/ # Base, dev, and prod Dockerfiles
└── docs/ # Product requirements, design system, and architecture reference
Data flows through the layers in one direction:
Page → Store → Repository → ServerFn ──RPC──→ Service → Diesel → PostgreSQL
| Image | Path | Purpose |
|---|---|---|
| base | docker/base/Dockerfile |
Rust toolchain, cargo-leptos, diesel_cli, wasm32 target |
| dev | docker/dev/Dockerfile |
Extends base — adds just and tailwindcss CLI |
| prod | docker/prod/Dockerfile |
Runtime-only: debian:bookworm-slim with pre-built binary |
Base image version is tracked in docker/base/VERSION. Bump with:
just bump-base patch # 1.0.0 → 1.0.1
just bump-base minor # 1.0.0 → 1.1.0
just bump-base major # 1.0.0 → 2.0.0- test.yml — runs on pushes to master and all PRs: format check, clippy, tests. Conditionally rebuilds the base image if
docker/base/**changed. - release.yml — runs on pushes to master: builds a production Docker image, pushes to ghcr.io, generates a changelog via git-cliff, and creates a GitHub release.
- Bump version:
just bump-version {major,minor,patch} - Push to master (via PR or direct push)
- The release workflow automatically builds and publishes the Docker image, changelog, and GitHub release
Proprietary — Zorya Development
