Category: Uncategorized

  • Submitted for the SBW (Revisited) project.

    Coming back to Alf’s

    Some projects only really teach you something the second time you build them. Alf’s Cycles is one of those. Vintage British cycling, top to bottom. I was happy with it when I shipped it, and parts of it still hold up.

    This project is about going back to the same brief with everything I’ve picked up since, and using that to build a stronger version of the same shop. The point isn’t to throw the old one out. The first version is still live, side by side with the new one, exactly so the two can be read together.

    You can compare them here:

    The thing I kept reminding myself, working on this, is that a redesign isn’t about scoring points against your old self. It’s about noticing what you didn’t know to look for last time, and being honest enough to do the work now that you can see it.

    A second read of the original

    Sitting with the old site again, a few things settled into place. The structure was static HTML, with the header, navigation, and footer pasted into every page. That’s not a problem until you want to change something, and then it becomes the only problem. The phone number lived in four files. The footer lived in four files. It was a stack of pages dressed up as a site, and it would have buckled the second the shop wanted anything updated.

    Accessibility had been considered, but considered isn’t the same as tested. I hadn’t run the original against the WAVE checker, hadn’t measured contrast with a tool, hadn’t gone through the alt text image by image. The site was probably mostly fine. Mostly fine isn’t a standard.

    The images on the original were the kind of files you ship when you want to get something live. PNGs at the wrong sizes, photos uploaded straight from a stock library without resizing or converting. The SEO setup was minimal. A title and a description, and not much else. For a brick-and-mortar shop in Keswick, that left a lot of useful signal on the table, especially geolocation.

    None of those are failures. They’re the things you only see clearly once you’ve spent more time reading other people’s code, breaking your own, and learning what the platform actually rewards. That second read became the brief I gave myself for the rebuild.

    What I worked on, and what I learned

    Accessibility, taken properly this time

    This was the area I spent the most time on, and the one where I learned the most. The revisited site opens every page with a “Skip to main content” link so keyboard and screen reader users don’t have to walk through the navigation on every load. Every image on the site now carries descriptive alt text written for the content, not the file. So the wheelie illustration on the homepage is described as an illustrated cyclist mid-wheelie, the Alf’s Cycles mascot, rather than something generic like “logo” or “image.”

    The accessibility statement is a dedicated page linked from the footer, with contact details for anyone who hits a barrier and wants to flag it. Tap targets across the site were checked against the recommended minimum size on mobile, because a lot of cycling customers might be looking at the site one-handed at a bus stop or in a shop doorway.

    What accessibility actually teaches you, more than the specific fixes, is patience. You stop guessing what users need and start asking. You write less clever HTML and more useful HTML. That mindset has changed how I open a new file now.

    ARIA labels, working out where they actually help

    This was a subtler bit of the same work. ARIA is one of those things where doing more isn’t doing better. Slapping aria-label on every element is noisier than helpful, because screen readers then have to talk over your visible content. The revisit went the other way. ARIA labels are used where the visible text on its own doesn’t tell the full story, like icon-only buttons or the navigation toggle on mobile. Everything else inherits its meaning from semantic HTML, which is what the language was designed to do.

    The lesson there is that accessibility tools are at their best when they’re filling specific gaps, not blanketing the page.

    Making the site dynamic with PHP includes

    The original was static HTML. The revisit moves to PHP, and the header, navigation, and footer now live in their own partial files that are included on every page. Update the phone number once, it changes everywhere. Add a menu item once, it appears across the whole site. Change a footer link, you change one file.

    This was the moment the project stopped feeling like a stack of pages and started feeling like an actual website. It’s a small architectural shift, but it changes how you think about everything that comes after it. Components. Separation of concerns. A single source of truth for things that should never be retyped. Learning how to use server side includes properly was easily one of the most valuable bits of this module, and it’s the technique I’ll reach for first on every multi-page brief from now on.

    Contrast and colour

    The red on cream palette is part of the brand and I wanted to keep it. The challenge was that the original had spots where smaller body copy dropped below WCAG AA contrast against the warmer cream tones. It looked fine to my eye, and that was the problem. I’d been judging it by what I could see, not by what a tool would measure.

    I rebuilt the colour tokens in CSS custom properties, then ran every text on background combination through a contrast checker before committing to it. A couple of the lighter greys came up shorter than I expected and got darkened. The palette still reads the same as the brand intended. It just passes the test now.

    Image optimisation, the big one

    This was the single biggest performance lever, and most of the PageSpeed jump traces back to it. Every photo on the site is now served as WebP, sized to the breakpoint that actually needs it rather than shipped at one giant resolution and scaled down by the browser. The wheelie illustration on the homepage went from a PNG to an SVG, which means it stays sharp at any size and loads at a fraction of the file weight. Width and height attributes are now declared on every image so the browser can reserve space and the layout doesn’t shift during load.

    It’s the unglamorous part of web design and it’s also the part that makes the biggest difference. The lesson, properly internalised this time, is that the network is the bottleneck. Every kilobyte you don’t ship is a kilobyte your visitor doesn’t wait for. That goes double for mobile users on patchy signal, which is exactly the audience for a Lake District bike shop.

    SEO, with proper signals

    The head section on the revisit carries a lot more useful information than the original did. A canonical URL so search engines know which version of the page is the real one. Open Graph tags so the site previews correctly when it’s shared on social or in messages. A theme colour so the browser chrome on mobile picks up the brand red instead of defaulting to grey.

    The bigger win, though, is geolocation. The revisited site declares ICBM coordinates, a geo.position pair, a placename of Keswick, Cumbria, and a region code of GB-CMA. This is the metadata that tells a search engine where the shop physically is, which matters enormously for a local business where most of the relevant traffic is going to be people in or near the area searching for “bike shop Keswick” or “bicycle repair Cumbria.” Geolocation was new to me on this project, and it’s the kind of thing I’ll be carrying into every local business brief from now on.

    The keyword strategy was rebuilt to match. Rather than abstract terms, the keywords are now phrased the way someone in the Lake District would actually search.

    A live open or closed status

    The new header carries a small pill that reads Open or Closed based on the current time and day of the week. It’s a tiny piece of JavaScript, but it answers a question the visitor used to have to answer for themselves by finding the hours in the footer and checking their watch. For a brick and mortar shop, this is one of the most useful things a website can do. It’s the difference between “I’ll have to call and check” and “I can pop in now.”

    The script reads the day and time, compares it against the trading hours, and updates the pill accordingly. No frameworks, no libraries, just a small bit of vanilla JS in line with the rest of the site’s approach.

    The 404 page, which took longer than I’d like to admit

    This is the one I struggled with the most, and I want to be honest about that because the struggle is where most of the learning lives. The brief asked for a custom 404 page, which sounds simple. You design a friendly error screen, save it, and you’re done. Except a 404 page isn’t a page in the normal sense. It only exists when the server decides to show it, and the server has to be told.

    The first version of my custom 404 was visually finished and completely useless. It sat in the project folder and nobody ever saw it, because the server was still serving the default white text on black error page for missing URLs. I went round in circles for a while trying to work out why. The fix, when it came, was an .htaccess directive telling the server to use my custom file for 404 responses. Once that was in place, the server started serving the right page, and everything I’d designed actually became visible.

    There were knock on issues. The first time I got it working, my relative links inside the 404 page were broken, because the 404 can be triggered from any URL on the site, and a relative path from “/some/missing/page” isn’t the same as a relative path from the homepage. I had to rewrite all the links inside the 404 to use absolute paths so they’d resolve correctly no matter where the user had landed.

    It’s a small page. It is also the only page on the site that has to work in every possible situation, including the situations you can’t predict. Getting it right taught me more about how the server actually serves files than any of the other parts of this project did.

    A mobile first responsive layout

    The original was responsive in the sense that it didn’t break at smaller widths. The revisited site is responsive in the sense that each breakpoint was designed, not survived. The CSS is written mobile first, with the small screen layout as the base and the wider layouts added as the viewport gets bigger. Particular attention went into the awkward widths between phone and tablet, where the first version had wasted whitespace and orphaned headings sitting on their own lines. The new layout handles those in between widths properly, which is where most of the real world traffic actually lives.

    Smaller details that matter

    A few of the smaller pieces of the project don’t need a section of their own but should be mentioned. The Meyer CSS reset is in place as a clean foundation, so the site isn’t fighting browser defaults. The code is consistently indented, with comments where the logic isn’t obvious. File and folder names are descriptive, lowercase, no spaces. HTML and CSS were both validated and the errors fixed before submission. Each of these is small. Together they’re the difference between a project that works and a project that’s been finished.

    The numbers, before and after

    PageSpeed Insights on mobile for the original site:

    [Upload your “Report from May 12, 2026” PageSpeed screenshot here. The one showing the mod_1 site at 79 Performance, 91 Accessibility, 96 Best Practices, 92 SEO.]

    • Performance: 79
    • Accessibility: 91
    • Best Practices: 96
    • SEO: 92

    PageSpeed Insights on mobile for the revisited site:

    [Upload your “Report from May 14, 2026” PageSpeed screenshot here. The one showing stalineapen.uk/alfs at 97 Performance, 96 Accessibility, 100 Best Practices, 92 SEO.]

    • Performance: 97 (up 18)
    • Accessibility: 96 (up 5)
    • Best Practices: 100 (up 4)
    • SEO: 92 (held steady)

    The performance jump is the one I’m proudest of, and as I mentioned earlier, almost all of it traces back to image optimisation and removing render blocking work. Accessibility climbed because every fix was tested with a tool rather than assumed by eye. Best Practices landing at 100 was the reward for the small disciplines like width and height attributes on every image, secure outbound links, no console errors. SEO held steady at 92, which is fine. The score was already in good shape and the real win there is the geolocation work, which doesn’t show up in a Lighthouse score but matters a great deal in the actual search results.

    What this project actually taught me

    Revisiting your own work is one of the most useful exercises a designer can do. You read your old code the way an editor reads a first draft, with affection but also with the clarity that distance gives you. The fixes are rarely dramatic. Most of them are small, careful, and only obvious once you know what to look for.

    The bigger lesson sits underneath all the specific changes. A website is not a design that happens to be on the internet. It is a system. Maintainable structure through includes. Sensible defaults in the reset and the responsive base. Decisions made on behalf of the person visiting before they ever have to make them. The open or closed pill. The skip link. The tested contrast. The 404 page that actually serves. The geolocation tags that put the shop on the map for search.

    When I started Alf’s Cycles, I was building pages. By the end of the revisit, I was building a site. Most of that difference is invisible from the screen. It’s in the includes, the alt text, the contrast values, the WebP files, the meta tags pointing search engines at Keswick, and the .htaccess line that makes the 404 page work. That’s the part I wanted this revisit to be about, and it’s the part I’ll be carrying forward.

    Both versions are still live, side by side:

    Declaration of AI tools used

    In the spirit of academic transparency, this is a record of where AI tools sat alongside the work on this project. The design decisions, the code, the testing, and the final judgement on what shipped were all my own. The AI tools were used as collaborators and assistants in the way a designer might use Stack Overflow, a tutor, or a writing partner.

    • Claude AI (Anthropic). Used for drafting and shaping written content, including this blog post. Helpful for working through how to explain technical decisions in plain English, and for restructuring paragraphs when my first pass felt cluttered.
    • Claude Code and Claude Code agents. Used during development for quick code review, debugging help, and walking through specific issues like the .htaccess setup for the 404 page. Useful as a second pair of eyes on code I’d already written rather than a replacement for writing it.
    • Google Gemini, including Gemini Flash and Gemini Pro models. Used for cross checking ideas and explanations, particularly around responsive layout patterns and accessibility checks. Sometimes useful for getting a second opinion when one model had given an answer I wasn’t fully convinced by.
    • ChatGPT (OpenAI). Used for drafting and refining specific paragraphs in written content, and occasionally for rewording sentences that weren’t landing the way I wanted them to.

    All AI assisted output was reviewed, edited, and accepted or rejected by me. Where code was suggested by an AI tool, it was read line by line and tested before being committed. Where text was suggested, it was rewritten in my own voice before being published.

    Stalin

  • What is CSS nesting? What are the practical use cases? Is it safe to use now?

    DESI-1206-M01-2025-26-130

    If you’ve ever written CSS, you know the pain. You start styling a navigation menu, and suddenly you’re typing header nav ul li a for the tenth time, wondering if there’s a better way. Spoiler: there is, and it’s called CSS nesting.

    What Actually Is CSS Nesting?

    CSS nesting is exactly what it sounds like – you can nest CSS selectors inside other selectors, creating a hierarchical structure that mirrors your HTML. Instead of repeatedly writing out parent selectors, you group related styles together in one logical block.

    Here’s the thing that surprised me: this isn’t a new concept at all. Developers have been using nesting since 2006 through preprocessors like Sass. What’s new is that it’s now native to CSS – your browser understands it directly, no build tools required.

    A Quick History Lesson (I Promise It’s Relevant)

    Back in 2006, a developer named Hampton Catlin created Sass (Syntactically Awesome Style Sheets). One of Sass’s killer features was nesting. Soon after, Less CSS came along with similar capabilities. For nearly 17 years, if you wanted to write nested CSS, you had to:

    1. Write your styles in Sass or Less
    2. Set up a build process
    3. Compile it back to traditional CSS
    4. Hope nothing broke in the process

    Developers loved nesting so much they were willing to add entire build tools to their workflow just to use it. That tells you something about how useful it is.

    Then, in 2023, CSS nesting finally became native. Chrome, Edge, Safari, and Firefox all added support. No more preprocessors needed (well, unless you’re using Sass for other features like mixins, which is fair).

    The Problem CSS Nesting Solves

    Let me show you with a real example. Here’s how you’d traditionally style a navigation header:

    css

    header {
      background: #333;
      padding: 1rem;
    }
    
    header nav {
      display: flex;
      gap: 2rem;
    }
    
    header nav ul {
      list-style: none;
      display: flex;
    }
    
    header nav a {
      colour: white;
      text-decoration: none;
    }
    
    header nav a:hover {
      colour: #3498db;
    }

    Count how many times “header” appears. Five times! If you later decide to rename header to site-header, you need to find and replace it in five different places. Miss one, and your styles break.

    Now here’s the same thing with CSS nesting:

    css

    header {
      background: #333;
      padding: 1rem;
      
      nav {
        display: flex;
        gap: 2rem;
        
        ul {
          list-style: none;
          display: flex;
        }
        
        a {
          colour: white;
          text-decoration: none;
          
          &:hover {
            colour: #3498db;
          }
        }
      }
    }

    Look at that. You write “header” once, and everything inside is automatically scoped to it. All your header-related styles are in one logical block. If you need to rename it, you change it in one place. That’s it.

    The Ampersand (&) Is Your New Best Friend

    Notice that &:hover in the nested example? That ampersand is crucial to understanding CSS nesting.

    The & symbol represents the parent selector. When the browser sees it, it replaces it with whatever the parent is. So:

    • &:hover becomes a:hover
    • &:focus becomes a:focus
    • &::before becomes a::before

    Here’s a more detailed example:

    css

    article {
      padding: 2rem;
      
      /* Creates: article h1 */
      h1 {
        font-size: 2rem;
      }
      
      /* Creates: article:hover */
      &:hover {
        box-shadow: 0 2px 8px rgba(0,0,0,0.1);
      }
      
      /* Creates: article::before */
      &::before {
        content: "📄";
      }
    }

    Without the ampersand on h1, it creates a descendant selector (article h1). But with the ampersand, it applies the style to the article itself. This distinction is important – I got it wrong the first time I tried nesting and couldn’t work out why my hover states weren’t working!

    Golden rule: Always use & before pseudo-classes (:hover, :focus, :active) and pseudo-elements (::before, ::after).

    Real-World Use Case 1: Semantic HTML Structure

    Let’s say you’re building a section with a header and some articles. Traditionally, your CSS would be scattered all over your stylesheet:

    css

    section { ... }
    section header { ... }
    section header h2 { ... }
    section header p { ... }
    section article { ... }
    section article:last-child { ... }

    That’s six separate selectors for one component. When you need to modify the section, you’re hunting through your entire CSS file.

    With nesting, it’s all in one place:

    css

    section {
      padding: 3rem 1rem;
      
      header {
        margin-bottom: 2rem;
        
        h2 {
          font-size: 2.5rem;
          colour: #2c3e50;
        }
        
        p {
          colour: #7f8c8d;
          font-size: 1.1rem;
        }
      }
      
      article {
        margin-bottom: 1.5rem;
        line-height: 1.6;
        
        &:last-child {
          margin-bottom: 0;
        }
      }
    }

    Everything section-related is together. The visual hierarchy in your CSS matches the HTML structure. When I need to change how sections work, I know exactly where to look.

    Real-World Use Case 2: Responsive Media Queries

    This one’s a game-changer. Traditionally, media queries are scattered throughout your CSS file. You have your base styles at the top, then scroll down to find @media (min-width: 768px) somewhere in the middle, then another media query at the bottom. It’s chaos.

    With nesting, media queries live right next to the styles they modify:

    css

    article {
      padding: 1rem;
      
      h1 {
        font-size: 1.5rem;
        margin-bottom: 1rem;
      }
      
      p {
        font-size: 1rem;
        line-height: 1.5;
      }
      
      @media (min-width: 768px) {
        padding: 2rem;
        
        h1 {
          font-size: 2.5rem;
        }
        
        p {
          font-size: 1.125rem;
          line-height: 1.7;
        }
      }
      
      @media (min-width: 1024px) {
        padding: 3rem;
        max-width: 800px;
        margin: 0 auto;
      }
    }

    Now I can see at a glance: mobile padding is 1rem, tablet is 2rem, desktop is 3rem. The heading grows from 1.5rem to 2.5rem. Everything about this article’s responsive behaviour is in one place.

    When I’m working on responsive design, this saves so much time. No more jumping between different parts of the file trying to remember what changes at which breakpoint.

    Browser Support (It’s Actually Good!)

    Here’s the exciting bit: CSS nesting has excellent browser support as of 2025.

    • Chrome 112+ (April 2023)
    • Edge 112+ (April 2023)
    • Safari 16.5+ (May 2023)
    • Firefox 117+ (August 2023)

    According to Can I Use, we’re looking at over 90% global browser support. For most modern projects, that’s production-ready.

    I checked the Can I Use data myself whilst preparing my presentation, and the support is genuinely impressive. All major browsers adopted it within a few months of each other in 2023.

    When Should You Use CSS Nesting?

    Green light scenarios:

    • Modern web applications targeting 2023+ browsers
    • Internal tools and dashboards where you control the browser environment
    • Projects with defined browser requirements
    • Component-based architectures (React, Vue, etc.)

    Proceed with caution:

    • Public-facing websites with diverse audiences
    • Clients specifically requiring older browser support
    • Projects where you don’t have analytics data on user browsers

    Fallback option: If you need to support older browsers but still want to write nested CSS, use PostCSS with the postcss-nesting plugin. It’ll automatically transpile your nested CSS to traditional CSS during the build process. Best of both worlds.

    Best Practices (Learn From My Mistakes)

    1. Always Use the Ampersand for Pseudo-Classes

    I learnt this the hard way. I forgot the & before :hover once and spent ages debugging why my hover states weren’t working. Don’t be like me.

    css

    /* ❌ Wrong - creates "article :hover" (note the space) */
    article {
      :hover {
        background: red;
      }
    }
    
    /* ✅ Correct - creates "article:hover" */
    article {
      &:hover {
        background: red;
      }
    }

    2. Don’t Nest Too Deeply

    Maximum 3-4 levels. If you’re nesting more than that, your selectors become overly specific and hard to override.

    css

    /* ❌ Too deep - creates incredibly specific selectors */
    main {
      section {
        article {
          header {
            h1 {
              /* This creates: main section article header h1 
                 That's a specificity nightmare! */
            }
          }
        }
      }
    }
    
    /* ✅ Better - flatter structure */
    main {
      section {
        padding: 2rem;
      }
      
      article {
        margin-bottom: 1rem;
      }
      
      h1 {
        font-size: 2rem;
      }
    }

    3. Use Nesting Where It Adds Value

    Don’t nest just because you can. Only nest when it improves organisation and readability.

    4. Keep an Eye on Specificity

    Nesting increases specificity just like traditional nested selectors. main section h1 has the same specificity whether you write it traditionally or nested. Be mindful of this.

    5. Test Across Target Browsers

    Even though support is excellent, always test. I use BrowserStack for cross-browser testing in my projects.

    Common Pitfalls to Avoid

    Pitfall 1: Nesting Too Deeply

    I already mentioned this in best practices, but it’s worth repeating because it’s the most common mistake. Five levels of nesting creates selectors like main section article header h1. That’s absurdly specific and nearly impossible to override without using !important (which you should avoid).

    Pitfall 2: Forgetting the Ampersand

    Without & before pseudo-classes, your styles won’t work as expected. The browser will look for a descendant element called :hover instead of applying the hover state to the parent.

    Pitfall 3: Overusing Nesting

    Just because you can nest doesn’t mean you should nest everything. If nesting doesn’t improve organisation, stick with traditional CSS.

    Resources and Further Reading

    If you want to dive deeper into CSS nesting, here are the resources I found most helpful:

    My Personal Take

    After using CSS nesting in a few recent projects, I genuinely can’t imagine going back to traditional CSS for component-heavy work. The organisation benefits alone are worth it.

    That said, I wouldn’t use it absolutely everywhere. For simple, one-off styles, traditional CSS is perfectly fine. But for anything component-based – navigation menus, cards, forms, footers – nesting makes the code so much more maintainable.

    The fact that it’s now native means there’s no excuse not to try it. You don’t need to set up Sass or any build tools. Just write nested CSS and it works.

  • Alf’s Cycles: A Design Reflection

    Building a Brand Identity from Scratch

    30 January 2026

    When I first opened the brief for Alf’s Cycles, I thought I was designing a website for a bike shop. I was wrong. I was designing a memorial for a cat who believed the world belonged to him.

    That realisation changed everything.

    The Beginning

    The project started simply enough: create a responsive website for a family run bike shop in Keswick. Four pages. Clean navigation. Mobile-friendly. Professional but approachable. I sketched wireframes in my notebook, planned colour palettes, researched competitors. Standard design process.

    Then I read about Alf the sharp eyed, fearless cat who sat through repairs, rode atop bicycles, and ruled Tom Harding’s garage like a king. Suddenly, this wasn’t about selling bikes anymore. It was about honouring a legacy. The design needed soul.

    Finding the Voice

    I spent hours staring at vintage British cycling posters from the 1960s. There was something in their bold typography, their limited colours, their unapologetic confidence. That’s what Alf deserved not corporate polish, but character.

    The colour palette came naturally: cream like aged paper (#EDE8D0), bold red for energy (#d5161b), dark grey softer than pure black (#383838). Together, they felt distinctly British, slightly vintage, wholly unique. The cream background became my favourite decision warmer than stark white, inviting like an old photograph.

    Typography took longer. I needed fonts that commanded attention without shouting. Anton for massive display headings condensed, bold, impossible to ignore. Anybody Condensed for navigation clean but distinctive. Helvetica for body text—reliable, readable, professional. The combination created natural hierarchy. Your eye knew exactly where to look.

    The Struggles

    Nothing worth making comes easy. I faced problems I hadn’t anticipated.

    First, the CSS became a battlefield. Multiple stylesheets fighting each other the repair page inherited homepage animations and looked broken. I spent an entire afternoon untangling specificity issues, eventually consolidating everything into two files. Lesson learned: plan your architecture before you start coding.

    Second, the About page layout defeated me three times. The heading was too large (15rem!), completely invisible. The image sat in the wrong position. I’d used absolute positioning thinking it gave me control instead, it gave me chaos. The solution was simpler than I’d imagined: flexbox, vertical flow, let content breathe naturally. Sometimes bigger isn’t better.

    Third, mobile readability. My line height was 1.3 far too tight. Text felt cramped, suffocating. Increasing it to 1.9 changed everything. Suddenly, paragraphs had room to breathe. Reading became pleasant instead of painful. Small details matter enormously.

    The Breakthrough

    The turning point came when I stopped trying to make a “modern” website and started asking: “Would Alf approve?”

    That question guided every decision. The horizontal scroll section that lets you drag through services Alf would’ve prowled through those cards. The dark backgrounds for storytelling sections—intimate, like tales told in dim light. The massive headings that refuse to be ignored Alf never did anything quietly.

    I wrote and rewrote the About page copy four times. The final version has rhythm: short sentences for impact, longer ones for flow. Specific details Station Street, Honister Pass, Latrigg. Showing rather than telling. “Sharp-eyed” not “looked sharp.” Every word earned its place.

    What I Learned

    Design isn’t just about making things look good. It’s about capturing something true. Technical skill is useless without narrative direction. I can write perfect CSS, implement flawless responsive layouts, optimise load times but none of that matters if the soul is missing.

    This project taught me that constraints breed creativity. Limited colour palette, simple layouts, semantic HTML restrictions forced innovation. It taught me that details compound: the breathing animation, the hover effects, the line-height adjustments. Small touches create big impressions.

    Most importantly, it taught me to listen. Not to trends, not to other websites, but to the story itself. Alf’s story demanded something memorable, lived in, bold but never corporate. Once I stopped fighting that and started honouring it, the design found its voice.

    The Result

    The final website isn’t perfect. I’d change things if I started again better CSS planning, mobile wireframes from day one, component libraries for consistency. But it’s honest. It feels like Alf: a bit scruffy, wholly authentic, impossible to forget.

    Every time I questioned a decision, I returned to one question: “Would Alf approve?” A cat who rode bicycles, ruled stone paths, and sat through countless repairs deserved more than generic corporate design. He deserved something with teeth.

    I think we got there. The website lives now, telling his story in cream and red and bold typography. And if you look closely really closely you might imagine Alf there still, perched on a digital saddle, one paw stretched out, ruling the screen like he always ruled everything else.

    Some spirits don’t leave. They just become part of the code.

  • Hello world!

    Welcome to WordPress. This is your first post. Edit or delete it, then start writing!