Skip to content

Repository files navigation

saad.works

Portfolio site for Saad Nasir — .NET backend & microservices engineer. Static today, structured so dynamic content can be added without reworking the UI.

Stack

Concern Choice
Framework Next.js 16 (App Router), React 19
Language TypeScript
Styling Tailwind CSS v4 (CSS-first config in globals.css)
Animation motion (scroll reveals) + CSS keyframes (hero)
Analytics @vercel/analytics, @vercel/speed-insights
Hosting Vercel (all routes prerender to static HTML)

Local development

npm install
npm run dev      # http://localhost:3000
npm run build    # production build — also runs typecheck
npm run lint
npm start        # serve the production build

Editing content

All copy lives in typed modules under src/content/ — no CMS required. Edit these and the pages update:

File Controls
src/content/site.ts Name, role, tagline, email, location, socials, CV link
src/content/capabilities.ts The "What I help with" cards
src/content/work.ts Case studies — home-page cards + /work/[slug] pages
src/content/experience.ts Work history and education
src/content/skills.ts The grouped skills list in the About section

Adding a case study

Append an entry to the work array in src/content/work.ts. Set featured: true to surface it as a card on the home page (all entries get a /work/<slug> page and an OG image automatically). Structure the copy as problem → approach → outcome; only use metrics that can be stood behind.

Enabling the "Download CV" link

Drop a PDF into public/ (e.g. public/saad-nasir-cv.pdf) and set cvUrl: "/saad-nasir-cv.pdf" in src/content/site.ts. The link is hidden while cvUrl is null. Note: the current résumé references a different GitHub handle and email than this site — reconcile before publishing it.

SEO

  • Per-route metadata + title template in src/app/layout.tsx and each page.tsx
  • src/app/sitemap.ts and src/app/robots.ts (generated at build)
  • JSON-LD: Person + per-case-study CreativeWork
  • OG images rendered with next/og: src/app/opengraph-image.tsx and src/app/work/[slug]/opengraph-image.tsx
  • Canonical URL is derived from site.url — keep it accurate

Deploying to Vercel

  1. Push this repo to GitHub.
  2. In Vercel: New Project → import the repo → framework auto-detects as Next.js → Deploy. No env vars needed.
  3. Analytics: in the Vercel project, enable Web Analytics and Speed Insights (Analytics tab). The scripts 404 locally — that's expected; they only serve on Vercel.
  4. Custom domain: Project → Settings → Domains → add saad.works. At the saad.works registrar, set the records Vercel shows — typically an A record for the apex to 76.76.21.21, or follow Vercel's nameserver option. Add www.saad.works as a redirect to the apex if desired.
  5. After DNS resolves, confirm https://saad.works/sitemap.xml and https://saad.works/robots.txt respond, then submit the sitemap in Google Search Console.

Adding dynamic content later

The content modules are the seam. To move any of them to a database or CMS, replace the file's exported constant with an async function of the same return type and await it where it's consumed (the pages are already async Server Components). A contact form would be a Route Handler at src/app/api/contact/route.ts plus an email provider (e.g. Resend) — the Contact section currently uses a mailto: link and a copy-to-clipboard button.

Theming

Light/dark via a .dark class on <html>. A tiny inline script in the document head sets it from localStorage (falling back to the OS preference) before paint to avoid a flash; ThemeToggle flips and persists it. Palette tokens are defined once in src/app/globals.css.

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages