§ unswayed-backend
The rebuild roadmap
What it is
unswayed-backend (NestJS) is a ground-up reimplementation of a legacy Laravel
backend — a job-board crossed with a professional social network. The legacy
app is large: 58 database tables, ~60 controllers (public / applicant /
employer / admin), 10 services (Affinda résumé parsing, Azure Search,
Cloudinary, Stripe, an AI assistant "Lexi", OTP, social login…), 16 mailables,
11 queued jobs, real-time chat, subscriptions, and a full admin panel.
The rebuild roadmap is the project-management plan for recreating all of that
in NestJS, faithfully. It lives in the repo at docs/roadmap/ and is the
companion to the API contract & docs:
the contract says what the wire looks like; the roadmap says how we build to it.
The manifest is the single source of truth
Everything keys off one machine-readable file: docs/roadmap/roadmap.json. It
holds every phase, every task, and top-level inventories of models,
emails, and integrations. Each task carries:
legacy— the realapp/...files it reimplements,contract— the frozenendpoint_documentation.mdsection(s) it must match,endpoints/models/emails/jobs/servicesit touches,improvement— a modernization scoped to internals (never the wire contract),knownIssue— a legacy bug to "do right this time" (mined from the legacy repo's 20+*_ANALYSIS.md/*_FIX.mdpost-mortems),detect— hints (modules / prisma models / routes / specs) the progress dashboard uses to auto-check what's actually built.
The same manifest drives both the written guide and the live dashboard, so they can never disagree about scope.
The 13 phases (dependency-ordered)
| # | Phase | Delivers |
|---|---|---|
| 0 | Foundation ✅ | auth, social login, mailer, users, API contract, governance (already built) |
| 1 | Platform infrastructure | BullMQ queue, scheduler, storage/media port, FCM push, realtime gateway, notifications, audit log |
| 2 | Master data & reference | countries/states/cities, genders, ethnicities, disabilities, universities, job taxonomies + FK enforcement |
| 3 | Profiles | applicant (education, résumé + Affinda/AI parse, filter prefs) + employer company profiles |
| 4 | Employer jobs | job CRUD + pivots, requisition #, interview rounds, salary, dashboard |
| 5 | Discovery & applications | search/filter, internal + external (JSearch) jobs, saves, alerts, applications + documents + history |
| 6 | Hiring pipeline | interviews (Google Calendar/Meet), offers, status transitions, hiring emails, reviews |
| 7 | Social feed & reels | posts/comments/likes/shares, feed, reels, reports, Cloudinary media |
| 8 | Blog | blogs, comments, likes, views |
| 9 | Chat & AI assistant | chats/messages over a realtime gateway, Lexi assistant |
| 10 | Subscriptions & billing | plans, Stripe + webhooks, histories, expiration reminders |
| 11 | Engagement extras | employer reviews, support tickets, feedback, talent network |
| 12 | Admin panel & RBAC | admin auth, roles/permissions/modules, full CRUD, dashboard, logs |
The ordering is enforced by real dependencies (e.g. Discovery needs Employer
jobs + Profiles + Master data); each phase doc states its dependsOn.
How the guide is organized
docs/roadmap/
├── README.md # master plan: phases at a glance, how to use, legend
├── roadmap.json # the manifest (single source of truth)
├── conventions.md # how EVERY feature is built (Nest module, TDD, edge mapping, ports, DoD)
├── phases/PHASE-NN-*.md # one per phase; each task uses the per-task template
├── workflows/ # applicant-journey.md + employer-journey.md (end-to-end)
└── reference/ # data-model · endpoints-index · emails · integrations · legacy-map
Every task in a phase doc follows one template: What to build · Legacy source · Wire contract § · Data-model delta · Emails/Jobs/Services · Suggested improvement · Known legacy issue · Definition of Done — and links out to the reference docs so the detail lives in one place. The two journey docs narrate the full applicant and employer lifecycles end-to-end.
Two rules that never bend
- The wire contract is frozen.
endpoint_documentation.mdis read-only; the rebuild reconciles to it byte-for-byte (snake_case under/api, the{status,message,data}envelope). Improvements are always internal. - Match legacy behavior, then improve the internals. Where the legacy app had a bug (OTP-queue crashes, video-upload 500s, the external-jobs country filter), the roadmap attaches a "do it right this time" note to the relevant task.
The plan stays honest because the progress dashboard live-scans the repo and flags any drift between the manifest's recorded status and what the code actually shows.
Subpages