008

Developer Portfolio Template

£15 View live demo or the whole Vault, £79.20

A one-page portfolio for a solo engineer, built around a workbench panel where each snippet types itself out character by character while the preview beside it builds, then runs the exact code you just read.

ScrollTrigger Lenis intermediate
8 more details
typewriterlive-previewtext-animationcursor-effectsphysicsscroll-revealstaggerclick-toggle

Updated

About this template

A production-ready one-page site for solo developers, freelance engineers, and technical contractors, art-directed away from the usual dark terminal portfolio: a warm graphite ground, raised panels, one ember accent, bundled project photography graded to match, and a high-contrast serif carrying the headlines instead of the monospace every other developer site reaches for.

Read the full template overview

The signature is the workbench. Each of three snippets is split into characters and typed out by a single tween, the preview beside it assembles as the typing passes marked milestones in the code, and on completion the demo runs the same animation the snippet describes, so the panel is a live thing rather than a screenshot.

Around it sit a masked hero reveal, a spec strip of real working detail, project entries with a headline engineering metric each, and a notes list. Swap the placeholder name, projects, and snippets for your own and deploy anywhere as static files.

Developer Portfolio Template - website template preview

What's included

12 items
  • Complete deployable one-page site: nav, hero with spec strip, workbench, selected work, approach, notes, contact, footer
  • Signature workbench: code types itself character by character while the preview builds alongside it, then runs the exact animation shown
  • Preview milestones driven by data-step attributes on the code lines, so the stage assembles in time with the typing
  • Three self-contained demos (stagger grid, orbit with function-based values, bounce ease) with previous, next, and replay controls
  • Typing starts when the workbench scrolls into view, so the moment is seen rather than missed
  • Hero headline pushes back under the cursor, character by character, turning the page's claim about interfaces behaving like objects into a demonstration in the first viewport
  • Add your own demo by copying one markup block and adding a matching entry to the RUNNERS map
  • Project entries pairing bundled graded photography with a written description and a single headline engineering metric
  • Photography ships as optimised WebP derivatives with the warm grade baked into the pixels, regenerated from a manifest, total weight around 100KB
  • Serif display type against monospace data, inverting the usual developer-portfolio pairing
  • Lenis smooth scrolling wired in and fully optional, with the code panels excluded so they scroll natively
  • Accessible: real buttons throughout, visible focus, reduced motion gets the finished code and a static preview, and without JavaScript the first demo shows its full snippet and completed preview

Perfect for

5 use cases
  • Solo developer, freelance engineer, and contractor portfolios
  • Technical consultants who need to show craft rather than describe it
  • Engineers applying for roles where the site is part of the application
  • Open-source maintainers presenting a body of work
  • Learning how to build a typewriter effect that drives a live preview rather than decorating text

How it works

4 sections

The typing workbench

One script initialises each section with a single setup and teardown path and one motion branch, skipping any section it cannot find. The workbench splits each snippet's text nodes into per-character spans once at startup, recording which character index completes each line marked with data-step. A single tween then drives an index from zero to the character count: on each update it reveals the newly passed characters, applies any step classes the preview is waiting on, and moves a caret to the last revealed character using its offset position.

Running what was typed

On completion the snippet's entry in the RUNNERS map builds the real GSAP timeline, so what runs is what was typed. Switching demos kills the running timeline, clears the inline properties it left behind, and retypes the new snippet.

The headline distortion

The hero headline adapts the text-hover-distortion effect: text nodes are split into per-character spans in place, so inline markup keeps its styling, and characters near the cursor are pushed away, and the push fades the further a character sits from it. Words are kept whole so per-character inline-blocks cannot break a line mid-word, the split waits until the intro reveal has finished, so character positions are never read while the text is still moving, and a visually hidden copy of the heading keeps one clean string for assistive tech.

When typing is off

Characters are visible by default and hidden only while typing is active, which means reduced motion and a JavaScript failure both leave the full snippet readable, with the preview showing its finished composition via CSS rather than script.

Plugins ScrollTrigger
Difficulty Intermediate
Smooth scroll Lenis integration
Includes HTML + JS + CSS source, documentation, AI setup prompt, lifetime updates

Lighthouse, as measured

Google Lighthouse on this template's demo, from the latest scan. A measurement of the demo as shipped, not a promise for your page.

Accessibility
100
Best practices
100

No performance score, on purpose. That figure depends on how you deploy: your server's compression and caching, your CDN, the connection and the device doing the test, none of which the code controls. The same page can score very differently on two consecutive runs, so measure it where it will live.

Questions about this template

Does the workbench run real code or is it a video?

Real code. Each snippet types itself out character by character, the preview builds alongside it driven by data-step attributes on the code lines, and then it runs the exact animation you just read. Nothing is prerecorded, which is the whole argument the section is making.

Can I add my own demos to the workbench?

Yes, and it is designed for it. Copy one markup block for the code and preview, then add a matching entry to the RUNNERS map in the script. Three demos ship (stagger grid, orbit with function-based values, bounce ease) as working examples of the shape.

What does someone see if they arrive with JavaScript off?

The first demo shows its complete snippet and its finished preview rather than an empty panel. Under reduced motion you get the finished code and a static preview too. The section never renders as a blank stage waiting for an animation that will not come.

I am not a GSAP developer. Is this still usable?

Yes, though it flatters people who write front-end code. The demos are self-contained and swappable for whatever you want to show, but the section is built around showing craft rather than describing it, so it suits engineers and technical consultants more than a generalist CV.

Will the typing animation have finished before anyone scrolls to it?

No, it waits. Typing starts when the workbench scrolls into view rather than on page load, so the moment is actually seen instead of having already happened by the time a visitor arrives.

Paid template

Purchase to unlock the code.

Buying Developer Portfolio Template opens the HTML, CSS and JavaScript source, the full documentation, an AI setup prompt for your editor, and every update we ship to it. Standard license: unlimited personal and commercial projects. Every paid product is tested for desktop and mobile layouts, reduced-motion handling, animation cleanup and keyboard controls wherever there is something to operate.

£15 Standard license, unlimited projects

Browse free effects

Or the whole library: the Vault, £79.20, one payment.

Documentation

What's Included

Code snippet omitted: it ships with the download.

No build step. Open index.html and it runs.

Quick Start

  1. Open index.html and replace the placeholder engineer with yourself: name, headline, spec strip, projects, tenets, notes, and contact details.
  2. Update the <title> and <meta name="description">, and remove <meta name="robots" content="noindex, nofollow"> when you go live.
  3. Change the workbench snippets to code you actually want to show (see below).
  4. Deploy the folder anywhere that serves static files.

Fonts load from Google Fonts and GSAP from a CDN. To go fully self-hosted, download both and update the tags in <head>.

The Workbench (the signature)

Each demo is one [data-demo] block containing a code panel and a stage. On startup the script splits every snippet into per-character spans and records which character index finishes each line marked data-step. A single tween then drives an index from zero to the character count, revealing characters, firing step milestones, and moving the caret. When it finishes, the demo's real GSAP timeline runs.

Adding or changing a demo

Two places, kept deliberately in sync:

1. The markup. Copy a [data-demo] block and give it a name and a filename:

Code snippet omitted: it ships with the download.

2. The RUNNERS map in script.js, keyed by the data-demo name:

Code snippet omitted: it ships with the download.

Return the tween or timeline so the script can kill it when the visitor switches demos.

Also update the 1 / 3 count in the bench bar.

Code markup

Lines are <span class="ln">, with token spans inside: .tok-fn, .tok-str, .tok-num, .tok-prop, .tok-punc, .tok-key, .tok-com. Indentation is real spaces inside the .ln, which preserves them without needing a <pre>.

data-step="1" and data-step="2" on a line tell the stage to add .step-1 or .step-2 when the typing passes that line. The stylesheet uses those to bring preview elements from hidden, to ghosted, to solid, so the picture assembles in time with the code. Add more steps by extending the CSS rules; the script applies any step number it finds.

Keeping the demos honest

The point of the panel is that the code shown is the code running. When you change a snippet, change its runner to match. If the two drift apart, the section quietly stops being the thing that sells the page.

Headline Distortion

The hero headline ([data-distort]) pushes back under the cursor: characters near the pointer are displaced by an amount that falls off with distance, then settle. It makes the page's claim about interfaces behaving like objects true in the first viewport, rather than only asserting it.

Tune it at the top of the module in script.js:

  • STRENGTH (22) — how far a character travels when the cursor is on it
  • RADIUS (150) — how far the influence reaches, in pixels

It runs only where it makes sense: motion allowed, and (hover: hover) and (pointer: fine), so touch devices skip it entirely rather than reacting to taps. The split waits for the intro reveal to finish, so characters are measured at rest.

Three details worth keeping if you edit it:

  • Text nodes are split in place, so inline markup such as <em> keeps its element and its styling. Rebuilding from textContent would flatten it.
  • Words are wrapped in .distort-word with white-space: nowrap, because per-character inline-blocks would otherwise let a line break mid-word.
  • The heading keeps a visually hidden copy of its text, and the visible characters are aria-hidden, so assistive tech reads one clean string instead of spelling it out.

Sections & Options

  • Spec strip (.spec): the four label/value pairs under the hero. Real working detail (availability, timezone, stack) does more for a reader than another paragraph of positioning.
  • Projects (.project): each pairs a graded photograph, a written description, and one headline metric. Pick a number you can defend in an interview.
  • Notes (.note): a writing list. Point the links at your posts, or delete the section.
  • Scroll reveals ([data-reveal]): one-time fade-up, batched. Add or remove the attribute on any element.

Photography

The three project images are bundled, optimised WebP derivatives, not hotlinks. The art direction is baked into the pixels: each is desaturated and duotoned to a warm stone tint so mixed source photography reads as one campaign against the graphite ground. Total weight is roughly 100KB.

Swapping in your own

Either replace the files in assets/img/ directly, keeping the same names and a 800 x 560 ratio, or edit assets/img-manifest.json and regenerate:

Code snippet omitted: it ships with the download.

The manifest holds each source URL, the output name, the dimensions, and the grade block (desaturate, tint, brightness, gamma). Per-image brightness compensates for source exposure, which is why the marine shot is set lower than the other two: matching perceived brightness matters more than matching numbers.

If you swap the palette, retint the photography to match, or the images will be the one thing on the page still wearing the old scheme.

Credits

Original photographs from Unsplash, free to use under the Unsplash licence. The shipped files are altered, graded derivatives.

Smooth Scrolling

Lenis is wired in and optional. Remove the CDN tag and the lenis block at the top of script.js to drop it. The code panels carry data-lenis-prevent so a long line scrolls natively inside the panel instead of being swallowed by the smooth scroller.

Accessibility

  • Workbench controls are real buttons with labels, reachable and operable by keyboard.
  • Focus is visible throughout, against the ember accent.
  • prefers-reduced-motion skips the typing entirely: the full snippet is shown and the preview sits in its finished composition, with no loops running.
  • Without JavaScript, all three workbench demos render stacked, each showing its complete snippet and completed preview, and the switching controls are hidden rather than left dead. Characters are visible by default and hidden only while typing is active, so a script failure degrades to readable code.

Palette

One ground, two raised surfaces, one accent. Change this block in :root and the whole site reskins; nothing else in the stylesheet hardcodes a colour.

Code snippet omitted: it ships with the download.

It is warm graphite rather than the cool blue-black that developer portfolios default to, and the code panel separates its tokens by luminance before hue, so a snippet reads as a block instead of as a rainbow.

Pair Ratio Where
Bone on void 15.11:1 body copy
Bone on panel 13.71:1 properties in code
Dim on void / panel / panel-2 9.05:1 / 8.21:1 / 6.30:1 secondary type
Accent-2 on panel 6.12:1 strings
Accent-3 on void / panel / panel-2 6.57:1 / 5.97:1 / 4.58:1 identifiers
Comment on panel 4.86:1 code comments
Accent on void 4.55:1 ember type, ground only

Two rules to keep if you reskin.

--accent is a ground-only text colour. It clears AA on --void at 4.55:1 and fails on both raised surfaces (4.13:1 on --panel, 3.17:1 on --panel-2). Treat ember as an interface colour — the caret, the status dot, borders, focus rings — and reach for --accent-3 whenever you want ember-coloured words on a panel. --accent-deep is a pressed state only; it is below AA on everything.

--comment on --panel at 4.86:1 is the tightest pair on the page and has no headroom. Darkening --panel past #2E2B28, or dimming --comment further, drops the code comments below AA.

Customisation Notes

  • Colour: the token block at the top of style.css is the whole palette; nothing else hardcodes a colour, so swapping that block reskins the site. --void and --accent carry the identity; change those two first. The syntax colours (--accent-2, --accent-3, --comment) are scoped to the code panel, where they mean something. Retint the photography to match (see Photography above).
  • Type: --font-display (Newsreader), --font-body (Manrope), --font-mono (Fira Code). Update the Google Fonts link when you swap them.
  • Sections are independent: the script skips any section it cannot find, so delete what you do not need.

Dependencies

  • GSAP 3.15.0 (core)
  • ScrollTrigger
  • Lenis 1.3.17 (optional)

Worked examples, the events and programmatic API, and the class reference ship with the download, alongside the full source.