Portfolio v2

Portfolio v2

In ProgressWeb Application2024-01Team: 1 people

A personal portfolio with a dark/light theme, bilingual support (PL/EN), an interactive bird guide, and parallax animations. Built on Next.js 16 App Router.

Next.jsReactTSCSS Modules

Project Overview

Portfolio v2 is a complete redesign of my personal website, built from scratch with Next.js 16 and the App Router. The project goes beyond a simple showcase — it introduces three custom-built systems that define the user experience: a theme engine, full internationalization, and an interactive bird guide.

Portfolio hero section in dark mode with parallax mountains
Hero section with parallax layers (dark mode)

Architecture

The application uses the App Router with route groups (landing) and (main)/[lang], Server Components for initial data loading, and CSS Modules for style isolation. Every piece of text is stored in typed dictionaries, keeping the UI fully translatable.

Follower System — interactive bird guide

An animated bird that follows the cursor and acts as a guide through the site. The system is built on useReducer with eight distinct action types controlling a state machine:

  • States: spawning → following → goingToNest → inNest → despawning
  • Tracking: mouse position throttled at 100 ms, smoothed with requestAnimationFrame and configurable easing
  • Direction: automatic left/right flip based on movement vector
  • Sprites: bird-fly.gif (flying) and bird-idle.gif (staying)

Components are split into Spawn (entry point + welcome message), Follower (animation loop), and Nest (home position with messages). The FollowerProvider wraps the main layout so every page has access to the bird context.

Bird follower following the cursor near a nest element
The bird following the cursor toward a nest
Theme System — light / dark with persistence

A fully custom theme engine built with React Context and a priority-based resolution chain:

  1. URL parameter (?mode=light)
  2. localStorage value
  3. System preference (prefers-color-scheme)
  4. Server-side cookie fallback for SSR

An inline ThemeScript runs before React hydration to prevent the flash of unstyled content (FOUC). The chosen theme is stored both in localStorage and in a cookie so the server can render the correct palette on the first response.

CSS custom properties switch between two palettes: dark (navy #0b1e3d) and light (green #10b981), each with an optional high-contrast variant.

Side by side comparison of dark and light themes
Dark and light mode comparison
i18n System — full Polish / English bilingualism

Every string in the application is wrapped in a Localized<T> type, ensuring compile-time safety for both languages. The system is composed of:

  • Middleware — reads Accept-Language and redirects to /pl or /en
  • Dictionary layer — separate modules for common, navigation, sections, and individual pages, loaded with React.cache
  • URL rewritesnext.config.ts maps Polish slugs to internal English routes
  • SEOhreflang alternates generated per page, bilingual OpenGraph metadata

The dictionary approach keeps translations co-located with the feature they serve, while the Localized generic makes it impossible to forget a translation at the type level.

Other Highlights
  • Parallax hero — layered SVG mountains, fog and clouds animated on scroll
  • Contact form — server action with validation, bilingual error messages
  • Project filtering — by status, category, and technology with AND/OR logic
  • Recommendations — bilingual PDF references
  • SEO — per-project meta, hreflang, OpenGraph, canonical URL