Overview
This site is version two, launched in April 2026. It is a complete ground-up rebuild. The first version was a hand-coded Astro site that served me well for a couple of years. It was fast, simple, and taught me a lot about the islands architecture. But as my needs grew to include dynamic OG images, a proper API layer, and more complex MDX interactions, the "simple" part started to fray. Version two is built on Next.js 16, with its component and layout drafts generated by Claude Design and then heavily refined by hand. This hybrid approach was a fascinating experiment in itself.
The entire project is open source and available on GitHub at github.com/kieran/kieran123.win-site. I believe in working in the open. You are welcome to browse the source code, fork the repository, or borrow any patterns you find useful. If you see a bug or a typo, a pull request is the fastest way to my heart. This page documents the tools, design choices, and happy accidents that make up the site you are reading right now.
Stack
I chose this stack for a balance of developer experience, performance, and the ability to control the entire pipeline from code to deployment.
- Next.js 16 App Router: The move from Astro was primarily for this. The App Router, with turbopack enabled, gives me a unified model for static pages, server components, API routes, and dynamic rendering. It simplifies everything. No more separate cloud functions for OG images; they are just another route.
- Tailwind 4: I was an early adopter of the new CSS-first engine. Defining my entire design system in a single
@themeblock inside my global CSS file feels incredibly clean. It compiles down to almost nothing and the performance is fantastic. - TypeScript: Strict mode is on. Life is too short for
anytypes and runtime errors that could have been caught at build time. It makes refactoring a breeze and gives me confidence when I come back to the code after a few weeks. - MDX: All my long-form content is written in MDX. I use
next-mdx-remotefor rendering,gray-matterfor frontmatter parsing, andrehype-pretty-codewith the Shiki highlighter for beautiful, accessible code blocks. - Framer Motion 12: I use it sparingly for subtle layout animations and page transitions. The goal is to provide feedback and a sense of place without being distracting. Everything is disabled if a user has
prefers-reduced-motionenabled. - React 19: The new compiler and built-in features like Actions simplify state management and data mutations. It feels like a significant step forward for the library.
- Cloudflare Pages: Deployment is handled through a git push, which triggers a build on Cloudflare's infrastructure. I use
wranglerfor local development and direct uploads. The integration with R2, Workers, and the broader ecosystem is excellent. You can read their docs to learn more. - Fonts: All fonts are self-hosted to avoid layout shifts and external requests. I use Inter Variable for all prose and UI text, and JetBrains Mono Variable for code and other monospaced elements. Both are open source and exceptionally well-made.
- Image Optimization: I use
sharpvia the built-in Next.js<Image>component. It automatically generates modern formats, prioritizing AVIF for browsers that support it, and provides responsivesrcsetattributes. - Agent-Ready Surfaces: Beyond a
robots.txtandsitemap.xml, I've added several machine-readable endpoints:/llms.txtfor training instructions,/mcp-card.jsonfor my machine-readable contact card,/agent.jsonfor AI agent instructions, and a full suite of.well-knownendpoints for security, AI, content signals, and payments. - Feeds: I provide full-content feeds for all my writing. You can subscribe via
/feed.xml(RSS 2.0),/atom.xml, or/feed.json. There is also an index page at/feeds. - Analytics: I use a self-hosted instance of Umami. It is a lightweight, privacy-focused analytics tool that does not use cookies and gives me simple, useful metrics about what pages are popular.
- Newsletter: My weekly newsletter is managed through Buttondown. It is a simple, powerful, and independent platform that I am happy to support.
What v2 changed from v1
The move to version two was driven by a desire for a more integrated and capable platform.
- From Astro to Next.js 16: This was the biggest change. In v1, I loved Astro's static output, but I had to bolt on other services. I had one toolchain for the site (Astro), another for generating OG images (a separate Vercel function), and a third for API endpoints (Cloudflare Workers). Next.js 16 lets me do all of this within a single framework and a single git repository. The developer experience is much cleaner.
- AI-Assisted Drafting: I used Claude Design to generate first drafts of most React components. I would describe the component's purpose, its props, and the desired style, and it would produce a surprisingly good starting point. I estimate this saved me about 60% of the initial component creation time, which I then spent on refinement, accessibility, and interaction details.
- Full Agent-Ready Surface: Version one had a basic
robots.txtandsitemap.xml. Version two adds a comprehensive set of endpoints for AI agents and crawlers. This is an experiment in structured data availability, making the site's content and purpose more legible to automated systems. - Interactive API: I added an experimental
/api/askendpoint. It is a paid endpoint (via the x402 protocol) that provides a direct interface to a Claude model fine-tuned on my own writing. It is a test of micropayments and agent-to-agent communication. - On-Site Search: The site now has a
/searchpage. The index is generated at build time and shipped to the client. It is fast, works offline, and is backed by a server-side search for users with JavaScript disabled. - Dark-Only Theme: Version one had a dark-by-default theme with a toggle for a light mode. My analytics showed that less than 1% of visitors ever used the light mode. For version two, I decided to simplify the CSS and embrace a single, refined dark theme.
Design language
I call the aesthetic "Rational Brutalism" or "Swiss Terminal". It is a mix of web brutalism's honesty about materials (pixels are square) and Swiss design's focus on grid, typography, and clarity.
- Color Palette: The site is dark-only. The background is a soft black (
#0a0a0b) and the text is a slightly off-white (#ededed). There is a single accent color, a vibrant green (#7cf39a), which reminds me of the status LEDs on old ThinkPad laptops. - Structure: I use a strict token for borders:
1px solid #26262b. There are no box shadows anywhere on the site. I find they add visual complexity without adding meaning. There is also noborder-radius, except for small "pill" shaped elements like tags. - Typography: The type system is simple. Inter is used for all prose and user interface text. It is a beautiful, highly legible sans-serif that works well at all sizes. JetBrains Mono is used for code blocks, inline code, and other labels that benefit from a monospaced face.
- Motion: Animation is used to communicate change, not for decoration. Transitions are typically between 200 and 300 milliseconds with a gentle
ease-outcurve. All motion is completely disabled if the user's system hasprefers-reduced-motionenabled. - Icons: I do not use an icon library. For the few icons on the site, I either use standard Unicode glyphs (like → or ↵) or tiny, hand-optimized inline SVGs. This reduces dependencies and keeps the site fast.
Content
- Corpus: As of this writing, the site contains about 14 long-form writing posts, 4 project case studies, and 2 core static pages (
/aboutand/now). - Format: All content is written in MDX, with metadata managed in YAML frontmatter. This allows me to mix narrative prose with interactive React components.
- Licensing: The prose on this site is licensed under a Creative Commons Attribution 4.0 International License (CC-BY-4.0). The underlying source code, unless otherwise noted in a specific file, is licensed under the MIT License.
- Schema: The post schema is machine-readable and available via the
/feed.jsonendpoint, making it easy for other services to ingest and understand the content.
Things I built that surprised me
- The Search Index: I was planning to use a service like Algolia, but I decided to try building a simple search index first. The build script parses all MDX files, strips the markdown, and creates a small JSON file with post titles, summaries, and slugs. This index is under 50KB when gzipped, covers my entire corpus, and provides instant client-side search results. It was much simpler and more effective than I expected.
- The x402 Gateway: The
/api/askendpoint was a wild experiment. It uses the emerging 402 "Payment Required" standard to let automated agents pay for API calls. I did not expect it to work at all. On the day I launched, one agent actually made a series of calls and paid me a grand total of $0.01. It was a tiny amount, but it proved the concept works. - Claude Design's Strengths and Weaknesses: I was surprised by how well Claude Design handled data-dense components. When I asked for a "list of posts with title, date, and tags", it produced clean, semantic, and well-structured React code. However, it struggled with more abstract or aesthetic tasks, like designing a hero section. Its first drafts for those were often generic and uninspired.
The one hack I'm not proud of
My dynamic OG image generation is a set of Next.js Route Handlers under /app/og/. To style the images, which are rendered using Satori (HTML/CSS to SVG), I need to provide colors, font sizes, and other design tokens. Instead of figuring out a way to import my Tailwind theme or global CSS variables into these server-side routes, I created a tokens.ts file that just duplicates the values. If I change a color in globals.css, I have to remember to change it in tokens.ts as well. I have a TODO comment in the code to automate this, perhaps with a build script that codegens one from the other. That TODO has been there for three weeks.
Credits
No site is built in a vacuum. My work stands on the shoulders of giants.
- Design Inspiration: The minimalist, content-focused layout is heavily inspired by Bret Victor's "Inventing on Principle" essay, Frank Chimero's old website
Shift, Craig Mod's work atRandom Access, and Devine Lu Linvega's incredibleXXIIVVwiki. - Typography: My appreciation for pairing a humanist sans-serif with a functional monospaced font comes from years of using iA Writer and reading countless books on Swiss design.
- Interaction Ideas: Some of the subtle interaction patterns, especially around focus and state changes, were inspired by observing the user interface of claude.ai itself during the April 2026 release cycle.
- Feedback: A huge thank you to every person who commented on my weekly newsletter drafts between October 2025 and April 2026. Your feedback was invaluable in shaping the content and structure of this site.
Open questions
I am still actively thinking about a few things for the future of the site.
- Should
/nowhave its own RSS feed? Probably yes. A "now" page is a snapshot in time, and a dedicated feed would let people follow those updates more easily. I will likely add this in version 2.1. - Should I add a Chinese mirror? I have a significant number of readers from Taiwan. Adding a
/zh-TWversion of the site is tempting. However, this would require a commitment to monthly translations, which is a significant undertaking. I am still weighing the costs and benefits. - Is Cloudflare-only hosting a lock-in risk? Slightly. By using Cloudflare Pages, I am tied to their build environment. But the site is just a standard Next.js project. Moving it to Vercel or a self-hosted Node.js server would probably be 2 to 3 hours of work at most. For now, the benefits outweigh the risk.
Licenses
- Prose: All writing is licensed CC-BY-4.0.
- Code: All source code is licensed MIT (see the
LICENSEfile in the repository). - Fonts: Inter and JetBrains Mono are licensed under the SIL Open Font License.
- Icons: The few icons I use are from Lucide and are licensed under the MIT license.
How to reach me about this site specifically
- For general comments or questions about the site, email me at
kieran@kieran123.win. - For bugs, accessibility issues, or corrections, please open an issue on the GitHub repository.
- Pull requests for typos, clearer language, or performance fixes are always welcome.
Last updated
Last updated 2026-04-20. If you spot something broken, tell me at kieran@kieran123.win.