
Personal Website
This website shows my works over the years, and represents the culmination of all my knowledge of working with NextJS.
sairamsuresh.is-a.dev
Personal portfolio website — built with Next.js 16, React 19, TypeScript, Tailwind CSS v4, and Firebase.
Overview
A fully server-rendered portfolio showcasing projects, achievements, education, events, VIA (service learning), and certifications. All text content is stored in Cloud Firestore and fetched server-side at build/request time with Next.js's "use cache" API. Similarly, images are fetched from Cloudinary. The animated background is a custom WebGL shader rendered via OGL.
The design is inspired by Apple's Liquid Glass aesthetic — frosted-glass navigation pills, smooth transitions, and a generative CPPN background that adapts to light/dark mode.
Tech Stack
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (App Router) |
| Language | TypeScript 5 |
| Styling | Tailwind CSS v4 + Catppuccin theme |
| UI Components | Radix UI primitives + shadcn/ui patterns |
| Animations | Motion (Framer Motion v12), GSAP |
| Background | OGL (WebGL) — custom CPPN fragment shader |
| Database | Cloud Firestore (content) + Firebase Realtime Database (config) |
| Auth / Admin | Firebase Admin SDK (server-only) |
| Analytics | Firebase Analytics (client-only) |
| Images | Cloudinary |
| Markdown | react-markdown v10 + remark-directive |
Pages
| Route | Description |
|---|---|
/ | Hero / about me |
/projects | Project cards with GitHub, Play Store, App Store, and Drive links |
/achievements | Achievements grouped by year |
/education | School roles and timeline |
/events | Events attended/organised |
/via | VIA (Values In Action / service learning) grouped by year |
/certifications | Certifications obtained |
Each content page fetches its data server-side, renders as a static page with a 1-hour revalidation window, and shows a loading skeleton while the Next.js cache is being rebuilt.
Architecture
app/
├── layout.tsx # Root layout: sticky nav, site background, analytics
├── page.tsx # Home page
├── [section]/page.tsx # One page per content section
└── api/
└── github-readme/ # Server-side proxy for GitHub README fetching
components/
├── custom/ # Feature components (adaptive-menu, card, markdown, …)
└── ui/ # Low-level primitives (sheet, dialog, navigation-menu, …)
lib/
├── server/
│ ├── firebase-admin.ts # Admin SDK init + Firestore/RTDB helpers
│ └── helpers.ts # Data-fetching and mapping functions
└── client/
└── analytics.ts # Firebase Analytics (browser-only)
Rendering strategy
- All content pages are statically pre-rendered at build time (ISR, 1 h revalidate).
- The root layout uses
"use cache"so name/title metadata is shared across pages without redundant Firestore reads. - Cache tags (
portfolio-data,portfolio-{section}-data) allow targeted on-demand revalidation without a full rebuild.
Navigation
AdaptiveMenu renders two entirely separate layouts from a single component:
- Mobile — a full-width glass topbar with a slide-in
Sheetdrawer. - Desktop — a floating glass pill for navigation and a separate pill for social links, both wrapped in a single
hidden lg:flexcontainer.
Markdown in long descriptions
Long description fields in Firestore support standard Markdown plus a custom ::github directive that embeds a live GitHub README preview inline:
::github{repo="Sairam-Suresh/mathx"}
The Markdown component is a React Server Component — only the GithubReadmePreview island (which fetches at runtime) is a client component.
Credits:
- React Bits (For the adaptive background used)