The challenge
What needed fixing
A portfolio should load fast on a phone, read well without JavaScript, respect people who prefer reduced motion, and not leak anything: no third-party scripts, no cookies, no analytics. It also had to be simple to deploy: a zip uploaded to shared hosting, with no build step.
My approach
What I did, in order
Static files only
Every page is plain HTML with real text, three CSS files and a few small JavaScript modules. No framework, no server-side code, no database. Fonts are self-hosted so nothing is fetched from third parties.
Background scene that never blocks the page
The particle scene (one three.js Points object with a custom shader, morphing between formations as you scroll) is lazy-loaded after the page is interactive. If motion is reduced, WebGL2 is unavailable, data saver is on, or the device is weak, a still image shows instead, and the text never waits for it.
Strict Content Security Policy
Scripts, styles, fonts and images are same-origin only. There is no unsafe-inline: the two inline scripts (theme bootstrap and the import map) are allowed by SHA-256 hashes. frame-ancestors is none, base-uri and form-action are self.
Transport and browser hardening
HTTPS is forced with a single 301 (www redirects to the apex), HSTS is set for a year with subdomains, plus X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy and Cross-Origin-Opener-Policy. A security.txt is published under /.well-known/.
No cookies, no trackers
The site sets no cookies and loads no analytics or embeds. The only stored value is the light/dark choice in localStorage, on your device.
Caching without stale files
Static assets and pinned libraries cache for a year. Site CSS and JavaScript URLs, including the import map that resolves every module, carry a version that changes on each deploy, so returning visitors never mix old and new files.
Accessibility
One h1 per page, semantic landmarks, a skip link, visible focus rings, 44px tap targets, keyboard-operable toggles, and AA contrast in both themes. The reveal animations have a failsafe so content can never stay hidden.
Architecture
Sanitized diagram
Results
What changed
Runs with JavaScript disabled and with reduced motion
No third-party requests, cookies or trackers
Lighthouse (local run): Accessibility, Best Practices and SEO 100; Performance 90+ on the home page
What I learned
Takeaway
The same rules that protect a clinical network apply to a personal site: default to same-origin, fail safe, version what you cache, and make every claim verifiable from the outside.
Tools used
Tools used
- HTML5
- CSS custom properties
- JavaScript modules
- three.js
- GSAP ScrollTrigger
- Apache/LiteSpeed .htaccess
Contact
Want the full story?
Happy to walk through the details, the trade-offs, and what I would do differently.