Skip to content
AnkitDimri4Public

About

Full-stack developer portfolio built with React, Node.js, Express, and PostgreSQL (Neon). Features a responsive UI, secure contact form with SendGrid email notifications, server-side validation, and persistent database storage to showcase real-world full-stack development skills.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

93 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ankit Dimri — Full-Stack Portfolio

Full-stack software engineer building fast, reliable web & mobile products with the MERN stack, React Native and machine learning.

React Node.js PostgreSQL Lighthouse desktop CI License: MIT

Live preview of Ankit Dimri's portfolio — click to open the site

Click the preview to open the live site · API on Render: https://portfolio-backend-ie6f.onrender.com


Highlights

  • Immersive, engineer-themed UI — dark & light themes, a fluid type system and a 12-column layout that uses the full width of laptops and large screens.
  • Hero — the name decodes from binary (hover it to see the initials A D as 01000001 01000100), a 3D code-editor card with parallax layers, and a node network that reacts to the cursor.
  • Live data — GitHub commits/repos and LeetCode stats fetched server-side, cached, and shown with a "synced X min ago" indicator.
  • Scroll storytelling — cards unfold into place, headlines flip up and the tech ribbons react to scroll speed — all compositor-only CSS, with a full reduced-motion fallback.
  • Useful details — certificate cover-flow with drag + lightbox, in-page interactive map of Dehradun, 12-hour IST clock, one-click email copy, accessible contact form.
  • Fast, accessible, SEO-ready — Lighthouse 100 across the board on desktop; Open Graph cards, JSON-LD, sitemap.

Screenshots — new design

Hero, dark theme
Hero · dark
Hero, light theme
Hero · light
About with live stats
About · live GitHub & LeetCode stats
Selected work
Selected work · demo videos
Tech stack bento grid
Stack · bento grid
Certificates cover-flow
Certificates · cover-flow
Contact section
Contact
Full-screen map dialog
In-page full-screen map
Mobile hero and menu
Mobile · hero & menu

Previous design

See the previous version — screen recording & screenshots
Screen recording of the previous design (0:29) — click to play
▶ 29-second screen recording of the previous design — click to open (docs/media/old-design.mp4)

img1 img2 img3
img4 img5 img6
img7 img8 img9

Performance

Lighthouse on the production build, before → after the redesign:

Metric Previous design New design
Performance (desktop / mobile) 89 / 66 100 / ~90
Accessibility 76 100
Best Practices 96 100
SEO 92 100
JavaScript (gzipped, initial) 243 kB + jQuery/Bootstrap 75 kB (+33 kB icons, loaded on demand)
Total page weight 1,918 kB · 50 requests ~250 kB · 15 requests
Largest Contentful Paint (mobile) 6.4 s ~2.9 s

Tech Stack

Frontend Backend Tooling & hosting
React 18 (Create React App) Node.js + Express Vercel (frontend)
Hand-built CSS design system PostgreSQL (Neon) via pg Render (API)
CSS scroll-driven animations SendGrid (email notifications) GitHub & LeetCode APIs
Canvas 2D (hero network) In-memory caching & rate limiting Self-hosted fonts, WebP images
react-icons dotenv, cors Jest + Testing Library, node:test
GitHub Actions (CI on every push & PR)

Project Structure

Portfolio/
├── client/                      # React frontend (Vercel root directory)
│   ├── public/                  # index.html (SEO/meta), fonts, icons, og-image, sitemap, robots
│   ├── src/
│   │   ├── sections/            # Hero, About, Work, Journey, Stack, Certificates, Contact
│   │   ├── components/          # Nav, Footer (+ map dialog), CodeCard, Marquee, NeuralField, ScrambleText…
│   │   ├── data/profile.js      # ← all site content: profile, projects, journey, certificates
│   │   ├── lib/                 # API client (shared fetch cache), scroll-reveal helpers
│   │   ├── context/             # ThemeContext (dark / light, persisted)
│   │   ├── styles/              # global design tokens, scroll "unfold" animations
│   │   └── assets/              # resume PDF, optimised WebP images, certificates
│   ├── vercel.json              # security & caching headers
│   └── package.json
│
├── backend/                     # Node.js + Express API (Render root directory)
│   ├── controllers/             # contact form, GitHub stats, LeetCode stats
│   ├── middleware/rateLimit.js  # per-IP rate limiting (Cloudflare-aware on Render)
│   ├── routes/portfolioRoutes.js
│   ├── lib/contact.js           # contact form validation, honeypot, HTML escaping
│   ├── config/db.js             # PostgreSQL (Neon) pool, verified TLS
│   ├── app.js                   # security headers, CORS allow-list, /health, JSON errors
│   ├── server.js                # loads .env and starts the server
│   └── test/                    # API, contact, rate-limit and stats tests (node:test)
│
├── .github/workflows/ci.yml     # tests + production build on every push and pull request
├── docs/                        # README screenshots and the previous-design recording
└── README.md

To update projects, experience or certificates, edit client/src/data/profile.js — no component changes needed.


Environment Variables

Frontend — client/.env

REACT_APP_BACKEND_URL=https://portfolio-backend-ie6f.onrender.com

⚠️ Every REACT_APP_* variable is compiled into the public JavaScript bundle. Never put tokens or keys in the frontend — GitHub data is fetched by the backend instead.

Backend — backend/.env

PORT=8080
DATABASE_URL=your_neon_postgres_url
SENDGRID_API_KEY=your_sendgrid_api_key
SENDGRID_SENDER_EMAIL=sender@example.com
SENDGRID_RECEIVER_EMAIL=receiver@example.com
# Strongly recommended: a GitHub token with NO scopes (public read only).
# Raises the API limit from 60 to 5,000 requests/hour; without it, shared hosting IPs can hit the limit.
GITHUB_TOKEN=your_github_token
# Optional: comma-separated origins allowed to call the API. When unset, the API allows
# the production site, this project's Vercel preview URLs and localhost (3000 / 5173).
CORS_ORIGIN=https://portfolio-nine-orcin-33.vercel.app,http://localhost:3000

⚠️ Do not commit .env files. They are covered by .gitignore.


Run Locally

Backend

cd backend
npm install
npm run dev        # http://localhost:8080  (npm start for production)

Frontend

cd client
npm install
npm start          # http://localhost:3000

To use the local API during development, create client/.env.development.local with REACT_APP_BACKEND_URL=http://localhost:8080.

npm test                  # client tests (in client/) or API tests (in backend/)
CI=true npm run build     # production build — warnings fail the build, same as Vercel

The backend tests use Node's built-in test runner and never touch the database, SendGrid, GitHub or LeetCode (network calls are mocked). GitHub Actions runs both test suites and the production build on every push to main and on every pull request.


Deployment

Backend → Render

  • Root directory: backend · Build: npm install · Start: npm start · Health check path: /health
  • Set the backend environment variables above (including GITHUB_TOKEN; CORS_ORIGIN only if you use other domains).

Frontend → Vercel

  • Root directory: client · Framework preset: Create React App
  • Environment variable: REACT_APP_BACKEND_URL = your Render URL
  • client/vercel.json adds security headers (anti-clickjacking, nosniff, referrer & permissions policies) and long-term caching for hashed assets.

API

Base URL: https://portfolio-backend-ie6f.onrender.com/api/v1/portfolio

GET /health — liveness check

Served at the root (https://portfolio-backend-ie6f.onrender.com/health), not under the base URL. Returns { "status": "ok", "uptime": 42 } without calling any other service, so it suits uptime monitors and Render's health check.

POST /sendEmail — contact form

{ "name": "Ankit Dimri", "email": "dimri.ankitdimri@gmail.com", "msg": "Hello, I want to connect!" }
{ "success": true, "message": "Message sent and saved successfully" }

Validation: all fields required, valid email (max 150 chars), name max 100 chars, message max 5,000 chars. Rate limited to 5 messages per 15 minutes per IP (429 with Retry-After when exceeded). Visitor input is HTML-escaped in the notification email.

The message is saved and emailed independently: if one of the two fails, the other still delivers it and the visitor gets a success response (so they don't resend and create duplicates). A 500 is returned only when both fail. An optional hidden company field acts as a honeypot: if it is filled in, the request gets a normal-looking success response but nothing is saved or sent.

GET /github — GitHub stats

Public repositories with commit counts, stars, language and last push, plus totalCommits. Fetched server-side and cached for 1 hour. If some counts can't be fetched (e.g. rate limiting), last known values are used; if a total can't be computed reliably, totalCommits is null and partial is true rather than returning an undercount.

GET /leetcode — LeetCode stats

totalSolved, solvedByDifficulty (easy / medium / hard), acceptanceRate and global ranking. acceptanceRate matches the LeetCode profile: accepted submissions ÷ all submissions. Cached for 10 minutes.

GitHub and LeetCode calls time out after 10 seconds. If either service is slow or down, the last good result is served; 502 is returned only when there is nothing cached yet.

Errors are always JSON with a message field and never include stack traces.


Database

Contact messages are stored in the contacts table (PostgreSQL / Neon):

CREATE TABLE contacts (
  id SERIAL PRIMARY KEY,
  name VARCHAR(100),
  email VARCHAR(150),
  message TEXT,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Security

  • No secrets in the frontend bundle or the repository; GitHub access is server-side only.
  • JSON-only errors (no stack traces), X-Powered-By removed, nosniff / frame-deny / referrer headers, CORS allow-list on by default.
  • Contact form: validation, HTML escaping, honeypot, 20 kB body limit, per-IP rate limiting (using Cloudflare's visitor IP on Render); parameterised SQL.
  • Database connections use TLS with certificate verification.
  • npm audit: 0 vulnerabilities in backend dependencies and in the frontend code shipped to visitors.

Author

Ankit Dimri — Full-Stack Software Engineer · 📍 Dehradun, India

GitHub GitHub   LinkedIn LinkedIn   LeetCode LeetCode


Created by Ankit Dimri · © 2024–2026 · MIT License

About

Full-stack developer portfolio built with React, Node.js, Express, and PostgreSQL (Neon). Features a responsive UI, secure contact form with SendGrid email notifications, server-side validation, and persistent database storage to showcase real-world full-stack development skills.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages