A clean, fast, content-first developer portfolio built with Next.js 15, React 19, and Tailwind CSS.
Most portfolio templates are either bloated with carousels and parallax, or so minimal that they feel unfinished. This one aims for a different middle:
- Content-first. Projects, experience, and activity are plain data files — update one file, ship.
- Fast. Static generation, shared-chunk budget under ~105 kB, Lighthouse 95+ across the board.
- Real signals. Live GitHub contribution graph, auto-synced activity feed (GitHub + WakaTime), MDX blog.
- Typed. Strict TypeScript end-to-end. No
anyescape hatches.
- Home / About / Projects / Blog / Activity / Guestbook — six clear pages, each a single data file (or env var) away from yours.
- Featured projects surface on the homepage via a single
featured: trueflag. - Live activity feed pulls commits, PRs, and coding sessions from GitHub + WakaTime (revalidated every 60s).
- Signed guestbook. Visitors sign in with GitHub and leave one public note. Admin can pin + delete.
- MDX blog with syntax highlighting, JSON-LD, and SEO metadata per post.
- GitHub contribution calendar with light/dark themes.
- SEO ready. Sitemap, OpenGraph, Twitter cards, JSON-LD (
Person,WebSite,ProfilePage,BlogPosting). - PWA manifest, proper theme-color meta, and RSS alternate link.
- Dark / light theme with
next-themes(respects system preference, no flash). - Accessibility minded. Reduced-motion respected, focus states, semantic structure.
| Layer | Choice |
|---|---|
| Framework | Next.js 15 (App Router) + React 19 |
| Language | TypeScript 5 (strict) |
| Styling | Tailwind CSS 3 + @tailwindcss/typography |
| UI | Radix UI primitives, lucide-react, Framer Motion |
| Content | MDX via next-mdx-remote, gray-matter for frontmatter |
| Data | GitHub REST API + WakaTime API (server-side, cached) |
| Typography | Space Grotesk |
# 1. Clone
git clone https://github.com/tukesh1/tukesh.in.git
cd tukesh.in
# 2. Install
npm install
# 3. (Optional) set env vars for the /activity and /guestbook pages
cp .env.example .env.local
# - GITHUB_TOKEN raises the GitHub rate limit (10 → 30 req/min)
# - WAKATIME_API_KEY required for coding-session stats
# - AUTH_SECRET + AUTH_GITHUB_* required for /guestbook sign-in
# - UPSTASH_REDIS_REST_* required for /guestbook storage
# 4. Dev
npm run dev # http://localhost:3000The /guestbook page uses GitHub OAuth (via Auth.js v5) and Upstash Redis. Without
these env vars, the page still renders — it just shows a friendly "not configured"
card instead of a form.
- Auth secret — generate one:
openssl rand -base64 32 # paste into AUTH_SECRET - GitHub OAuth App — Settings → Developer settings → OAuth Apps → New.
Callback URL:
https://<your-domain>/api/auth/callback/github(for local dev:http://localhost:3000/api/auth/callback/github). Copy the client id / secret intoAUTH_GITHUB_ID+AUTH_GITHUB_SECRET. - Upstash Redis — create a free database at console.upstash.com/redis,
copy the REST URL + token into
UPSTASH_REDIS_REST_URL+UPSTASH_REDIS_REST_TOKEN. - Admin — set
ADMIN_GITHUB_USERNAMEto your GitHub username to unlock per-message pin/unpin and delete.
| Command | What it does |
|---|---|
npm run dev |
Start the dev server |
npm run build |
Production build (static + SSG) |
npm start |
Serve the production build |
npm run lint |
Run ESLint (next/core-web-vitals) |
src/
├── app/ # Next.js App Router pages (routes only)
│ ├── about/ # /about
│ ├── activity/ # /activity — live GitHub + WakaTime feed
│ ├── post/ # /post & /post/[slug] — MDX blog
│ ├── projects/ # /projects
│ ├── layout.tsx # Root layout, fonts, metadata, theme provider
│ ├── page.tsx # Home
│ ├── not-found.tsx # 404
│ ├── manifest.ts # PWA manifest
│ └── sitemap.ts # Dynamic sitemap
│
├── components/ # Reusable UI
│ ├── about/ # About-page sections (experience, skills, tools…)
│ ├── icons/ # Inline SVG icons (kept small, tree-shakable)
│ └── *.tsx # Header, footer, panel, mdx-content, etc.
│
├── content/ # MDX blog posts
│
├── data/ # ALL content lives here — edit these files to customize
│ ├── siteMetadata.ts # Name, description, social links, SEO keywords
│ ├── projects.ts # Your projects (set `featured: true` to surface on home)
│ ├── experience.tsx # Work history (supports inline JSX for bold / links)
│ ├── skills.tsx # Skill grid
│ ├── tools.tsx # Tool stack
│ ├── certifications.ts
│ ├── socials.tsx # Social icons shown on the home page
│ └── activity.ts # GitHub + WakaTime fetching logic
│
└── lib/utils.ts # cn() helper, formatDate()
See Customization.md for a step-by-step walkthrough.
TL;DR — 90% of what you need to change lives in src/data/:
- Edit
src/data/siteMetadata.ts(name, URL, social links). - Replace
public/assets/profile.png,public/assets/social-banner.png,public/resume.pdf. - Add your projects to
src/data/projects.ts(mark your best 2-3 withfeatured: true). - Update
src/data/experience.tsx,skills.tsx,tools.tsx,certifications.ts. - Drop MDX posts into
src/content/post/. - Deploy to Vercel (recommended) or any Node host.
docker build -t tukesh.in .
docker run -p 3000:3000 tukesh.in
# → http://localhost:3000Any host that runs Node 18+ will work. The easiest path is Vercel:
- Lighthouse 95+ across Performance, Accessibility, Best Practices, and SEO.
- First Load JS budget: ~102 kB shared, ~125 kB on the heaviest route.
react-github-calendaris dynamically imported and client-only so it never blocks the main page.- All images served via
next/image.
Contributions are welcome — see CONTRIBUTING.md. If you're using this template for your own site, a link back in your footer is appreciated but not required.
