🔗 Live Portfolio: rajghosh06-dev.github.io/portfolio
A multi-page personal portfolio built with Next.js, React, TypeScript, Framer Motion, and a heavily customized CSS system. The project is designed to present Rishit Ghosh’s academic background, projects, skills, experience, and contact channels in a polished, recruiter-friendly format while keeping content easy to maintain through centralized JSON files.
This is not a generic starter anymore. The codebase has been refactored into a structured portfolio system with:
- a custom floating navbar and SVG brand mark
- light mode, dark mode, and a site-wide experimental Glass Mode
- editable JSON content sources
- reusable page/card/button components
- motion and hover systems across major UI surfaces
- a protected profile-image wrapper for casual download deterrence
The portfolio uses the Next.js Pages Router and a shared MainLayout to provide a consistent shell across all pages. The visual language blends:
- soft grid-and-orb light backgrounds
- darker neon-accented dark mode styling
- glassmorphism as an optional enhancement layer
- animated cards and polished CTA patterns
The overall goal of the project is twofold:
- present a strong personal brand with modern UI polish
- keep the content layer simple enough to edit without touching core source code
The landing page is structured as a high-impact introduction plus supporting proof points. It includes:
- a hero section with positioning statement and CTA buttons
- a professional profile tile with a formal portrait
- a current-education panel with academic status, expected graduation, and skill cloud
- featured project previews
- applied learning and experience highlights
- certifications and workshop cards
- a footer-top Glass Mode beta control
The About page is a structured narrative page that presents:
- introduction and identity
- academic and technical background
- project and portfolio philosophy
- leadership and community engagement
- workflow principles
- personal interests and long-term vision
The Projects page showcases the main build archive with:
- a page-level introduction
- project statistics
- filter chips by project category
- reusable project cards with images, notes, stack, summary, and highlights
The Skills page organizes the technical foundation through:
- grouped skill cards
- academic timeline content
- certifications
- workshop and learning history
The Contact page combines styled platform cards with a custom message composer instead of relying on plain links alone. It presents:
- GitHub
- a custom "Send Message" panel below the cards
Each platform is framed as an intentional contact surface rather than a plain text link list, and the composer adds a direct outreach path that still works within a static GitHub Pages deployment.
The site supports:
- Light mode
- Dark mode
- Glass Mode beta overlay
The theme state is centralized in src/utils/ThemeContext.tsx. It stores user preferences in localStorage and applies global HTML-level state using:
- the
darkclass for dark theme data-glass-mode="true"for Glass Mode
This makes the styling system easy to scale because the CSS can respond to one global source of truth.
Glass Mode is an experimental visual layer controlled from the footer-top beta tile. When enabled, it transforms major surfaces across the site into a frosted-glass aesthetic using:
- semi-transparent layered backgrounds
backdrop-filterblur- brighter border edges
- softened gradient illumination
- hover states with richer highlights
Glass Mode works in both light and dark themes and has its own tuning for contrast and surface clarity.
One of the most important refactors in this portfolio is the move away from scattered hardcoded content. Most editable information lives under:
src/data/content/
This allows content updates without editing page logic or component code.
Current editable sources include:
academics.jsoncertificates.jsonexperience.jsonhome.jsonprojects.jsonskills.json
TypeScript wrapper files inside src/data/ read those JSON files and provide typed exports to the rest of the app.
The project uses a reusable component layer for consistency:
Button.tsxfor CTA variantsContactMessagePanel.tsxfor the custom contact composer and submission logicNavbar.tsxfor navigation and brand identityDarkModeToggle.tsxfor light/dark switchingGlassModeToggle.tsxfor the experimental glass aestheticProjectCard.tsxfor project presentationSkillCard.tsxfor skills presentationFooter.tsxfor footer shell and Glass Mode placement
The contact system is designed around the constraints of a static GitHub Pages deployment.
Why this matters:
- this portfolio is exported with
output: "export" - GitHub Pages does not provide a Next.js backend or API routes
- a normal server-side contact endpoint would not work here
To solve that cleanly, the portfolio uses a hybrid contact flow:
- visitors fill out the custom form on the Contact page
- if Google Forms is enabled and configured, the browser posts the message into the published Google Form response endpoint
- if that handoff does not confirm in time, the portfolio falls back to a prefilled
mailto:draft - if Google Forms is intentionally disabled, the form skips straight to the email-draft backup flow
This means the page can stay visually custom while the data still lands in a real collection system.
The current contact message fields are:
- Full Name
- Email Address
- Subject
- Message
The runtime is controlled in src/data/contact.ts through contactFormConfig.
That config currently stores:
recipientEmailfor the fallback email-draft routegoogleForms.enabledto decide whether Google Forms is the primary routegoogleForms.formIdfor the published Google FormgoogleForms.pageHistoryandgoogleForms.fbzxfor the Google form submission payloadgoogleForms.fields.*mappings for the requiredentry.xxxxxxxxids
The actual UI and submission behavior live in src/components/ContactMessagePanel.tsx.
The page-level integration happens in src/pages/contact.tsx, and the visual system for light mode, dark mode, and Glass Mode is handled in src/styles/globals.css.
Important implementation note:
- Google Forms success is inferred from the submission handoff through a hidden transport frame
- because this is not a first-party JSON API, the success state is practical and reliable for normal usage, but not as authoritative as a dedicated backend response
- the email-draft fallback exists to keep the contact path resilient even if Google does not confirm in time
Framer Motion is used for entry animations, while CSS handles:
- hover lifts
- border glow shifts
- icon motion
- media scaling
- chip and badge reactions
The result is a portfolio that feels active without becoming noisy.
The profile photo on the home page uses a wrapper in src/security/ProtectedImage.tsx to discourage casual image downloading by:
- disabling right-click on the image area
- disabling drag behavior
- disabling standard pointer interaction on the underlying image
- placing a transparent shield layer above the image
Important note: this is a deterrent, not absolute protection. Any browser-delivered image can still be captured by determined users.
- Static-first deployment through GitHub Pages using Next.js export mode
- Motion-rich UI with React, Framer Motion, and a custom CSS-heavy presentation layer
- Theme-aware surfaces across light mode, dark mode, and the experimental Glass Mode
- A custom contact workflow that integrates Google Forms with an email-draft fallback
The global shell is provided by:
Responsibilities:
- attach global CSS
- wrap the app in the theme provider
- set the root HTML attributes
- render the persistent navbar and footer
- mount the custom light-mode background scene
The data system follows this pattern:
JSON content -> typed wrapper -> page/component consumption
Examples:
src/data/content/projects.json->src/data/projects.tssrc/data/content/skills.json->src/data/skills.tssrc/data/content/home.json->src/data/home.ts
This keeps the main UI safer while still allowing fast edits.
Most visual behavior lives in src/styles/globals.css. The file contains:
- theme variables
- navbar styles
- button styles
- page-specific layouts
- shared hover systems
- dark-mode overrides
- Glass Mode global overrides
This portfolio currently relies more on carefully authored CSS than on utility-only styling.
src/
├── components/
│ ├── Button.tsx
│ ├── ContactMessagePanel.tsx
│ ├── DarkModeToggle.tsx
│ ├── Footer.tsx
│ ├── GlassModeToggle.tsx
│ ├── Navbar.tsx
│ ├── ProjectCard.tsx
│ └── SkillCard.tsx
├── data/
│ ├── contact.ts
│ ├── home.ts
│ ├── profile.ts
│ ├── projects.ts
│ ├── skills.ts
│ └── content/
│ ├── academics.json
│ ├── certificates.json
│ ├── experience.json
│ ├── home.json
│ ├── projects.json
│ └── skills.json
├── layouts/
│ └── MainLayout.tsx
├── pages/
│ ├── _app.tsx
│ ├── _document.tsx
│ ├── about.tsx
│ ├── contact.tsx
│ ├── index.tsx
│ ├── projects.tsx
│ └── skills.tsx
├── security/
│ └── ProtectedImage.tsx
├── styles/
│ ├── globals.css
│ └── tailwind.css
└── utils/
├── ThemeContext.tsx
├── animations.ts
├── darkTheme.ts
├── lightTheme.ts
└── PRESET/
Edit:
Edit:
Edit:
Edit:
Edit:
Edit:
Edit:
This file now controls both the visible contact links and the message-composer submission flow.
If you need to update the Google Forms integration:
- publish the responder form
- copy the form id from the public form URL
- copy the
entry.xxxxxxxxids for each field from the form source - update:
googleForms.formIdgoogleForms.pageHistorygoogleForms.fbzxgoogleForms.fields.namegoogleForms.fields.emailgoogleForms.fields.subjectgoogleForms.fields.message
- keep
googleForms.enabledastrue
If you want to force the backup path for testing:
- temporarily set
googleForms.enabledtofalse
Then open:
http://localhost:3000/contact/
That bypasses Google Forms and opens the prefilled email-draft route instead.
If the Google Form structure changes later, re-check the ids because Google can regenerate them after edits.
npm installnpm run devThen open:
http://localhost:3000/contact/
to test the contact experience locally.
npm run lintnpm run buildnpm run startThe project uses:
scroll-behavior: smoothin global CSSdata-scroll-behavior="smooth"on the root HTML element
This prevents the Next.js development warning related to route-transition scrolling behavior.
The home-page portrait is imported from private/ and rendered through a protective wrapper. Public images for project cards and other visual assets live under public/.
The portfolio intentionally avoids a plain boilerplate look. It leans into:
- expressive hero structure
- hover-driven motion
- gradient accents
- frosted surfaces
- glassmorphism as an optional premium layer
The contact system can be tested in two modes:
- Google Forms primary mode:
keep
googleForms.enabledset totrue - Email fallback mode:
temporarily set
googleForms.enabledtofalse
When Google Forms is enabled, the page attempts to submit to the Google form first.
When Google Forms is disabled, or when the Google handoff does not confirm in time, the portfolio opens a prefilled email draft using the configured recipientEmail.
This behavior is especially useful on GitHub Pages because it gives the portfolio a functional backup path without needing a custom backend.
This portfolio is not just a personal website. It is also a structured frontend system built around:
- content modularity
- repeatable editing workflow
- visual experimentation
- recruiter-facing presentation quality
- incremental refinement without rewriting the entire app each time
That combination makes it useful both as a portfolio and as a case study in personal-site architecture.
The project is routinely verified with:
npm run lintnpm run build
If a build shows spawn EPERM in a restricted Windows sandbox, that is an environment restriction rather than a project code issue.
This project is licensed under the MIT License — see the LICENSE file for details.
|
GitHub rajghosh06-dev Code, repositories, and build history |
rajghosh06 Professional profile and networking |
Portfolio Live site Full project archive and design system |
rishitghosh06@gmail.com Best for direct outreach and collaboration |
Built as a structured, evolving portfolio system for Rishit Ghosh.