A production-grade Task Management API built with Go, featuring a clean architecture, robust security, and deep observability. The project also includes a Svelte 5 demo client to showcase the API's capabilities in a real-world scenario.
Taskify is primarily a backend-focused project showcasing advanced Go engineering patterns, secure authentication, and system observability:
slog.golang-migrate.| Backend | Go 1.24, Gin | | Database | PostgreSQL 17, GORM | | Auth & Security | JWT (RSA), Argon2id, Casbin (RBAC) | | Tracing | OpenTelemetry + Jaeger | | Cache | Redis 7 | | Documentation | Swagger (swag) | | Containerization | Docker, Docker Compose | | Frontend (Demo) | Svelte 5, TanStack Query, Skeleton UI |
The project maintains a clear separation between the presentation layer and the core business logic:
┌─────────────────────────────────────────────────────┐
│ Bonus Frontend Demo (Svelte) │
│ Reactive UI, TanStack Query, Skeleton Components │
├─────────────────────────────────────────────────────┤
│ Backend (Go API) │
│ Handlers, Services, Repositories, Domain Models, │
│ Middleware (Auth, RBAC, Tracing, Rate Limiting) │
├─────────────────────────────────────────────────────┤
│ Infrastructure Layer │
│ PostgreSQL, Redis, OpenTelemetry, S3-style Uploads │
└─────────────────────────────────────────────────────┘
.
├── backend/ # Go API Core (Go 1.24 + Gin)
│ ├── cmd/
│ │ ├── api/ # API entrypoint (server setup & shutdown)
│ │ └── seed/ # Database seeding logic
│ ├── internal/
│ │ ├── config/ # Environment configuration (caarlos0/env)
│ │ ├── handlers/ # HTTP Handlers (Restful logic)
│ │ ├── middleware/ # Gin Middlewares (Auth, RBAC, Tracing, CORS)
│ │ ├── models/ # Domain models and GORM entities
│ │ ├── pkg/ # Common utilities (JWT, Hashing, Tracing)
│ │ ├── repository/ # Data access layer (GORM implementations)
│ │ ├── routes/ # Router registration and wiring
│ │ └── service/ # Business logic and coordination
│ ├── migrations/ # Versioned SQL migrations (golang-migrate)
│ ├── model.conf # Casbin RBAC model configuration
│ └── Dockerfile # Multi-stage optimized production build
├── frontend/ # Svelte 5 Demo Client (Bonus)
│ ├── src/ # Reactive state, components, and routes
│ └── Dockerfile # Nginx-based production deployment
├── deployment/ # Docker Compose orchestration
└── Makefile # Task automation (Migrations, Keys, Docker)
| Tool | Version | Purpose |
|---|---|---|
| Go | 1.24+ | Build and run the backend API |
| Node.js | 20+ | Build and run the frontend application |
| Docker | 20.10+ | Orchestrate local infrastructure (Postgres, Redis, Jaeger) |
| OpenSSL | any | Generate RSA key pairs for JWT signing |
The application loads settings from environment variables, with an optional .env file for local development.
| Variable | Required | Default | Description |
|---|---|---|---|
DB_HOST |
✅ | localhost |
PostgreSQL host address |
DB_PORT |
✅ | 5432 |
PostgreSQL port |
DB_USER |
✅ | — | PostgreSQL username |
DB_PASSWORD |
✅ | — | PostgreSQL password |
DB_NAME |
✅ | — | PostgreSQL database name |
APP_PORT |
❌ | 8080 |
Backend API listening port |
ENV |
❌ | development |
Environment (development or production) |
PRIVATE_KEY_PATH |
❌ | private.pem |
Path to RSA private key for JWT |
PUBLIC_KEY_PATH |
❌ | public.pem |
Path to RSA public key for JWT |
OTLP_ENDPOINT |
❌ | localhost:4317 |
OpenTelemetry Collector endpoint |
REDIS_HOST |
❌ | localhost |
Redis server host |
RATE_LIMIT_GLOBAL |
❌ | 100-M |
Global rate limit (requests-period) |
UPLOAD_PATH |
❌ | uploads |
Directory for task attachments |
| Variable | Required | Default | Description |
|---|---|---|---|
PUBLIC_API_URL |
✅ | http://localhost:8080 |
Backend API base URL |
The fastest way to get the full stack running (API + Frontend + Postgres + Redis + Jaeger):
# 1. Clone the repository
git clone https://github.com/jandiralceu/taskify.git
cd taskify
# 2. Generate RSA keys for JWT authentication
make generate-keys
# 3. Start all services (Infra + API + Frontend)
# This builds images and runs database migrations automatically
make docker-up-all
# 4. (Optional) Seed the database with sample data (CR7, Messi, etc)
make db-restore
Access the Frontend at http://localhost:3000 and the API at http://localhost:8080.
For testing purposes, you can use the following pre-configured accounts. All users share the same password: P4ss0Rdd.
| Role | Name | Tasks? | |
|---|---|---|---|
| Admin | Cristiano Ronaldo | [email protected] |
✅ Yes |
| Admin | Lionel Messi | [email protected] |
✅ Yes |
| Employee | Neymar Junior | [email protected] |
✅ Yes |
| Employee | Lamine Yamal | [email protected] |
✅ Yes |
[!TIP] Use an Admin account to manage roles and other users, or an Employee account for standard task management.
Run the backend natively for debugging while keeping infrastructure in Docker:
# 1. Start infrastructure containers (DB, Redis, Jaeger)
# Current directory should be root
make docker-up
# 2. Setup Backend
cd backend
cp .env.example .env # Update with your local settings
make generate-keys
make migration-up
go run cmd/api/main.go
# 3. Setup Frontend (In a new terminal)
cd frontend
cp .env.example .env # Update PUBLIC_API_URL if necessary
npm install
npm run dev
| Command | Location | Description |
|---|---|---|
make docker-up |
Root | Start PostgreSQL, Redis, and Jaeger containers |
make docker-up-all |
Root | Start all containers including the Go API and Svelte Demo |
make docker-down |
Root | Stop and remove all Docker containers |
make generate-keys |
Root | Generate RSA key pairs for JWT signing |
make test |
Root | Run all tests (Backend unit + Integration, Frontend unit) |
make start |
Backend | Run the Go application natively with go run |
make migration-up |
Backend | Apply all pending database migrations |
make migration-down |
Backend | Rollback the latest database migration |
make db-dump |
Root | Create a data-only backup to deployment/seed.sql |
make db-restore |
Root | Restore database data from deployment/seed.sql |
make swagger |
Backend | Regenerate Swagger API documentation |
make lint |
Root | Run code quality checks across the entire stack |
Full interactive documentation is available via Swagger UI at http://localhost:8080/swagger/index.html when the server is running. The API follows REST conventions and is organized into logical resource groups:
| Group | Prefix | Auth | Description |
|---|---|---|---|
| Authentication | /auth |
No | Registration, Login, Logout, and Token Refresh |
| Roles | /roles |
Yes | Dynamic RBAC management and role assignments |
| Users | /users |
Yes | User profiles and account management |
| Tasks | /tasks |
Yes | Kanban lifecycle (CRUD, filtering, archiving) |
| Notes | /notes |
Yes | Task comments and threaded discussions |
| Attachments | /attachments |
Yes | File uploads and binary asset management |
The application uses a PostgreSQL database with a dynamic RBAC (Role-Based Access Control) system. The relationship between core entities is visualized below:
erDiagram
users {
uuid id PK
string email UK
string password_hash
string first_name
string last_name
boolean is_active
string avatar_url
}
roles {
uuid id PK
string name UK
string description
}
permissions {
uuid id PK
string resource
string action
string description
}
tasks {
uuid id PK
string title
string status
string priority
uuid created_by FK
uuid assigned_to FK
boolean is_blocked
boolean is_archived
}
task_notes {
uuid id PK
uuid task_id FK
uuid user_id FK
text content
}
task_attachments {
uuid id PK
uuid task_id FK
uuid user_id FK
string file_path
}
casbin_rule {
bigint id PK
string v0 "Subject (Role)"
string v1 "Object (URL)"
string v2 "Action (Method)"
}
users }o--o{ roles : "user_roles"
roles }o--o{ permissions : "role_permissions"
users ||--o{ tasks : "created_by/assigned_to"
tasks ||--o{ task_notes : "has_comments"
tasks ||--o{ task_attachments : "has_files"
users ||--o{ task_notes : "writes"
users ||--o{ task_attachments : "uploads"
Database schema management is handled exclusively by golang-migrate. When running via Docker, migrations are applied automatically by a dedicated container before the API starts.
# 1. Create a new migration file
cd backend && make migration-create name=add_indices_to_tasks
# 2. Apply migrations manually
make migration-up
# 3. Rollback (if necessary)
make migration-down
You can backup the current state of your database (data only) or restore it using the following commands:
# Save current database data (users, tasks, etc) to deployment/seed.sql
make db-dump
# Restore data from deployment/seed.sql into the database
make db-restore
Note: These commands use the
taskify-postgresDocker container to perform the dump and restore.
Taskify implements a dual-layer testing strategy to ensure reliability across both business logic and infrastructure integration.
Focused on isolated logic using Go's built-in testing package.
cd backend && make test-unit
Utilizes testcontainers-go to spin up ephemeral PostgreSQL and Redis instances, exercising the full data access layer.
cd backend && make test-integration
The application is fully instrumented with OpenTelemetry for distributed tracing. Every request is tracked as it passes through middleware, business logic, and database queries.
This project is licensed under the MIT License.