A full-stack task management application built with ASP.NET Core 8 Web API, Angular 17, and PostgreSQL, following Clean Architecture principles.
- Frontend: https://task-manager-web-topaz.vercel.app
- Backend API: https://zestful-sparkle-production.up.railway.app
As a team member, I want to manage my tasks through a web application, So that I can create, view, update, and delete tasks while having my account secured with authentication.
- Users can register and log in with username/password
- Authenticated users can create tasks with a title, description, status, and due date
- Users can view all tasks (public) or filter to see only their own tasks
- Users can edit and delete their tasks
- Task status can be set to Pending, InProgress, or Completed
- The "All Tasks" view displays the owner of each task
- Unauthenticated users are redirected to the login page
- All operations are available through a responsive web interface
This project follows Clean Architecture principles with clear separation of concerns:
TaskManager/
├── src/
│ ├── TaskManager.Domain/ # Entities, Interfaces, Exceptions (innermost)
│ ├── TaskManager.Application/ # Services, DTOs, Validation, Mapping
│ ├── TaskManager.Infrastructure/ # PostgreSQL + ADO.NET, JWT Auth, BCrypt
│ ├── TaskManager.WebAPI/ # ASP.NET Core 8 Controllers, Middleware
│ └── TaskManager.Angular/ # Angular 17 Frontend
├── tests/
│ ├── TaskManager.Domain.Tests/ # 25 tests
│ ├── TaskManager.Application.Tests/ # 88 tests
│ └── TaskManager.WebAPI.Tests/ # 33 tests
├── Dockerfile
├── PROCESS.md # Development thought process
└── TaskManager.sln
Dependency Flow: WebAPI -> Application -> Domain <- Infrastructure
- No Entity Framework / Dapper / Mediator: Raw ADO.NET with Npgsql for data access, demonstrating manual SQL and parameter handling
- PostgreSQL (Neon): Serverless PostgreSQL for production; auto-scaling and zero infrastructure management
- JWT Authentication: Stateless token-based auth with BCrypt password hashing
- Clean Architecture: Domain has zero dependencies; Application depends only on Domain; Infrastructure implements Domain interfaces
- Custom Migration Runner: SQL migration files embedded as assembly resources, tracked in
__MigrationHistory, executed in transactions on startup - Standalone Components: Angular 17 standalone components (no NgModule)
- .NET 8 SDK
- Node.js 18+ and npm
- Angular CLI (
npm install -g @angular/cli)
# From the root directory
dotnet restore
dotnet build
# Run the API (database migrations run automatically)
dotnet run --project src/TaskManager.WebAPIThe API will be available at:
- HTTP: http://localhost:5000
- Swagger UI: http://localhost:5000/swagger (Development mode only)
cd src/TaskManager.Angular
npm install
ng serveThe app will be available at http://localhost:4200
# Run all 146 tests
dotnet test
# Run with verbose output
dotnet test --verbosity normal
# Run specific test project
dotnet test tests/TaskManager.Domain.Tests
dotnet test tests/TaskManager.Application.Tests
dotnet test tests/TaskManager.WebAPI.TestsBackend configuration is in src/TaskManager.WebAPI/appsettings.json:
{
"ConnectionStrings": {
"DefaultConnection": "Host=...;Database=...;Username=...;Password=...;SSL Mode=Require"
},
"JwtSettings": {
"SecretKey": "YourSuperSecretKeyThatIsAtLeast32CharactersLong!2024",
"Issuer": "TaskManagerAPI",
"Audience": "TaskManagerApp",
"ExpirationMinutes": 60
}
}The application seeds the following data on first run:
Demo User:
- Username:
admin - Password:
Admin123! - Email: admin@taskmanager.com
Sample Tasks:
- "Complete project documentation" - Pending
- "Setup continuous integration" - InProgress
- "Review code quality" - Pending
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| GET | /api/tasks | No | Get all tasks (with owner username) |
| GET | /api/tasks/{id} | Yes | Get task by ID |
| GET | /api/tasks/my | Yes | Get current user's tasks |
| POST | /api/tasks | Yes | Create a new task |
| PUT | /api/tasks/{id} | Yes | Update a task |
| DELETE | /api/tasks/{id} | Yes | Delete a task |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| POST | /api/auth/register | No | Register a new user |
| POST | /api/auth/login | No | Login and get JWT token |
| GET | /api/auth/me | Yes | Get current user info |
Backend:
- .NET 8 / ASP.NET Core 8 Web API
- PostgreSQL with raw ADO.NET (Npgsql)
- JWT Bearer Authentication
- BCrypt.Net for password hashing
- Global exception handling middleware
- Custom SQL migration runner
Frontend:
- Angular 17 (standalone components)
- Bootstrap 5 (responsive: table on desktop, cards on mobile)
- RxJS
- TypeScript
- Auth interceptor + route guards
Testing (146 tests):
- xUnit
- Moq
- FluentAssertions
Deployment:
- Backend: Railway (Docker)
- Frontend: Vercel
- Database: Neon (serverless PostgreSQL)