Utsav Malla Portfolio - Cursor Repo Note
This file is loaded by Cursor to reduce repeated context and to keep future edits consistent.
Run / Build / Preview
Frontend (project root):
npm run dev(Vite dev server)npm run dev:all(starts backend + frontend locally; requires MongoDB running)npm run build(runstsc, thenvite build, then copies CNAME)npm run preview(previews production build)npm run lint
Backend (backend/):
npm run dev(Express + TS viats-node-dev)npm run build(tsc)npm run seed(re-seeds MongoDB frombackend/src/seed-data/*)
Environment Variables
- Frontend:
VITE_API_BASE_URL(default:http://localhost:4000)VITE_FORMSPREE_ENDPOINT(contact form)
- Backend:
MONGODB_URI(required)PORT(optional, default:4000)CORS_ORIGIN(optional, default:*)
Architecture (high level)
Vite + React frontend renders sections. On mount, Projects, Experience, and Skills fetch data from the Express backend.
If the API request fails, each component keeps using the local fallback arrays in src/data/*.
Data flow diagram
- If backend is failing, components should still display fallback content (so the UI should not be blank)
flowchart LR
ProjectsUI[React Components (Projects/Experience/Skills)] -->|fetchProjects()/fetchExperience()/fetchSkills()| ApiClient[src/api/client.ts]
ApiClient -->|GET /api/projects| ProjectsRoute[backend/src/routes/projects.ts]
ApiClient -->|GET /api/experience| ExperienceRoute[backend/src/routes/experience.ts]
ApiClient -->|GET /api/skills| SkillsRoute[backend/src/routes/skills.ts]
ProjectsRoute --> ModelsProjects[Mongoose ProjectModel]
ExperienceRoute --> ModelsExperience[Mongoose ExperienceModel]
SkillsRoute --> ModelsSkills[Mongoose SkillModel]
ModelsProjects -->|json| ProjectsUI
ModelsExperience -->|json| ProjectsUI
ModelsSkills -->|json| ProjectsUI
Seed[backend/src/scripts/seed.ts] -->|insertMany| ModelsProjects
Seed -->|insertMany| ModelsExperience
Seed -->|insertMany| ModelsSkills
Fallback[src/data/*] --> ProjectsUI
Key Files (source-of-truth)
Frontend:
src/api/client.ts(definesAPI_BASE_URLandfetchProjects/Experience/Skills)src/components/Projects/Projects.tsx(uses fallbacksrc/data/projects.ts)src/components/Experience/Experience.tsx(uses fallbacksrc/data/experience.ts)src/components/Skills/Skills.tsx(uses fallbacksrc/data/skills.ts)src/data/projects.ts(shape:Project)src/data/experience.ts(shape:ExperienceItem)src/data/skills.ts(shape:Skill)
Backend:
backend/src/index.ts(Express app + routes mount points)backend/src/routes/projects.tsbackend/src/routes/experience.tsbackend/src/routes/skills.tsbackend/src/models/*(Mongoose schemas)backend/src/scripts/seed.ts(deletes + re-inserts from seed arrays)backend/src/seed-data/*(seed arrays)
Conventions to follow
- TypeScript is
strict: trueintsconfig.json. - ESLint is present at the root; extend it when needed rather than disabling rules.
- Keep React components simple: fetch on mount with
useEffect, store in local state, and keep the fallback arrays insrc/data/*. - Maintain API contract compatibility:
Projectfields:id,title,description,image,imageAlt,linkExperienceItemfields:title,duration,responsibilities[]Skillfields:name,proficiency
Recommended Cursor Workflow (prompt checklist)
When you ask Cursor to make a change, include:
- Goal/behavior (what should happen)
- Expected file(s) to edit (front vs backend, and which section)
- API contract details (endpoints + response shape) if it affects data
- Fallback impact (should
src/data/*be updated, and should seed data be updated?) - Acceptance checks:
- Which component(s) should change
- What to verify (browser render + API responses, if applicable)
Tip: Ask Cursor to “summarize the impact before editing” to reduce unnecessary diffs/tokens.
Common tasks
-
Add a new project card:
- Update
src/data/projects.tswith a newProjectobject - Update
backend/src/seed-data/projects.tswith matching fields - Add the image into
public/images/and ensure theimagestring matches the public path - Verify
Projects.tsxrenders the new card and the link behavior works as expected
- Update
-
Update skills/experience:
- Update both
src/data/skills.ts(orexperience.ts) andbackend/src/seed-data/skills.ts(orexperience.ts) - Keep field names consistent with the Mongoose models
- Update both
-
Debug “data not showing”:
- Check frontend
VITE_API_BASE_URL(defaults tohttp://localhost:4000) - Confirm backend routes work:
GET /api/projects,/api/experience,/api/skills - If backend is failing, components should still display fallback content (so the UI should not be blank)
- Check frontend