<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Mateusz Muszarski: blog</title>
    <link>https://muszarski.com/en/blog/</link>
    <atom:link href="https://muszarski.com/en/rss.xml" rel="self" type="application/rss+xml"/>
    <description>Notes from building products: AI-assisted development, Lingui, performance and accessibility.</description>
    <language>en</language>
    <item>
      <title>yws.lu: rebuilding a Luxembourg non-profit's site from Next.js to Astro in one day</title>
      <link>https://muszarski.com/en/blog/yws-lu-case-study/</link>
      <guid isPermaLink="true">https://muszarski.com/en/blog/yws-lu-case-study/</guid>
      <description>Case study: migrating a Next.js site with 3D to static Astro in one day with Claude Code. Lab Lighthouse on phones: 23-28 to 99-100.</description>
      <pubDate>Fri, 09 Oct 2026 00:00:00 GMT</pubDate>
      <category>case-study</category>
      <category>astro</category>
      <category>performance</category>
      <category>ai</category>
    </item>
    <item>
      <title>Psychology in UX and on the frontend: persuasion you can defend</title>
      <link>https://muszarski.com/en/blog/psychology-in-ux-and-frontend/</link>
      <guid isPermaLink="true">https://muszarski.com/en/blog/psychology-in-ux-and-frontend/</guid>
      <description>Scarcity, social proof, anchors, defaults and progress bars, built honestly in code, and where EU and Polish law draws the line on dark patterns.</description>
      <pubDate>Wed, 07 Oct 2026 00:00:00 GMT</pubDate>
      <category>design</category>
    </item>
    <item>
      <title>A contact form on a static site: one function, server-side email and the bug that failed every message</title>
      <link>https://muszarski.com/en/blog/contact-form-on-a-static-site/</link>
      <guid isPermaLink="true">https://muszarski.com/en/blog/contact-form-on-a-static-site/</guid>
      <description>One Vercel Function next to a static Astro build: a message-first form, three bot checks, EmailJS from the server, no-JS support and one ESM bug.</description>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <category>astro</category>
      <category>accessibility</category>
      <category>privacy</category>
    </item>
    <item>
      <title>A multilingual Astro site with Lingui: routes, hreflang and a language switch that keeps your place</title>
      <link>https://muszarski.com/en/blog/multilingual-astro-site-with-lingui/</link>
      <guid isPermaLink="true">https://muszarski.com/en/blog/multilingual-astro-site-with-lingui/</guid>
      <description>How this site serves English, Polish and Spanish from one static Astro build: locale routes, translated slugs, hreflang and a switch that keeps your page.</description>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <category>i18n</category>
      <category>astro</category>
    </item>
    <item>
      <title>Hover effects on phones: every hover gets a tap, focus or scroll twin</title>
      <link>https://muszarski.com/en/blog/hover-effects-on-phones/</link>
      <guid isPermaLink="true">https://muszarski.com/en/blog/hover-effects-on-phones/</guid>
      <description>Phones have no cursor. How this site gates hover with (hover: hover) and (pointer: fine) and gives every hover a tap, focus or scroll twin.</description>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <category>accessibility</category>
      <category>design</category>
    </item>
    <item>
      <title>How do you keep a web CV and its PDF from drifting apart?</title>
      <link>https://muszarski.com/en/blog/web-cv-and-pdf-from-one-source/</link>
      <guid isPermaLink="true">https://muszarski.com/en/blog/web-cv-and-pdf-from-one-source/</guid>
      <description>My CV page and its PDFs in English, Polish and Spanish come from one TypeScript file: Playwright prints a designed A4 sheet, and a test fails on drift.</description>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <category>astro</category>
      <category>i18n</category>
      <category>accessibility</category>
    </item>
    <item>
      <title>Lighthouse scores of 16 developer portfolios: immersive vs minimal</title>
      <link>https://muszarski.com/en/blog/lighthouse-scores-of-16-developer-portfolios/</link>
      <guid isPermaLink="true">https://muszarski.com/en/blog/lighthouse-scores-of-16-developer-portfolios/</guid>
      <description>Mobile Lighthouse, 3 runs each, on 16 well-known developer portfolios: 3D median 35.5, minimal 74.5. The method, the results and what the score misses.</description>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <category>performance</category>
      <category>accessibility</category>
    </item>
    <item>
      <title>Shipping a mobile app alone: Linkoglot, from one codebase to two app stores</title>
      <link>https://muszarski.com/en/blog/shipping-a-mobile-app-alone/</link>
      <guid isPermaLink="true">https://muszarski.com/en/blog/shipping-a-mobile-app-alone/</guid>
      <description>How I built and shipped Linkoglot, an AI language app, alone: Expo, Supabase, RevenueCat, Lingui in 30 languages, and what both app stores ask for.</description>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <category>react</category>
      <category>i18n</category>
      <category>ai</category>
    </item>
    <item>
      <title>Why my three.js portfolio was slow on mobile, and what a 3D site needs</title>
      <link>https://muszarski.com/en/blog/why-my-threejs-portfolio-was-slow-on-mobile/</link>
      <guid isPermaLink="true">https://muszarski.com/en/blog/why-my-threejs-portfolio-was-slow-on-mobile/</guid>
      <description>My old three.js portfolio scored 34 on mobile Lighthouse. What made it slow, and a checklist for a 3D site that stays fast on phones.</description>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <category>performance</category>
      <category>react</category>
      <category>accessibility</category>
    </item>
    <item>
      <title>Trying to build an Awwwards-winning brutalist portfolio: the process, the mindset and the tools</title>
      <link>https://muszarski.com/en/blog/case-study/</link>
      <guid isPermaLink="true">https://muszarski.com/en/blog/case-study/</guid>
      <description>Case study: why I swapped my 3D portfolio for a poster. The research, the sites I learned from, every version, and shaders that never get in the way.</description>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <category>case-study</category>
      <category>ai</category>
      <category>astro</category>
      <category>performance</category>
    </item>
    <item>
      <title>An LLM wiki: project memory for Claude Code that survives compaction</title>
      <link>https://muszarski.com/en/blog/llm-wiki-project-memory-for-claude-code/</link>
      <guid isPermaLink="true">https://muszarski.com/en/blog/llm-wiki-project-memory-for-claude-code/</guid>
      <description>How I stop Claude Code from forgetting: a foldered markdown wiki, a routing table, a lessons file and three hooks that reload them after compaction.</description>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <category>ai</category>
      <category>claude-code</category>
    </item>
    <item>
      <title>Astro vs Next.js for a portfolio or a landing page</title>
      <link>https://muszarski.com/en/blog/astro-vs-nextjs-for-a-portfolio/</link>
      <guid isPermaLink="true">https://muszarski.com/en/blog/astro-vs-nextjs-for-a-portfolio/</guid>
      <description>When Astro fits a portfolio or landing page and when Next.js is the right call, with HTTP Archive Core Web Vitals data and this site's measurements.</description>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <category>astro</category>
      <category>performance</category>
      <category>react</category>
    </item>
    <item>
      <title>Claude Code skills, hooks, MCP servers and subagents: which one when</title>
      <link>https://muszarski.com/en/blog/claude-code-skills-hooks-mcp-subagents/</link>
      <guid isPermaLink="true">https://muszarski.com/en/blog/claude-code-skills-hooks-mcp-subagents/</guid>
      <description>When to use CLAUDE.md, a skill, a hook, an MCP server or a subagent in Claude Code: the official docs, plus the real setup that built this site.</description>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <category>ai</category>
      <category>claude-code</category>
    </item>
    <item>
      <title>Cookieless analytics in the EU: Umami, GDPR and Poland's art. 399</title>
      <link>https://muszarski.com/en/blog/cookieless-analytics-in-the-eu/</link>
      <guid isPermaLink="true">https://muszarski.com/en/blog/cookieless-analytics-in-the-eu/</guid>
      <description>Cookieless is not automatically consent-free. What GDPR and art. 399 of Poland's electronic communications law say, and three positions you can defend.</description>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <category>privacy</category>
    </item>
    <item>
      <title>Fit text to its container at build time with a variable font</title>
      <link>https://muszarski.com/en/blog/fit-text-to-width-at-build-time/</link>
      <guid isPermaLink="true">https://muszarski.com/en/blog/fit-text-to-width-at-build-time/</guid>
      <description>How my name runs edge to edge on this site with no JavaScript: font metrics measured at build time, the wdth axis, cqi units and font-stretch.</description>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <category>typography</category>
      <category>performance</category>
      <category>design</category>
    </item>
    <item>
      <title>Lingui vs i18next in 2026: which i18n library for React and React Native</title>
      <link>https://muszarski.com/en/blog/lingui-vs-i18next/</link>
      <guid isPermaLink="true">https://muszarski.com/en/blog/lingui-vs-i18next/</guid>
      <description>Lingui and i18next compared from their docs and npm data: message format, macros, compile step, bundle size, plurals, TypeScript and React Native.</description>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <category>i18n</category>
      <category>react</category>
    </item>
    <item>
      <title>Motion that respects people: prefers-reduced-motion and a pause button</title>
      <link>https://muszarski.com/en/blog/reduced-motion-and-a-pause-button/</link>
      <guid isPermaLink="true">https://muszarski.com/en/blog/reduced-motion-and-a-pause-button/</guid>
      <description>How this site handles motion: a WCAG 2.2.2 pause control, prefers-reduced-motion, loops that stop offscreen and reveals that never hide content.</description>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <category>accessibility</category>
      <category>design</category>
    </item>
    <item>
      <title>Translating Lingui catalogs with an LLM</title>
      <link>https://muszarski.com/en/blog/translate-lingui-catalogs-with-an-llm/</link>
      <guid isPermaLink="true">https://muszarski.com/en/blog/translate-lingui-catalogs-with-an-llm/</guid>
      <description>How to machine-translate Lingui .po catalogs with an LLM, what breaks (placeholders, plurals, tone) and the checks to run before a catalog ships.</description>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <category>i18n</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
