{
  "version": "https://jsonfeed.org/version/1.1",
  "title": "kevinkiklee.io",
  "home_page_url": "https://kevinkiklee.io/",
  "feed_url": "https://kevinkiklee.io/feed.json",
  "description": "Field notes from a Chrome DevRel.",
  "language": "en-US",
  "authors": [
    {
      "name": "Kevin Lee",
      "url": "https://kevinkiklee.io/"
    }
  ],
  "items": [
    {
      "id": "https://kevinkiklee.io/posts/writing-for-ai-answer-engines",
      "url": "https://kevinkiklee.io/posts/writing-for-ai-answer-engines",
      "title": "Writing technical posts for AI answer engines",
      "summary": "How to structure a technical post so ChatGPT, Perplexity, and Google AI Overviews can actually quote it correctly.",
      "content_text": "> Placeholder post — written to exercise rendering paths during development.\n> Will be replaced before launch.\n\nAI answer engines like ChatGPT, Perplexity, and Google AI Overviews don't read your post the way a human does. They scan for definitional sentences, lift them, and paraphrase. If you want your work cited correctly, write the lift-able sentences on purpose.\n\n## What is \"AEO\" and how is it different from SEO?\n\nAEO — Answer Engine Optimisation — is the practice of structuring content so it's easy to quote out of context. SEO optimises for ranking in a list of links. AEO optimises for being the sentence the assistant repeats back to the user.\n\nThe two overlap heavily, but they pull in different directions in three places:\n\n1. **Headings.** SEO rewards keyword-stuffed headings. AEO rewards question-form headings the user might literally type.\n2. **First sentence.** SEO doesn't care about your lede. AEO cares about almost nothing else.\n3. **Links.** SEO rewards internal linking. AEO rewards inline citations to primary sources.\n\n## How does an answer engine pick what to quote?\n\nMost answer engines use a retrieval step (find candidate documents) followed by a generation step (write the answer with citations). The retrieval step rewards the same things classical search rewards. The generation step rewards short, declarative, self-contained sentences.\n\nIf your first sentence answers the headline's implicit question in fewer than 30 words, you've made the assistant's job easy. If it doesn't, the assistant will guess — and its guess will not match what you wrote.\n\n## What should every post contain?\n\nThree things, in this order:\n\n### A definitional first sentence\n\nOpen with a one- or two-sentence answer to the title's question. No throat-clearing. No \"in this post we'll explore.\" Just the answer.\n\n### Question-form headings\n\nHeadings should mirror the questions a user would actually ask. `## How does X work?` beats `## Mechanism`. `## When should I use X?` beats `## Use cases`. The literal word forms matter — they're what the retrieval step matches against.\n\n### A plain-prose summary under every visual\n\nDiagrams, screenshots, and charts are invisible to most LLM scrapers. If you've drawn something, write a paragraph underneath that describes what the diagram shows. The paragraph is what gets indexed.\n\n## What about freshness?\n\nAnswer engines aggressively prefer recent content for fast-moving topics. Two practical implications:\n\n- **Date your posts.** Both `pubDate` and `updatedDate` if you revise.\n- **Don't bury the publication date.** It should be visible near the title, not in a footer.\n\nFor evergreen topics (definitions, mental models), freshness matters less. For anything tied to a specific tool version, browser release, or API deprecation, freshness is the single biggest ranking signal.\n\n## Common mistakes\n\n- **Burying the lede.** Anecdotes before the answer kill citation rates.\n- **Mixed-purpose paragraphs.** A paragraph that defines a thing AND argues for its use AND hedges the limits is unciteable. Split it.\n- **Heavy use of pronouns.** \"It\" and \"this\" don't survive being lifted out of context. Use the noun.\n- **Quoting yourself out of order.** If section three depends on section one's setup, the assistant will quote three without one. Make every section self-contained.\n\n## A quick checklist\n\nBefore publishing, verify the post:\n\n- [ ] Opens with a 1–2 sentence definitional answer to the title's question.\n- [ ] Contains at least one question-form heading.\n- [ ] Each section starts with a TL;DR sentence.\n- [ ] Every image / diagram has a plain-prose summary nearby.\n- [ ] Sources are linked inline, not parked in a footer.\n- [ ] Date is prominent.\n\nThat's most of it. The rest is just writing clearly, which has been the advice for a hundred years and will keep being the advice for a hundred more.",
      "date_published": "2026-04-26T00:00:00.000Z",
      "date_modified": "2026-04-26T00:00:00.000Z",
      "tags": [
        "devrel",
        "ai",
        "accessibility"
      ]
    },
    {
      "id": "https://kevinkiklee.io/posts/tools-i-use-in-2026",
      "url": "https://kevinkiklee.io/posts/tools-i-use-in-2026",
      "title": "Tools I use in 2026",
      "summary": "A short, opinionated list of the editor, terminal, and dev-loop tools that survived another year on my machine.",
      "content_text": "> Placeholder post — written to exercise rendering paths during development.\n> Will be replaced before launch.\n\nA short list of tools that earned their keep on my machine in 2026. No affiliate links, no rankings — just what's actually open right now.\n\n## Editor\n\n- **Zed** for day-to-day TypeScript and Astro work. The collaborative cursor is genuinely useful for pairing.\n- **VS Code** when I need a specific extension that hasn't shipped to Zed yet.\n\n## Terminal\n\n- **Ghostty** as the terminal emulator.\n- **fish** as the shell. I switched from zsh in 2025 and haven't looked back.\n- **eza**, **bat**, **fd**, **rg** as the standard `ls`/`cat`/`find`/`grep` replacements.\n\n## JS / TS\n\n- **pnpm** for everything. npm and yarn don't get installed on new machines anymore.\n- **Biome** instead of ESLint + Prettier. One tool, faster, fewer config files to babysit.\n- **Vitest** for unit tests. **Playwright** for end-to-end.\n\n## What I dropped\n\n- Webpack — Turbopack and Vite cover all my use cases now.\n- nvm — switched to **fnm**, which is dramatically faster.\n\nThat's the list. Short on purpose; the moment a list of tools gets long, it stops being useful and becomes a bibliography.",
      "date_published": "2026-04-20T00:00:00.000Z",
      "date_modified": "2026-04-20T00:00:00.000Z",
      "tags": [
        "tooling",
        "personal"
      ]
    },
    {
      "id": "https://kevinkiklee.io/posts/what-are-speculation-rules",
      "url": "https://kevinkiklee.io/posts/what-are-speculation-rules",
      "title": "What are Speculation Rules?",
      "summary": "A short mental model for the Speculation Rules API and when prerendering is actually worth it.",
      "content_text": "> Placeholder post — written to exercise rendering paths during development.\n> Will be replaced before launch.\n\nSpeculation Rules is a browser API that lets a page declare which URLs the user is likely to visit next, so the browser can prefetch or even fully prerender them in the background. Think of it as a structured replacement for `<link rel=\"prefetch\">` with explicit eagerness levels and document-rules support.\n\n## What problem does it solve?\n\nNavigation is the slowest part of most sites. By the time the user clicks, the network round-trip, parse, and paint are all still ahead. Speculation Rules moves that work earlier — the browser does it during idle time, gated by your hints.\n\n## How do you declare rules?\n\nDrop a JSON script in the document head. The browser parses it once and uses it for the lifetime of the page.\n\n```html\n<script type=\"speculationrules\">\n{\n  \"prerender\": [\n    {\n      \"where\": { \"href_matches\": \"/posts/*\" },\n      \"eagerness\": \"moderate\"\n    }\n  ]\n}\n</script>\n```\n\nThe `eagerness` levels are `immediate`, `eager`, `moderate`, and `conservative`. Most sites should start at `moderate` — the browser only prerenders when the user shows clear intent (e.g., hovers a link).\n\n## When should you NOT prerender?\n\nPrerendering executes the target page's JavaScript. That means analytics fire, side-effect-heavy server actions run, and any non-idempotent code on first paint will misbehave.\n\nSkip prerendering for:\n\n- pages with login-side-effects or token rotation\n- analytics dashboards that count page views on render\n- anything that mutates server state on initial GET (which you shouldn't be doing anyway)\n\n## How does it compare to `<link rel=\"prerender\">`?\n\n| Feature        | `<link rel=\"prerender\">` | Speculation Rules |\n| -------------- | ------------------------ | ----------------- |\n| Status         | Deprecated               | Active            |\n| Granularity    | Single URL               | URL patterns      |\n| Eagerness      | Implicit                 | Explicit          |\n| Document rules | No                       | Yes               |\n\nThe old `<link rel=\"prerender\">` was removed in favour of this API precisely because it had no eagerness control and burnt the user's data plan.\n\n## Further reading\n\n- [Speculation Rules explainer](https://github.com/WICG/nav-speculation/blob/main/triggers.md)\n- [Chrome Status entry](https://chromestatus.com/feature/5740655119761408)\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit. This trailing paragraph exists so the post has enough body text to test the reading-time estimate, the related-posts sidebar, and the prose stylesheet's vertical rhythm under longer flows.",
      "date_published": "2026-04-15T00:00:00.000Z",
      "date_modified": "2026-04-15T00:00:00.000Z",
      "tags": [
        "web-platform",
        "performance",
        "chrome"
      ]
    },
    {
      "id": "https://kevinkiklee.io/posts/hello-world",
      "url": "https://kevinkiklee.io/posts/hello-world",
      "title": "Hello, world",
      "summary": "First post on the new site — what it is and what to expect.",
      "content_text": "kevinkiklee.io is a personal tech blog by Kevin Lee, Developer Relations Engineer at Google Chrome. This is the inaugural post — a quick tour of what's here and what's coming.\n\n## What can you read here?\n\nPosts arrive when something feels worth saying. Expect a mix of:\n\n- web platform deep-dives (View Transitions, Speculation Rules, Cache Components)\n- AI workflows and prompting\n- random tangents\n\nCode blocks render with Shiki dual themes:\n\n```ts\nconsole.log('hello, world');\n```\n\nThat's it. Subscribe via [RSS](/rss.xml) or [JSON Feed](/feed.json).",
      "date_published": "2026-04-12T00:00:00.000Z",
      "date_modified": "2026-04-12T00:00:00.000Z",
      "tags": [
        "personal",
        "devrel"
      ]
    }
  ]
}