Skip to content

Latest commit

Β 

History

252 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Language Three.js Deploy License

A modern, bilingual, interactive personal portfolio β€” built entirely with HTML, CSS, and vanilla JavaScript, with no framework, no build step, and no bundler.

The deliberate constraint of zero dependencies forced every interactive feature β€” the 3D hero, the aurora background, the command palette, the world map, the film grain overlay β€” to be implemented from first principles. The result is a site that loads in under a second, scores well on Lighthouse, and has no supply-chain risk from third-party packages.

Table of Contents

Preview

Section Dark Light
Hero Hero Dark Hero Light
Projects Projects Dark Projects Light
Education Education Dark Education Light
Volunteering Volunteering Dark Volunteering Light
Places Places Dark Places Light
Contact Contact Dark Contact Light
Changelog Changelog Dark Changelog Light
About About Dark About Light
Privacy Privacy Dark Privacy Light

Features

  • Light and dark mode with fluid transition, persisted via localStorage
  • Bilingual (Italian / English) toggle without page reload β€” driven by data-it / data-en attributes on every text node, with no separate page or route per language
  • Aurora canvas background β€” real-time 2D canvas animation with drifting color blobs that adapt to the active theme via composite blend modes
  • 3D wireframe icosahedron in the hero section built with Three.js, tracking mouse movement
  • Morphing cursor orb β€” a custom element that follows the pointer and continuously morphs its border-radius and hue
  • 3D tilt cards β€” vanilla JS perspective transforms on project and volunteer cards based on mouse coordinates
  • Scroll-reveal animations via Intersection Observers, animated top progress bar, and a navbar that hides on downward scroll
  • Film grain overlay β€” SVG noise texture animated purely in CSS, zero canvas cost
  • Intro screen β€” animated first-visit overlay with a typing effect, shown once per session via sessionStorage, skippable
  • Command palette (⌘K) β€” fuzzy-searchable navigation and quick actions: jump to section, toggle theme or language, copy email, open project links
  • Interactive world map β€” custom Canvas 2D implementation with Natural Earth-derived borders, hoverable countries, and pinned locations (home, university, trips, scout routes)
  • Fully responsive β€” custom mobile menu, fluid CSS grid, and clamp()-based typography
  • Contact form via Formspree with a required privacy-policy consent checkbox
  • Privacy policy pages for both the site (privacy.html) and the companion LifeOS app (lifeos-privacy.html), both bilingual

Work in progress: js/scrollytelling.js implements a Three.js + GSAP ScrollTrigger fly-through sequence with a DEBUG_MODE waypoint editor. This script is not currently loaded by index.html and depends on house.glb plus GSAP/ScrollTrigger/GLTFLoader CDN scripts that are not yet wired in. It is an unfinished feature, not active functionality.

Tech Stack

  • Markup: HTML5 with data-it / data-en localization attributes
  • Styling: CSS3 β€” custom properties, grid, flexbox, clamp(), responsive breakpoints
  • Scripting: Vanilla JavaScript β€” Intersection Observers, Canvas 2D, Web Animations API, sessionStorage, localStorage
  • 3D: Three.js r128 via CDN
  • Icons: Font Awesome 6.5.0 via CDN
  • Typography: Self-hosted Inter and JetBrains Mono via @font-face β€” migrated from Google Fonts to avoid transmitting visitor IP addresses to Google's servers, as noted in the site's own Privacy Policy
  • Forms: Formspree (contact form backend β€” no custom server required)
  • Hosting: Cloudflare Pages β€” every push to main triggers a deploy in approximately 30 seconds

index.html loads the Leaflet CSS stylesheet from CDN, but no Leaflet JS is present and no L.map() calls exist anywhere in the codebase. The world map is a fully custom Canvas 2D implementation. This CSS import is an unused leftover and can be removed.

Design Tokens

Defined in css/tokens.css and consumed as CSS custom properties throughout:

Token Dark Light
Base background #07070A #F8F8FB
Surface #0D0D12 #F1F2F7
Primary text #F5F7FA #0F172A
Accent β€” purple #7c3aed #7c3aed
Accent β€” indigo #4f46e5 #4f46e5
Accent β€” cyan #06b6d4 #06b6d4

Design Decisions

Why no framework or bundler? A portfolio site is a document with progressive enhancement, not an application. Adding React or Vue would mean shipping a runtime, a virtual DOM, and a hydration cost for what is ultimately a set of static sections. Vanilla JS with Intersection Observers and CSS custom properties achieves everything the design requires with a fraction of the payload and zero build-time complexity.

Why self-host fonts? Google Fonts embeds a tracking pixel that transmits the visitor's IP address to Google's servers on every page load. For a site that includes its own Privacy Policy and explicitly describes its data handling, using Google Fonts would be a direct contradiction. Self-hosting via @font-face adds two HTTP requests (woff2 files, cached after first load) with no privacy tradeoff.

Why Cloudflare Pages over GitHub Pages? Cloudflare Pages provides an automatic global CDN, edge caching, and HTTPS with no configuration β€” the same outcome as GitHub Pages but with better latency internationally, which matters for a portfolio viewed by recruiters across different regions.

Why a custom Canvas 2D world map instead of Leaflet? Leaflet is a feature-rich mapping library designed for interactive GIS applications with tile layers, zoom controls, and marker clusters. The use case here is a decorative, non-navigable map showing a handful of personal pins. Loading Leaflet (plus a tile provider) for this would be roughly 200 KB of JavaScript and thousands of tile requests for a purely aesthetic element. The custom Canvas implementation does the same visual job in under 150 lines of code and zero network requests beyond the GeoJSON border data.

Project Structure

mirconegri.com/
β”œβ”€β”€ index.html
β”œβ”€β”€ privacy.html                  # Privacy policy for this site
β”œβ”€β”€ lifeos-privacy.html           # Privacy policy for the LifeOS companion app
β”œβ”€β”€ LICENSE
β”œβ”€β”€ css/
β”‚   β”œβ”€β”€ tokens.css                # Design tokens, theme variables, reset
β”‚   β”œβ”€β”€ light-mode.css            # Light theme overrides
β”‚   β”œβ”€β”€ layout.css                # Scroll progress bar, aurora canvas, sections, footer
β”‚   β”œβ”€β”€ navbar.css                # Fixed navbar and mobile menu
β”‚   β”œβ”€β”€ hero.css                  # Hero section and CTA buttons
β”‚   β”œβ”€β”€ sections.css              # All content sections
β”‚   β”œβ”€β”€ fonts.css                 # Self-hosted @font-face declarations
β”‚   └── extras.css                # Film grain, intro screen, command palette
β”œβ”€β”€ js/
β”‚   β”œβ”€β”€ aurora.js                 # Animated gradient blob background
β”‚   β”œβ”€β”€ threejs-hero.js           # 3D wireframe icosahedron
β”‚   β”œβ”€β”€ orb.js                    # Cursor-following morphing orb
β”‚   β”œβ”€β”€ ui.js                     # Navbar, theme/language toggle, scroll reveal, card tilt
β”‚   β”œβ”€β”€ intro.js                  # First-visit intro overlay
β”‚   β”œβ”€β”€ grain.js                  # Film grain overlay injection
β”‚   β”œβ”€β”€ map.js                    # Custom Canvas 2D world map
β”‚   β”œβ”€β”€ palette.js                # Command palette
β”‚   └── scrollytelling.js         # Not loaded β€” see Features note above
β”œβ”€β”€ fonts/
β”‚   β”œβ”€β”€ inter/                    # woff2 files referenced by fonts.css
β”‚   └── jetbrains-mono/           # woff2 files referenced by fonts.css
└── assets/
    β”œβ”€β”€ CV_Mirco_Negri.pdf        # Linked by the hero "Download CV" button
    β”œβ”€β”€ lifeos-icon.png           # Referenced by lifeos-privacy.html
    └── ...                       # Preview screenshots and GIFs used in this README

Getting Started

Prerequisites

  • Any modern browser
  • A local HTTP server is optional but recommended to avoid any file:// protocol restrictions

Installation

git clone https://github.com/mirconegri/mirconegri.com.git
cd mirconegri.com
open index.html

Or serve locally:

python3 -m http.server 8000
# then open http://localhost:8000

No build step, no npm install, no compilation.

Usage

  • Live: mirconegri.com
  • Local: open index.html directly or via a local server as shown above

Deployed via Cloudflare Pages connected to this repository. Every push to main triggers an automatic deploy.

Configuration and Environment

No .env file and no build-time environment variables. The only runtime integration points are:

Item Location Notes
Formspree endpoint index.html β€” <form action="https://formspree.io/f/xpqedpyo"> Tied to the author's Formspree account β€” replace the endpoint ID to reuse the form
CV file assets/CV_Mirco_Negri.pdf Linked by the hero "Download CV" button β€” replace with your own file at this path
LifeOS icon assets/lifeos-icon.png Referenced by lifeos-privacy.html

Contributing

This is a personal portfolio, but bug reports and suggestions are welcome:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/your-feature)
  3. Commit your changes with a clear message
  4. Open a Pull Request

For broken links or layout issues, open an Issue.

Author

Mirco Negri β€” Computer Science @ UniTrento

Portfolio GitHub LinkedIn Gmail

License

This project is licensed under the MIT License β€” see the LICENSE file for details.