Swift Essay is an academic writing marketplace where admins post writing orders and writers claim, complete, and submit them for payment. It's built as a full-stack Next.js application with a MongoDB backend.
Why the order lifecycle is a state machine. Orders move through unassigned → assigned → in_progress → revision → completed, with cancelled as an exit at several points. I modelled it as explicit states rather than a set of booleans because the transitions have rules attached: a writer can only claim an unassigned order, only the assigned writer can submit work, and only an admin can mark something paid. Keeping that in the status field rather than scattering checks through the handlers meant the authorisation logic stayed in one place.
Auth and route guards. JWT with bcrypt password hashing, and guards enforced on the admin API routes rather than only in the UI. Hiding a button doesn't secure an endpoint, and the admin actions here move money.
What I'd change. The service layer calls API routes directly from the client, which was fine at this scale but would need a more deliberate caching and invalidation strategy as order volume grew. TanStack Query handles part of that, but I'd think harder about query keys. I'd also add tests around the status transitions, since that's the logic most likely to break as the rules change.
-
User Roles:
- Admin: Creates and manages orders, assigns/tracks writers, and processes payments.
- Writer: Browses available orders, claims work, submits completed files, and tracks earnings.
-
Order Management:
- Admins create orders with discipline, deadline, pricing (per page/total), and reference files.
- Writers claim unassigned orders and upload submitted files when work is complete.
- Orders move through a status lifecycle:
unassigned → assigned → in_progress → revision → completed(orcancelled). - File uploads (order attachments and submissions) are stored via Cloudinary.
-
Payments:
- Admins mark orders as paid; dedicated payment views for admins and writers track paid/unpaid orders.
-
Notifications:
- In-app notifications (new order, order paid, order completed) are created for relevant users and can be marked as read.
-
Authentication:
- JWT-based auth with login, registration, password reset, and a "forgot password" flow.
- Route guards restrict admin-only API endpoints.
-
Dashboards:
- Role-specific dashboards (admin and writer) with a shared topbar/sidebar layout, order tables, and writer profile pages.
-
Clone the repository:
git clone https://github.com/jmdotdev/swift-essay.git cd swift-essay -
Install dependencies:
pnpm install
-
Set up environment variables:
Create a
.envfile in the root directory with the variables your environment needs, for example:MONGODB_URI= JWT_SECRET= CLOUDINARY_CLOUD_NAME= CLOUDINARY_API_KEY= CLOUDINARY_API_SECRET= SMTP_HOST= SMTP_PORT= SMTP_USER= SMTP_PASS= -
Run the development server:
pnpm dev
-
Open your browser and visit http://localhost:3000 to view the app.
-
Admin:
- Create new orders, monitor their status, and edit order details.
- View and manage writers, assign orders, and mark orders as paid.
-
Writer:
- Browse available orders and claim ones matching their skills/deadline.
- Submit completed files, track "my orders," and review payment history.
- Manage profile details from a dedicated profile page.
- Framework: Next.js (App Router) with React
- Language: TypeScript
- Database: MongoDB via Mongoose
- Auth: JWT (jsonwebtoken, bcryptjs for password hashing)
- File Storage: Cloudinary
- Email: Nodemailer
- UI: Tailwind CSS, Radix UI primitives, shadcn-style components
- Data Fetching/State: TanStack Query, TanStack Table
- Forms/Validation: React Hook Form, Zod
app/(auth)— login, registration, and password reset pagesapp/(dashboard)— admin and writer dashboard pages (orders, payments, writers, profile)app/api— REST-style API routes for auth, orders, writers, and notificationscomponents/dashboard— dashboard UI (topbar, order tables/detail views, etc.)models— Mongoose schemas (User,Order,Notification)services— client-side service functions that call the API routeslib— shared utilities (Mongoose connection, JWT helpers, mailer, notifications, validations)
This project is licensed under the MIT License. Feel free to use, modify, and distribute it as per the license terms.