Architecture
Symphony API follows a conventional layered Express architecture optimized for simplicity and demonstration purposes.
High-level overview
Client (curl / browser / frontend)
│
▼
┌─────────────────────────────────┐
│ Express Application │
│ ┌───────────┐ ┌─────────────┐ │
│ │ CORS │ │ JSON body │ │
│ │ middleware│ │ parser │ │
│ └───────────┘ └─────────────┘ │
│ ┌───────────────────────────┐ │
│ │ Route handlers │ │
│ │ /api/projects │ │
│ │ /api/tasks │ │
│ │ /api/teams │ │
│ └───────────────────────────┘ │
│ ┌───────────────────────────┐ │
│ │ Error handler middleware │ │
│ └───────────────────────────┘ │
└─────────────────────────────────┘
│
▼
┌─────────────────────────────────┐
│ In-memory data store │
│ (loaded from JSON seed files) │
└─────────────────────────────────┘
Request lifecycle
- An HTTP request arrives at the Express server.
- Global middleware runs: CORS headers are set, and the JSON body (if present) is parsed.
- The request is matched against registered route handlers (
/api/projects,/api/tasks,/api/teams). - The route handler reads from or mutates the in-memory data arrays.
- A JSON response is sent back to the client.
- If no route matches, the
notFoundmiddleware generates a 404 error. - Any thrown or forwarded error is caught by the centralized
errorHandlermiddleware, which returns a consistent JSON error envelope.
Data model
Symphony manages three entity types:
| Entity | Key fields | Relationships |
|---|---|---|
| Project | id, name, status, teamId | Belongs to a Team; has many Tasks |
| Task | id, projectId, title, status, priority, assignee | Belongs to a Project |
| Team | id, name, members[] | Has many Projects |
All IDs are prefixed strings (e.g. proj_01, task_01, team_01). New records receive a UUID-based ID at creation time.
Design decisions
- No database — data is held in plain JavaScript arrays cloned from JSON seed files at startup. This keeps the demo dependency-free and instantly runnable.
- Mutable state — POST, PUT, PATCH, and DELETE operations modify the in-memory arrays. Restarting the server resets all data to the seed values.
- No authentication — the API is open by default. See Authentication for how to add token-based auth in a production deployment.
- Centralized error handling — all errors flow through a single Express error middleware that produces a uniform
{ error: { code, message } }envelope.