You have built and deployed a complete full stack application: a React front end, an Express API, a MongoDB database, sign-in, file uploads and a production server. This last lesson turns what you did into habits. It has a checklist you can reuse on every project, a list of the mistakes that most often catch people, and a plan for what to build next.
The checklist
# Before you call it finished
## Security
- [ ] `.env` is in `.gitignore` and was never committed (check with `git log --all -- server/.env`)
- [ ] `JWT_SECRET` is long, random and different from development
- [ ] Every private route uses `protect`, and every query includes the signed-in user's id
- [ ] Passwords are hashed; the hash is never returned
- [ ] Uploads: type, size and file signature are checked, names are random
- [ ] Rate limit on sign-in and sign-up; helmet on; CORS lists only your own site
## Quality
- [ ] `npm test` passes in `server/`
- [ ] The app works on a phone-sized screen and with the keyboard only
- [ ] Empty, loading and error states exist for every list and form
## Production
- [ ] HTTPS works and HTTP redirects to it
- [ ] `/api/health` is watched by an uptime monitor
- [ ] Database backups are on and you have restored one at least once
- [ ] Logs are readable with `pm2 logs`, and contain no passwords or tokens
Run through it before you share any app. A few lines deserve a comment. “.env was never committed” must be checked in the Git history, not only in the current files, because a secret committed once stays in history even after you delete the file. If it ever was, change the secret. “Every query includes the signed-in user's id” is the single most valuable security habit in the course. And “you have restored a backup at least once” turns a hope into a plan.
Mistakes that catch almost everyone
- Forgetting `await`, and then wondering why a value is
Promise { <pending> }or why data is missing. - Mutating state in React (changing an array or object in place) so the screen does not update.
- Missing dependencies in
useEffect, which cause stale data, or new functions in dependencies, which cause endless loops. - Trusting the client: no validation on the server, or taking the user id from the request body.
- Route order in Express:
/:idbefore/stats. - Secrets in Git, or a database open to the whole internet.
- No loading, empty or error states, so a slow connection looks like a broken app.
- Testing only the happy path. Bad input, no token and someone else's data are where the bugs are.
Where each lesson's idea shows up again
It helps to see the course as a few ideas used repeatedly, rather than forty topics. A request has a shape (lessons 1, 5, 9). Middleware is a pipeline (10, 12, 22, 23, 36). Never trust input (12, 17, 18, 23, 36). Data belongs to someone (20, 22, 36). State is replaced, not edited (26, 31, 33). Effects have cleanups (28, 33, 35). The URL is state (29, 33). Failure needs a design (12, 28, 31, 37). When you meet a new library, look for these ideas and you will understand it quickly.
What to build next
# Where to go next
Each idea below uses only what you already built. Do them in this order.
1. **Interview dates**: add `interviewAt` to the Job model and show upcoming ones first on the dashboard.
2. **Delete my account**: a route that deletes the user, all of their jobs and their uploaded files.
3. **Refresh sign-in**: keep the token in an httpOnly cookie instead of localStorage (this needs `cookie-parser`, `credentials: 'include'` and a CSRF plan).
4. **Password reset by email**: a one-time token with an expiry, sent through an email provider.
5. **Tests for the React app**: Vitest and React Testing Library for `JobForm` and `Filters`.
6. **TypeScript**: convert the server first (the models give you the types), then the client.
7. **Docker**: one Dockerfile for the app and a compose file with MongoDB for local work.
8. **CI**: a GitHub Actions workflow that runs `npm test` and `npm run build` on every push.
Each idea uses only skills from this course, in a sensible order. Interview dates add a field, a sort and a screen. Delete my account is a good lesson in cleaning up related data and files, and many places require it by law. Cookies instead of localStorage, password reset by email, tests for React, TypeScript, Docker and CI are the usual next steps in professional work.
Your task
- Run the checklist on your deployed app and tick every line honestly.
- Pick one item from
docs/NEXT-STEPS.mdand build it, with a test. - Write a README for your repository: what it does, how to run it, and which parts you built yourself.
- Teach one lesson of this course to someone else. Explaining is the best test of understanding.
How to check it worked
- Every line of the checklist is ticked, or you have written down why not.
- You have a public, working version of the project and a short README.
Summary
- Use the checklist on every project, and check Git history for secrets.
- Most bugs are the same few mistakes: missing await, mutated state, missing effect dependencies and trusting input.
- Extend the project step by step, with tests, and show it.