avlogo
Spider
Home
About
WorkSpace
Contact
Book a Call
avlogo

Aviralyadav Aviralyadav

I'm Aviral - a full-stack developer, freelancer & problem solver. Thanks for checking out my site!

Genral

  • Home
  • About Me
  • Projects

Specifics

  • Guest Book
  • Bucket List
  • Uses

Genral

  • Home
  • About Us
  • Projects

Specifics

  • Guest Book
  • Bucket List
  • Uses

Contact

  • Contact Us
  • Links
  • RSS

© 2025 Aviral Yadav. All rights reserved.

Privacy Policy•Terms of Use
Made withCodeForTravel
All Projects

Curated Work / personal-portfolio

Personal PortfolioPersonal Portfolio

A developer-first portfolio that goes beyond a résumé.

NEXT.JSREACT.JSTAILWIND CSSMONGODBNODE.JSMOTION.DEVNEXT AUTHNODE MAILERVERCELSEO
Visit Live Site
Type
Full-Stack Portfolio
Role
Full-Stack Developer & Designer
Timeline
2024 – Present
Status
Live
Personal Portfolio screenshot 1
Personal Portfolio screenshot 2

Overview

This is the portfolio you're reading right now, built as a real product rather than a static resume. It runs on Next.js 15's App Router with React 19 and strict TypeScript, layered over MongoDB, NextAuth, Nodemailer, and a mix of ogl/three.js WebGL that stays cheap because it only renders when it's actually on screen. Every visible feature — the guestbook, the live GitHub activity graph, the contact flow — is backed by a real database, real OAuth, and shared validation. The whole thing is tuned to hold a 95+ Lighthouse score while still feeling animated and alive, and it's engineered for both classic search crawlers and the newer AI answer engines.

A developer-first, full-stack portfolio that combines refined UI/UX, smooth animations, and practical utility into a high-performance digital presence, optimized for SEO and accessibility.

Key Features

  • SEO-first architecture with semantic HTML and 95+ Lighthouse scores.
  • Secure OAuth authentication via NextAuth (GitHub & Google).
  • Interactive MongoDB-powered guestbook showcasing full-stack capability.
  • Polished UI/UX with smooth Motion.dev animations and scroll effects.
  • Built-in scheduling via Cal.com with automated branded emails.

Why I Built This

Most developer portfolios are a screenshot wall — a grid of projects you can't touch, describing skills the site itself never demonstrates. I wanted mine to prove the claims it makes by being a production application: real GitHub + Google OAuth, a real MongoDB-backed guestbook people can sign, a contact form that actually sends branded transactional email, and a live GitHub contribution graph pulled from the GraphQL API. If the site says I can build full-stack systems, the site should *be* one.

It also had to earn its traffic. A portfolio nobody can find is worthless, so SEO and answer-engine optimization were first-class concerns from day one, not bolted on at the end — and so was performance, because a slow, janky site undercuts every word on it. On top of that, I rebuilt the whole thing from a loose JavaScript codebase into strict TypeScript with a single shared validation layer, because I wanted a codebase I'd actually be comfortable handing a reviewer.

Architecture Overview

The app is App-Router-first: React Server Components are the default and client interactivity is pushed out to the leaves. Tailwind v4 runs CSS-first with no config file, styled-components v6 survives as a few legacy islands behind an SSR registry (which fixes FOUC and hydration mismatches), MDX powers the content layer, and Biome plus ESLint keep it honest. Heavy WebGL and the guestbook are the only large client boundaries — everything else renders on the server.

app/
  layout.tsx            # metadata API + JSON-LD + fonts + providers
  page.tsx              # RSC home; client leaves for WebGL
  work/[slug]/page.tsx  # SSG case-study pages (generateStaticParams)
  api/
    og/route.tsx        # edge dynamic OG card (ImageResponse)
    comments/route.ts   # guestbook: auth POST + Mongoose populate
    messages/route.ts   # contact: Zod + rate-limit + Nodemailer
    github/contributions/route.ts
    auth/[...nextauth]/route.ts
  robots.ts  sitemap.ts  rss.xml/route.ts
lib/
  validation.ts   # ONE Zod source (contact + comment schemas)
  github.ts       # cache() + ISR-wrapped GraphQL fetch
  mongo.ts        # MongoClient (adapter) + Mongoose (models)
  auth.ts  projects.ts  sendEmail.ts
components/
  Galaxy.tsx      # ogl shader galaxy (viewport-gated rAF)
  GlobeDemo.tsx   # three-globe (dynamic ssr:false, IO-gated)
  StructuredData.tsx
  • Frontend Next.js 15 App Router with React 19, server-first rendering, motion/react for animation, and two WebGL scenes (an ogl shader galaxy and a three.js/three-globe globe) code-split as `dynamic(..., { ssr:false })` islands.
  • Data layer MongoDB reached through two intentional connections — the native MongoClient promise for the NextAuth adapter and a cached Mongoose connection for the app's own models — plus a server-side `cache()` + ISR wrapper for the GitHub GraphQL feed.
  • Auth NextAuth v4 on the database-session strategy with Google + GitHub OAuth; a session callback wires `session.user.id` through so guestbook comments have stable authorship.
  • Validation A single `lib/validation.ts` Zod module is imported by both the API routes (`safeParse`) and the React Hook Form clients (`zodResolver`), so front-end and back-end validation physically cannot drift.
  • SEO/AEO The Metadata API, a server-rendered JSON-LD `@graph`, hand-tuned robots/sitemap, and an edge dynamic-OG route together make the site legible to both search crawlers and AI answer engines.

Performance Engineering: Viewport-Gated WebGL

The visual identity leans on two continuously-animating WebGL scenes, and naively they're expensive: a full-screen ogl fragment shader in the hero and a three.js globe with animated arcs further down. Worse, the responsive layout renders a second, CSS-hidden copy of the globe for other breakpoints — which, left alone, spins up a whole extra WebGL context that's never even visible. The performance work was mostly about *not running* GPU work rather than optimizing the shaders themselves.

  • Code-split Both scenes load through `next/dynamic` with `ssr:false`, so the shader source and the three.js/three-globe bundle never ship in the server payload or block hydration.
  • rAF gating The galaxy's `requestAnimationFrame` loop is wrapped in start/stop functions driven by an `IntersectionObserver` and `visibilitychange` — scroll it off-screen or switch tabs and the render loop halts completely, with zero visual change when it's back.
  • Second-context kill `GlobeDemo` only mounts the actual `<World>` once its container intersects the viewport (with a 200px `rootMargin`); the hidden responsive duplicate never intersects, so its redundant WebGL context is simply never created.
  • Clean teardown On unmount the galaxy calls `WEBGL_lose_context` and removes its resize and mouse listeners, so navigating away frees the context instead of leaking it.
  • Asset diet Alongside the render work: the favicon dropped from ~1.6MB to ~2.6KB, raster `<img>` tags were converted to `next/image` now serving AVIF, and the duplicate Google Fonts requests were merged into one — together shaving several MB off the critical path.

SEO & Answer-Engine Optimization

I treated discoverability as an engineering surface with three distinct audiences: classic search crawlers, Google's AI surfaces (AI Overviews / Gemini), and standalone answer engines like ChatGPT Search, Perplexity, and Claude. Each one reads the site differently, so each gets an explicit, machine-readable signal rather than being left to infer structure from markup.

  • Structured data A server-rendered JSON-LD `@graph` describes a Person, Organization, WebSite, ProfilePage, and SiteNavigationElement set, cross-linked by `@id`, giving machines an explicit entity graph instead of guessing who the site is about.
  • AEO allow-list `robots.ts` explicitly allows the AI crawlers — GPTBot, OAI-SearchBot, ClaudeBot, PerplexityBot, Google-Extended, Applebot-Extended, CCBot and more — so answer engines are permitted to read and *cite* the site rather than being blocked by a blanket rule.
  • Metadata system A `metadataBase`, a `%s | Aviral Yadav` title template, canonical URLs, a structured keyword set, and per-priority sitemap entries; each `/work/[slug]` case study is statically generated with its own `generateMetadata`, article-type OG tags, and canonical.
  • Dynamic OG An edge `/api/og` route renders a branded 1200×630 `ImageResponse` from `title`/`subtitle` query params, so every page and project gets a unique, lightweight social card instead of reusing one heavy profile photo.

Backend Systems

Behind the animation is a genuine backend. MongoDB stores guestbook comments and contact messages, NextAuth handles identity, Nodemailer sends transactional email over Gmail SMTP, and the GitHub GraphQL API feeds the contribution graph. The theme throughout is defensive: nothing should crash the build, leak PII, or let front-end and back-end validation disagree.

  • Dual DB connections `lib/mongo.ts` exposes a lazily-built MongoClient promise for the NextAuth `MongoDBAdapter` plus a Mongoose connection cached across HMR — built lazily specifically so a missing `MONGODB_URI` can never throw at module-eval time and take down `next build`.
  • Guestbook `/api/comments` requires an authenticated session to POST, supports threaded replies, and uses Mongoose `populate` for author data — including a deliberate `import '@/models/user'` side-effect so the User model is registered and populate actually resolves.
  • Contact `/api/messages` validates with the shared Zod schema, enforces a per-IP in-memory rate limit (5 requests / 10 min), HTML-escapes all user text before it enters email markup, and sends both a branded thank-you and an admin notification; the GET handler is gated to the owner's email because it returns stored PII.
  • GitHub feed `lib/github.ts` wraps the GraphQL query in React's `cache()` plus `next: { revalidate: 3600 }`, so the fully-typed `ContributionCalendar` is de-duped per render and cached for an hour instead of hammering the API on every request.

Key Decisions

  • NextAuth v4 database sessions over v5 — comment authorship depends on a stable `session.user.id` supplied by the MongoDB adapter under the database-session strategy; migrating to v5 would have rewritten that entire path for no user-facing gain, so I stayed on v4 deliberately.
  • One Zod schema over per-layer validation — a single `lib/validation.ts` feeds both the RHF client and the API route, which eliminated a duplicated, subtly-wrong email regex and made front/back drift structurally impossible.
  • Viewport-gating over 'just lazy-load' — lazy-importing a WebGL scene still burns GPU the moment it mounts; gating the actual render loop on visibility (and refusing to create the hidden globe's context at all) was the fix that actually helped battery and scroll smoothness.
  • Dynamic edge OG over a static image — a tiny `ImageResponse` route gives every page and project a unique branded card and keeps a multi-hundred-KB profile photo out of the social payload entirely.
  • Kept styled-components behind an SSR registry over a full rewrite — rather than porting every styled island to Tailwind, I added a StyledComponentsRegistry to fix FOUC and hydration — pragmatic, visually identical, and far lower risk.
  • Strict TypeScript migration over incremental `any` — I rebuilt the JS app under a strict `tsconfig`, isolating only three genuinely heavy WebGL files behind `@ts-nocheck` so the other ~90 files got real type coverage.

What I Learned

  • Performance is mostly about what you don't run — the biggest wins came from never creating a second WebGL context and halting the render loop off-screen, not from micro-optimizing shader math.
  • AEO is real infrastructure now — an explicit JSON-LD entity graph plus a deliberate bot allow-list is the difference between being cited by an answer engine and being invisible to it, and it's worth engineering like any other feature.
  • A shared validation schema pays for itself instantly — the first time a field's rules changed, I edited one Zod file and both the form and the API moved together — no drift, no forgotten second copy.
  • A strict JS→TS migration surfaces latent bugs — typing the codebase exposed dead form state and missing null guards that had only ever 'worked' by luck, which is exactly the kind of thing you want a compiler to catch before a user does.

Tech Stack

NEXT.JSREACT.JSTAILWIND CSSMONGODBNODE.JSMOTION.DEVNEXT AUTHNODE MAILERVERCELSEO

Like what you see?

Explore more work or get in touch.

More ProjectsGet in Touch