Overview
KarlHorning.dev is my centralised developer portfolio — a single, accessible Next.js build that replaces the need to maintain separate stacks. It brings together my projects, writing, and CMALT portfolio in one modular codebase, built with the same care I apply in a production environment.
It's a custom-built portfolio and blog designed to showcase my work as a Full-Stack JavaScript/TypeScript Developer and Learning Technologist. The site prioritises accessibility, performance, and maintainability, supported by consistent documentation and strong TypeScript typing.
I rebuilt the site while preparing my CMALT portfolio. I wanted something easier to read, more maintainable, and reflective of both my technical and educational background. My previous site lacked a dedicated Projects section, and this rebuild gave me the opportunity to include one — alongside a full blog and case study framework.
Tech Stack
- Framework: Next.js 15 (App Router)
- Language: TypeScript (strict mode)
- UI: React 19 + Tailwind CSS
- Tooling: ESLint + Prettier (Tailwind plugin)
- Icons: React Icons
- Image Optimisation: Sharp
- Testing: Playwright + axe-core for end-to-end accessibility
- Deployment: GitHub Pages (static export)
- Accessibility: WCAG-aware design, semantic HTML, ARIA-friendly components
CI/CD: GitHub Actions runs type checks, linting, build, Playwright accessibility tests, and next export
on push to main
, then deploys automatically to GitHub Pages. Workflows include a composite Node setup/cache action and a Pages deployment pipeline.
Key Skills Demonstrated
- Front-end architecture: Next.js 15, React 19, TypeScript
- Styling and accessibility: Tailwind CSS, WCAG 2.2 AA, semantic HTML, ARIA
- Performance and accessibility testing: Playwright + axe-core, Lighthouse, and static export
- Documentation and consistency: TypeScript + JSDoc, predictable structure
- Maintainability and quality: ESLint, Prettier, CI/CD automation
- Deployment and scalability: GitHub Pages static deployment, JSON-based data
Design Approach
The design focuses on clarity, accessibility, and tone rather than visual noise. Typography and spacing follow a grid-based rhythm, with a restrained colour palette supporting both light and dark modes.
Animations are minimal — for example, the logo includes a subtle CSS glitch hover effect to add personality without distraction. All layouts are mobile-first and responsive, optimised for readability across devices.
Page Structure
The site is divided into structured, component-driven sections for easy maintenance and future scalability.
Home
A focused introduction with clear navigation and recent projects.
About
- Values Grid: Highlights inclusive design, calm collaboration, and developer experience.
- Technology Stack: Displays key technologies with consistent iconography.
- Certifications: CELTA, PTLLS, Apple Teacher, Scrum Fundamentals.
- Experience Timeline: Roles at Imperial College London and freelance work.
Projects & Case Studies
Showcases case studies with technologies and links. Each card is dynamically generated from JSON typed with ProjectMeta
.
For example, see my detailed backend case study: Learnlight Platform & Mobile Apps.
CMALT Portfolio
A structured portfolio following the CMALT framework, linking to evidence documents, media, and reflections.
Contact
A minimal, accessible contact page with form, social links, and JSON-LD structured data for SEO.
Accessibility affordances are baked into the layout: a visible “Skip to content” link, and the main content wrapped in <main id=“main”>
for keyboard and assistive tech users.
Architecture and Data Model
The codebase follows a clear separation of concerns between content, types, and logic.
- Constants under
lib/constants/
(assets, links, SEO, icons) - Shared types in
src/types/ui.ts
- Concise JSDoc annotations ensure every dataset is self-documented.
This structure makes the site predictable, modular, and easy to extend.
Content Architecture
A content-first approach stores data in JSON and TypeScript constants, making it portable and predictable.
- Blog posts in
public/data/posts.json
typed withBlogPost
. - Dynamic tag and search generation.
- Projects follow the same structure for reusability.
By centralising content, I maintain static generation for GitHub Pages and eliminate the need for a separate Eleventy site.
Migrating from Eleventy to Next.js
I migrated from Eleventy (11ty) to Next.js to simplify the stack and unify my blog and portfolio under React components. The site remains fully static thanks to a JSON-based data layer and next export
.
Documentation and Consistency
Each file includes JSDoc annotations describing its purpose and data structure, complementing TypeScript's static analysis.
/** * Centralised collection of external URLs used across the site. */ export const externalLinks: SiteLink = { GitHubLink: "https://github.com/Karl-Horning", PortfolioLink: "https://www.karlhorning.dev", };
Accessibility and Performance
Accessibility is monitored throughout development and on the live site using Lighthouse, WAVE, and Firefox's built-in accessibility tools. The current live score is 100, and a full Lighthouse and accessibility audit is published from the production build.
- Keyboard-friendly navigation
- Proper alt text and ARIA attributes
- High contrast in both light and dark modes
- Static generation for speed and SEO
- Optimised media via Next/Image and Sharp
Lighthouse Performance (Live): Mobile
Performance
97
Accessibility
100
Best Practices
100
SEO
100

Lighthouse Performance (Live): Desktop
Performance
99
Accessibility
100
Best Practices
100
SEO
100
These figures reflect the production environment as of 16 Oct 2025.
In addition to manual and Lighthouse testing, a full-site automated accessibility suite runs with Playwright and axe-core. Each route is rendered in a real browser and scanned against WCAG 2.2 AA criteria, ensuring zero accessibility violations before deployment. Current results: all pages pass with no detected issues.
Privacy, Security & Performance
The site is statically generated for reliability and security, with no user tracking or unnecessary third-party scripts. Assets are optimised using Sharp, and privacy-friendly analytics will be added to measure engagement responsibly.
Scalability and Future Development
The site's modular structure makes it easy to extend with new projects or features. Upcoming work includes adding Jest tests for interactive elements and exploring lightweight analytics for performance insights.
Development currently happens in refresh/2025-design
, with feature and bug branches merged into that branch before PRs to main
, which serves the live site.
Outcome
The finished site is a fast, accessible, and maintainable portfolio that represents both my technical and educational background. It consolidates my online presence, streamlines maintenance, and provides a flexible structure for showcasing projects.
It demonstrates proficiency in modern front-end development, an understanding of accessibility and inclusive design, and a commitment to clean, maintainable code. Ultimately, it reflects my core values: clarity, maintainability, and accessibility.
Consolidating 11ty into a single Next.js codebase reduces maintenance by roughly 2-3 hours per month, while keeping accessibility work and documentation in one place.
Why It Matters
I approach my personal site as I do a client project — with attention to accessibility, structure, and maintainability. Building it this way keeps my skills sharp and demonstrates the standards I apply in professional environments, without unnecessary complexity. It also serves as a living example of my front-end principles in practice.