G.S.

/

Writing

/

Website Update For 2026

Website update for 2026

December 22, 2025DevelopmentDesignNext.js

Moving from Webflow to a custom Next.js build

After using Webflow for my portfolio for a couple of years, I decided to migrate to a custom Next.js build. This wasn't because Webflow failed me. In fact, I still highly recommend Webflow for its ease of use and powerful visual editor. But I wanted to challenge myself with a fully custom build, it felt like the right time to explore what's possible with modern development tools.

Why make the switch?

Webflow is an excellent platform, and I genuinely recommend it. I still build client websites in Webflow, and in my experience it's a perfect platform for companies with little to no development experience. The visual editor is intuitive, the hosting is reliable, and you can build complex interactions without writing JavaScript.

However, a few factors pushed me toward building custom:

Cost optimization. Between hosting, CMS features, and additional services, the monthly fees were adding up. For a simple portfolio site, these costs felt higher than necessary.

Learning opportunity. I wanted to challenge myself and see how far I could take a custom build using modern tools and frameworks.

Complete ownership. Having full control over every aspect of the codebase meant I could experiment freely without platform limitations.

Modern tooling. With AI assistants like Claude Code, building custom websites has become significantly more accessible. I was curious to see how these tools could help structure a project from scratch.

The tech stack

I chose a modern, performant stack that aligned with my workflow as a designer who codes:

Next.js 16 with the App Router for routing and React Server Components. I've used Next.js before and having an understanding of React, it was the obvious choice for me. It might be overkill for a portfolio site, but having used it before and understanding how it works, it seemed like the right choice. The framework handles optimization and provides excellent developer experience out of the box.

Base UI for component primitives. Rather than using a heavy component library, I wanted unstyled, accessible components I could style exactly how I envisioned.

SCSS Modules for styling. This gave me the familiarity of SASS with scoped styles, avoiding the complexity of CSS-in-JS while maintaining full control.

Resend for email handling. With Webflow, I had native form submissions that would show up in the dashboard. For the new site, I wanted to receive emails directly when someone submits the contact form, so Resend provided a clean API with excellent deliverability.

Design system first

Before building any components, I established a design system with tokens for colors, spacing, typography, and transitions:

:root {
  // Colors
  --text-aaa: #f5faf7;
  --text-aa: #8f9391;
  --background: #0c0d0d;
  --panel: #151616;
  // ...

  // Spacing
  --spacing-xs: 4px;
  --spacing-sm: 8px;
  --spacing-md: 16px;
  // ...

  // Typography
  --font-size-sm: 0.875rem;
  --font-size-base: 1rem;
  // ...

  // Transitions
  --transition-base: 200ms ease;
  // ...
}

This approach meant I could make global design decisions from a single file. Adjusting spacing or colors across the entire site became a matter of changing a few variables.

Building with AI assistance

One of the most interesting aspects of this project was using Claude Code to help structure components and implement features. Rather than searching through documentation or piecing together tutorials, I could describe what I wanted and get working code that followed best practices.

For example, when building the Table component, I described the requirements: organized lists with headers, support for tags, animated hover states, and handling both internal and external links. Claude Code helped structure the component with proper TypeScript types, accessibility features, and clean separation of concerns.

<Table
  lists={[
    {
      header: "Navigation",
      items: [
        { title: "Home", href: "/" },
        { title: "Writing", href: "/writing" },
      ],
    },
    {
      header: "Projects",
      items: [
        {
          title: "Slim icons",
          href: "https://slimicons.com",
          tag: "Design System",
          openInNewTab: true,
        },
      ],
    },
  ]}
/>

The component ended up being highly reusable. I use it for site navigation, blog post listings, and my tech stack page. Each use case leverages the same flexible API.

Handling the contact form

One of the more interesting integrations was setting up the contact form with Resend. In Webflow, form submissions were native and appeared in the dashboard automatically. For the custom build, I wanted to receive emails directly when someone submits a partnership request.

The implementation required handling form validation, managing loading states, and providing user feedback:

const handleSubmit = async (e: React.FormEvent) => {
  e.preventDefault();
  setIsSubmitting(true);

  try {
    const response = await fetch("/api/contact", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(formData),
    });

    if (response.ok) {
      toast.success("Message sent successfully!");
      setFormData({
        name: "",
        email: "",
        company: "",
        projectDetails: "",
      });
    } else {
      throw new Error("Failed to send message");
    }
  } catch {
    toast.error("Failed to send message. Please try again.");
  } finally {
    setIsSubmitting(false);
  }
};

The server-side API route handles the actual Resend integration and sends me an email with the form details:

export async function POST(request: Request) {
  const { name, email, company, projectDetails } = await request.json();

  const resend = new Resend(process.env.RESEND_API_KEY);

  await resend.emails.send({
    from: "contact@sigurdarson.is",
    to: "hello@sigurdarson.is",
    subject: `New Partnership Request from ${name}`,
    html: `
      <p><strong>Name:</strong> ${name}</p>
      <p><strong>Email:</strong> ${email}</p>
      <p><strong>Company:</strong> ${company}</p>
      <p><strong>Project Details:</strong> ${projectDetails}</p>
    `,
  });

  return Response.json({ success: true });
}

This pattern of keeping sensitive API keys server-side while providing a clean client interface worked well. The same approach applies to other integrations like the newsletter subscription and Dribbble API proxy.

Content management

I wanted the flexibility of a CMS without the overhead. MDX for blog posts and JSON for structured data gave me exactly what I needed.

Blog posts are written in Markdown with frontmatter:

---
title: "My post title"
date: "2025-01-15"
tags: ["Design", "Development"]
---

# My post title

Content here with full MDX support...

For structured data like my tech stack, JSON files work perfectly:

[
  {
    "section": "App defaults",
    "items": [
      {
        "name": "Raycast",
        "tag": "Launcher",
        "url": "https://raycast.com",
        "affiliate": false
      }
    ]
  }
]

This approach means I can update content directly in my code editor. No admin panel, no database, just files in my repository.

Performance & accessibility optimizations

Next.js handles much of the optimization automatically, but I added a few specific improvements:

Image optimization using the Next.js Image component with WEBP format for photography. This significantly reduced file sizes while maintaining quality. I have a created custom WEBP converter that anyone can use here.

Locale-aware date formatting that respects each visitor's browser settings:

// Automatically formats based on browser locale
<FormattedDate dateString="2025-01-15" />
// US: "January 15, 2025"
// UK: "15 January 2025"
// DE: "15. Januar 2025"

What I learned

Design systems scale the same in code as in Figma. Investing time upfront in design tokens and reusable components made adding new pages fast. The Stack page, for example, was composed from existing components in under an hour.

AI tools are game-changers. Claude Code didn't just write code for me. It helped me structure the project, suggested better patterns, caught potential issues, and explained complex concepts. The learning curve for custom development has significantly flattened.

Constraints breed creativity. Working with a small set of well-designed components forced me to think about patterns and reusability. The Table component serves three completely different use cases because I designed it to be flexible from the start.

Modern frameworks remove friction. Next.js handles routing, optimization, image processing, and deployment seamlessly. I spent time on design and features rather than configuration.

Cost comparison

The migration resulted in significant cost savings:

Webflow: ~$30-40/month for hosting and CMS features

Current setup: ~$0/month (deployed on Vercel's free tier, Resend's free tier for email)

For my use case, this made the investment in a custom build worthwhile. Your mileage may vary depending on traffic and feature requirements.

The result

The new site is fast, maintainable, and completely mine. Pages load instantly with server components. Adding new content or features is straightforward, and good enough for me.

More importantly, I learned a tremendous amount in the process. Understanding every line of code in your portfolio means you can iterate without limitations.

Still recommend Webflow

Despite migrating away, I genuinely recommend Webflow. I still build a lot of client websites in Webflow, and in my experience it's a perfect platform for companies with little to no development experience. If you want a professional site quickly, without touching code, or need client-friendly editing, Webflow is excellent. The visual editor is unmatched, and the platform is reliable. See my services here.

I chose to migrate because I wanted the learning experience and cost optimization. But for many use cases, Webflow remains the better choice.

Moving forward

Building this portfolio taught me that custom development is more accessible than ever. With modern frameworks and AI assistance, designers can create production-quality websites without being expert developers (I have a background in computer sience).

The process also gave me a platform I can grow with. As I explore new technologies or develop new design ideas, I can iterate freely.

If you're considering a similar migration, my advice is to start small. Build one page, get it deployed, then expand from there. The tooling is more approachable than you might think.

Thank you for reading.