Personal Portfolio
Personal portfolio for Shashank Kumar Singh — Full-Stack & DevOps Engineer. Dark "gym steel" visual theme, scroll-driven home page, and a Projects section that syncs itself from GitHub.
Stack: Next.js 15 (App Router) · React 19 · TypeScript · Tailwind CSS v4 · Framer Motion · shadcn/ui · Zod · Resend Hosting: Vercel
Getting started
npm install
npm run dev # http://localhost:3000
Scripts
| Command | What it does |
|---|---|
npm run dev | Dev server with hot reload |
npm run build | Production build |
npm start | Serve the production build locally |
npm run type-check | tsc --noEmit |
npm run lint | ESLint over the whole repo |
npm run format | Prettier, write mode |
npm run format:check | Prettier, check mode (what CI runs) |
Environment variables
All optional — the site builds and runs without any of them.
| Variable | Effect if unset |
|---|---|
RESEND_API_KEY | Contact form accepts submissions but only logs them; no email is sent. |
GITHUB_TOKEN | GitHub API calls stay unauthenticated (60 req/hour instead of 5,000). |
Copy .env.example to .env.local to set them for local development.
Project structure
src/
├── app/ # Next.js App Router
│ ├── (site)/ # Route group: every page with nav + footer chrome
│ │ ├── layout.tsx # the chrome itself
│ │ ├── page.tsx # home
│ │ ├── about/
│ │ ├── achievements/
│ │ ├── contact/
│ │ ├── experience/
│ │ ├── projects/ # index + [slug] detail, both GitHub-driven
│ │ └── skills/
│ ├── api/contact/route.ts # POST handler for the contact form
│ ├── layout.tsx # root shell: fonts, metadata, JSON-LD
│ ├── robots.ts # /robots.txt
│ └── sitemap.ts # /sitemap.xml
│
├── components/
│ ├── ui/ # shadcn/ui primitives (button, card, badge, …)
│ ├── layout/ # SiteNav, NavOverlay, NavItem, Footer, MusicBubble
│ ├── common/ # Section, StatCounter, Magnetic
│ ├── home/ # the home page's scroll-driven acts
│ ├── projects/ # GitHub repo cards, README renderer, skeletons
│ ├── skills/ # SkillPlates
│ └── charts/ # hand-rolled SVG charts (no chart library)
│
├── content/ # all copy and data, validated by Zod at load
│ ├── site.ts # identity, nav, SEO defaults
│ ├── skills.ts
│ ├── experience.ts
│ └── achievements.ts
│
├── hooks/
│ └── use-magnetic.ts # cursor-following hover physics
│
├── lib/
│ ├── github.ts # GitHub REST client (1h ISR cache)
│ ├── seo.ts # per-page metadata + JSON-LD
│ ├── utils.ts # cn(), formatDate()
│ └── validators.ts # Zod schemas — source of truth for data shapes
│
└── styles/
├── globals.css # entry point; imports the three partials below
├── theme.css # design tokens (@theme + CSS custom properties)
├── base.css # element defaults, scrollbar, body texture
└── utilities.css # .steel-plate, .gym-shadow, .nav-fab, …
Conventions
@/maps tosrc/. Use it for cross-folder imports; relative paths only within the same folder.- Components are
.tsx, styles are.css. No CSS-in-JS files. Static styling lives insrc/styles/; inlinestyleobjects are reserved for values driven by Framer Motion, which CSS cannot express. - Content never lives in components. Copy and data go in
src/content/, behind a Zod schema, so a bad value fails the build instead of the page. - Tailwind v4 is configured from CSS. There is no
tailwind.config.ts— tokens are declared insrc/styles/theme.css.
How the pages work
Home is three scroll-driven acts stacked with no gaps:
AboutSection— the hero recedes while a green panel rises over it across a 200vh sticky scroll (CinematicTransitionorchestrates it).SelectedWork— a dark cap slides away to reveal the work index.ContactCta— a black panel takes over before the footer.
Projects reads the GitHub REST API rather than a hand-maintained list. Public, non-forked, non-archived repos are shown newest-push-first, and each detail page renders that repo's README. Responses are cached for an hour, so pushing to GitHub updates the site without a redeploy.
Contact posts to /api/contact, which validates with Zod and sends the
message through Resend. There is no database and nothing is written to disk —
Vercel's filesystem is read-only.
Editing content
| To change… | Edit |
|---|---|
| Name, email, socials, SEO | src/content/site.ts |
| Nav menu / sitemap | src/content/site.ts → navigation |
| Skills and levels | src/content/skills.ts |
| Work history | src/content/experience.ts |
| Certifications and awards | src/content/achievements.ts |
| Colours and fonts | src/styles/theme.css |
| Resume PDF | public/Shashank_RESUME2025.pdf |
Adding a page? Create it under src/app/(site)/, then add it to navigation
in src/content/site.ts — the side nav, overlay nav, footer and sitemap all
pick it up from there.
Deployment
Vercel builds from main. vercel.json sets the region, security headers, the
/resume redirect, and the contact function's timeout; everything else is
inferred from the framework.
CI (.github/workflows/ci.yml) runs type-check, lint, format-check and build
on every push and pull request to main.
Known follow-ups
src/content/site.tspointsseo.ogImageat the profile photo. Replace it with a purpose-built 1200×630 card for better link previews.- The ambient audio in
public/audios/is a copyrighted track; swap it for something licensed before promoting the site widely.