<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:base="https://dmartinez.xyz/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    
    <title>Writing · Daniel Martínez Fernández</title>
    <link>https://dmartinez.xyz/</link>
    <atom:link href="https://dmartinez.xyz/rss.xml" rel="self" type="application/rss+xml" />
    <description>Notes on what I build and what I learn along the way.</description>
    <language>en</language>
    <item>
      <title>Rebuilding my site with Eleventy and zero frameworks</title>
      <link>https://dmartinez.xyz/writing/rebuilding-with-eleventy/</link><description>&lt;h2&gt;Why not a framework&lt;/h2&gt;
&lt;p&gt;I write React and Next.js every day at work. For a personal site with a few pages and a handful of posts, a client-side framework adds JavaScript the reader never needs. Static HTML loads fast, and there is nothing to keep patched.&lt;/p&gt;
&lt;h2&gt;Why Eleventy over Hugo&lt;/h2&gt;
&lt;p&gt;Hugo was the other option. It builds quickly and bundles TypeScript out of the box, but its Go templates were one more thing to learn. Eleventy is JavaScript all the way down, so the config, filters and data files are code I already know how to debug.&lt;/p&gt;
&lt;h2&gt;TypeScript with esbuild&lt;/h2&gt;
&lt;p&gt;Eleventy does not compile TypeScript by itself. A few lines in &lt;code&gt;eleventy.config.js&lt;/code&gt; run esbuild before every build:&lt;/p&gt;
&lt;figure class=&quot;code-window&quot;&gt;&lt;figcaption class=&quot;code-window__bar&quot;&gt;&lt;span&gt;eleventy.config.js&lt;/span&gt;&lt;span&gt;js&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;code-window__scroll&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; esbuild &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;esbuild&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;eleventyConfig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Bundle and minify the site&#39;s TypeScript&lt;/span&gt;
  eleventyConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;eleventy.before&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; esbuild&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;entryPoints&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;src/assets/ts/main.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;outfile&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;_site/assets/main.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;minify&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  eleventyConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addPassthroughCopy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;src/assets/css&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;src&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/figure&gt;
&lt;h2&gt;What the browser gets&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;HTML generated at build time, one file per page&lt;/li&gt;
&lt;li&gt;One small script, loaded only where a page needs it&lt;/li&gt;
&lt;li&gt;One stylesheet, with custom properties for the light and dark themes&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Results&lt;/h2&gt;
&lt;p&gt;I ran Lighthouse 13.5 against the live homepage on October 24, 2026. The scores are performance, accessibility, best practices and SEO:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Desktop:&lt;/strong&gt; 100 / 100 / 100 / 100. Largest contentful paint at 0.4 s.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mobile:&lt;/strong&gt; 99 / 100 / 100 / 100. Largest contentful paint at 1.7 s on Lighthouse’s simulated slow 4G connection.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Both:&lt;/strong&gt; 0 ms total blocking time, no layout shift, 6 requests and 61 KiB in total.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The two web fonts make up about 52 KiB of that. The HTML, stylesheet and script together come to under 9 KiB.&lt;/p&gt;
&lt;p&gt;The first run scored lower: 88 for performance on mobile, 96 for best practices and 90 for SEO. Four small fixes closed the gap:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Self-hosted fonts.&lt;/strong&gt; The Google Fonts stylesheet blocked rendering while the browser connected to two more domains. Serving the font files from my own server and preloading them moved mobile contentful paint from 3.1 s to 1.3 s.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A favicon.&lt;/strong&gt; Without one, the browser asked for &lt;code&gt;/favicon.ico&lt;/code&gt;, got a 404 and logged a console error.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Absolute &lt;code&gt;hreflang&lt;/code&gt; URLs.&lt;/strong&gt; The links between the English and Spanish versions used paths like &lt;code&gt;/es/&lt;/code&gt;, and &lt;code&gt;hreflang&lt;/code&gt; requires full URLs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Accessible names that match the visible text.&lt;/strong&gt; The language switch showed “es” while screen readers heard “Leer en español”, and the theme toggle showed “dark” while they heard “Switch to light mode”. Now each label starts with the word on screen.&lt;/li&gt;
&lt;/ul&gt;
</description><pubDate>Fri, 23 Oct 2026 00:00:00 +0000</pubDate>
      <dc:creator>Daniel Martínez Fernández</dc:creator>
      <guid>https://dmartinez.xyz/writing/rebuilding-with-eleventy/</guid>
    </item>
  </channel>
</rss>