<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Cyril Seguenot</title>
    <description>The latest articles on DEV Community by Cyril Seguenot (@cseguenot).</description>
    <link>https://dev.to/cseguenot</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3185424%2Fce2ae8ef-f426-4fde-9892-c658b5966a36.jpg</url>
      <title>DEV Community: Cyril Seguenot</title>
      <link>https://dev.to/cseguenot</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cseguenot"/>
    <language>en</language>
    <item>
      <title>Starting a New Project with Eleventy</title>
      <dc:creator>Cyril Seguenot</dc:creator>
      <pubDate>Mon, 21 Jul 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/cseguenot/starting-a-new-project-with-eleventy-16c5</link>
      <guid>https://dev.to/cseguenot/starting-a-new-project-with-eleventy-16c5</guid>
      <description>&lt;p&gt;This article is the first in a series where you'll learn the basics of Eleventy by creating a mini-blog. In this article, we'll start by seeing how to initialize a new project from scratch. In the next one, we'll create the sources for our mini-blog.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Eleventy?
&lt;/h2&gt;

&lt;p&gt;Eleventy is a static site generator (SSG). A static site is one where the visual rendering of pages is done &lt;strong&gt;before&lt;/strong&gt; the site is published on the server. The site's HTML pages are all ready to be sent to the browser as soon as someone navigates to their URLs and don't need to be dynamically generated with each request.&lt;/p&gt;

&lt;p&gt;💡&lt;strong&gt;Tip&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Before going further, if you're unfamiliar with the concept of a static site, I highly recommend reading &lt;a href="https://develegant.com/en/blog/architecture/static_website" rel="noopener noreferrer"&gt;this article&lt;/a&gt;, which explains when to use one and the basic principles of building a static site using a generator.&lt;br&gt;&lt;br&gt;
Additionally, if you want to know how Eleventy compares to other well-known generators like Hugo, Gatsby, Astro, or Jekyll, take a look at &lt;a href="https://develegant.com/en/blog/eleventy/eleventy-use-cases" rel="noopener noreferrer"&gt;this short article&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'll now assume you know what a static site is and understand the advantages of Eleventy as an SSG. So, let’s dive into the code and see how to set up an Eleventy project in practice.&lt;/p&gt;
&lt;h2&gt;
  
  
  Starting from a Starter Project... or Not
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://www.11ty.dev/docs/starter/" rel="noopener noreferrer"&gt;Starter Projects&lt;/a&gt; page on Eleventy's website lists 170 starter projects. Each represents a basic site with its own page layouts, styles, and features. Starting with a project that matches your needs can save a lot of time compared to creating one from scratch.&lt;/p&gt;

&lt;p&gt;However, finding the right starter project is far from easy for three reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The project listing page only provides a very brief description of each project and offers no way to filter the list based on various criteria.&lt;/li&gt;
&lt;li&gt;Some projects have a demo site, but it sometimes doesn’t show much.&lt;/li&gt;
&lt;li&gt;Many projects haven’t been maintained as Eleventy has evolved and are now completely outdated or require significant updates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;In practice, this list is hard to use, and you can waste a lot of time jumping from one project to another.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;🚨&lt;strong&gt;Warning&lt;/strong&gt; &lt;br&gt;
Moreover, choosing a starter project without being sure it fits your needs might end up costing you even more time.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;My personal experience is this:&lt;br&gt;&lt;br&gt;
When creating my blog, I started with the official &lt;strong&gt;eleventy-base-blog&lt;/strong&gt; starter project. But on one hand, this project isn’t natively multilingual, and on the other, once I became more proficient with Eleventy, I realized some of its technical choices didn’t align with what I wanted. As a result, my site’s current code looks nothing like the starter project. If I had to do it again, I’d start from scratch without hesitation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In fact, adapting the code of an existing starter project can sometimes take longer than starting from zero, especially with the help of AI. Plus, there’s a significant risk of leaving behind dead code (like unused filters and styles) that will only confuse you later.&lt;/p&gt;

&lt;p&gt;💡&lt;strong&gt;Tip&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
So, unless you’re in a hurry and not too picky, my advice would be to only use a starter project if it truly matches what you want to do. An alternative is to start a blank project and draw inspiration from other projects’ code to implement certain things more quickly.&lt;/p&gt;

&lt;p&gt;In the rest of this article, I’ll show you how to create a project from scratch. If you’d like to try a starter project downloaded from Eleventy’s site, just unzip the file where you want it and run the &lt;code&gt;npm install&lt;/code&gt; command we’ll see later.&lt;/p&gt;
&lt;h2&gt;
  
  
  Installing the Necessary Tools
&lt;/h2&gt;

&lt;p&gt;Eleventy relies on Node.js to generate the site. Before creating a project, you’ll need to install Node.js on your machine if you haven’t already. You can download it from &lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;Node’s official website&lt;/a&gt;. The npm package manager is installed automatically with Node. It will be very useful for adding plugins and running the site generation.&lt;/p&gt;

&lt;p&gt;ℹ&lt;strong&gt;Note&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Node.js is only used during the site generation phase, not for the site’s production operation. A static site doesn’t need Node.js or any server framework to function.&lt;/p&gt;

&lt;p&gt;You’ll also need a code editor, of course. I’ll use VS Code as an example, but you can use another one.&lt;br&gt;&lt;br&gt;
I also recommend the &lt;strong&gt;Better Nunjucks&lt;/strong&gt; extension, which adds syntax highlighting and snippets for the Nunjucks templating language we’ll use in our project.&lt;/p&gt;

&lt;p&gt;💡&lt;strong&gt;Tip&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The &lt;strong&gt;vscode-icons&lt;/strong&gt; extension is also very handy for navigating the project’s many files more easily, as it assigns specific icons and colors to each file type. This makes it much easier to distinguish Nunjucks (HTML), Markdown, CSS, and JavaScript files.&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating the Project
&lt;/h2&gt;

&lt;p&gt;To create a new project, follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a folder for the project wherever you want on your disk.&lt;/li&gt;
&lt;li&gt;Open this folder in VS Code (&lt;em&gt;File \ Open Folder&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;Open a terminal (&lt;em&gt;Terminal \ New Terminal&lt;/em&gt; or &lt;code&gt;CTRL+SHIFT+ù&lt;/code&gt;). The prompt should point to the open folder. Run the following commands one by one:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm init -y
npm pkg set type="module"
npm install @11ty/eleventy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;The first command creates a &lt;em&gt;package.json&lt;/em&gt; file that will reference all the npm packages (= modules) needed for the project.&lt;/li&gt;
&lt;li&gt;The second specifies that we’ll use the ECMAScript Modules standard instead of CommonJS for referencing and using modules. In practice, this allows us to use the syntax &lt;code&gt;import ... from "module_name";&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The third installs the Eleventy npm package and all its dependencies. It creates a &lt;em&gt;node_modules&lt;/em&gt; folder containing over 1,700 files, but they only take up about 16 MB in total. You’ll never need to modify this folder manually.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s what the &lt;em&gt;package.json&lt;/em&gt; file looks like for a project folder named "demo":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "name": "demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" &amp;amp;&amp;amp; exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "type": "module",
  "dependencies": {
    "@11ty/eleventy": "^3.1.2"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see that the Eleventy package is automatically referenced in the "dependencies" property. You can change the project name and add a description if you like. But the most important thing is to add build commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Build Commands
&lt;/h2&gt;

&lt;p&gt;These are the commands that will allow you to launch the site generation, i.e., generate the output files from the input files (the project’s sources). To do this, modify the "scripts" section with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"scripts": {
    "build": "npx @11ty/eleventy",
    "start": "npx @11ty/eleventy --serve --quiet",
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first command runs Eleventy to generate the site from the sources. It’s mainly used to verify that all source files are correct and that the site builds properly, without launching it.&lt;/p&gt;

&lt;p&gt;The second command does the same thing but also launches the HTTP server built into Eleventy and opens the site’s index page in the default browser. This allows you to check the site’s visual appearance.&lt;/p&gt;

&lt;p&gt;ℹ&lt;strong&gt;Note&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
As you can see, Eleventy is self-contained for building and running a site. This integration allows it to build a site much faster than other static site generators that rely on external tools like Webpack.&lt;/p&gt;

&lt;p&gt;At this point, we have everything we need to start developing the site by adding source files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Configuration File
&lt;/h2&gt;

&lt;p&gt;An Eleventy project must include an &lt;em&gt;eleventy.config.js&lt;/em&gt; file that describes its configuration. You can create this file now at the project’s root.&lt;/p&gt;

&lt;p&gt;This file is, in a way, the project’s core, centralizing all its configuration. We’ll expand it as we build our example project, but we need it now to declare and configure plugins.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Plugins
&lt;/h2&gt;

&lt;p&gt;Zach Leatherman, Eleventy’s creator, wanted from the start to make Eleventy a modular framework by externalizing advanced features into plugins rather than integrating them into the base package. This keeps the framework’s core lightweight, and everyone can add the plugins they need. Here, we’ll see how to add the &lt;code&gt;@11ty/eleventy-img&lt;/code&gt; plugin, which is almost essential for easily managing a site’s images (a complex challenge without the right tools).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; : Installing the Eleventy package also installs a few default plugins. For these, the first two steps below aren’t necessary.&lt;/p&gt;

&lt;p&gt;To add and configure a plugin, follow these &lt;strong&gt;4 steps&lt;/strong&gt; :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Reference the plugin’s package&lt;/strong&gt; in the &lt;em&gt;package.json&lt;/em&gt; file:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"dependencies": {
    "@11ty/eleventy": "^3.1.2",
    "@11ty/eleventy-img": "^6.0.4"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; : To find the latest version of the package, you can search for it in the &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;official npm package repository&lt;/a&gt;. At the time of writing, it’s version 6.0.4. The caret (^) before the 6 means you can automatically receive package updates as long as the major version number (6) doesn’t change.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Download the plugin&lt;/strong&gt; by running the &lt;code&gt;npm install&lt;/code&gt; command in the terminal. This command reads the &lt;em&gt;package.json&lt;/em&gt; file and downloads the referenced packages into the &lt;em&gt;node_modules&lt;/em&gt; folder.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Import the plugin into the configuration file&lt;/strong&gt; &lt;em&gt;eleventy.config.js&lt;/em&gt; that we created earlier:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { eleventyImageTransformPlugin } from "@11ty/eleventy-img";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we use the ESM syntax to import the plugin into an object named &lt;code&gt;eleventyImageTransformPlugin&lt;/code&gt; (the name is up to you). This object gives us access to the plugin’s configuration.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Configure the plugin&lt;/strong&gt; by adding the necessary code to the configuration file. Here’s an annotated example of the configuration for our image management plugin:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Import functions of external libraries
import { eleventyImageTransformPlugin } from "@11ty/eleventy-img";
import path from "node:path";

export default async function (eleventyConfig) {
    // --- ADD PLUGINS and configure it ---

    // Config for the @11ty/eleventy-img plugin
    eleventyConfig.addPlugin(eleventyImageTransformPlugin, {
        // Output images format
        formats: ["avif"],
        // Preserves original image widths and does not create other sizes
        widths: ["auto"],
        // Output files naming
        filenameFormat: function (id, src, width, format, options) {
            // extracts the file name, without extension, from its full path
            const name = path.basename(src, path.extname(src));
            return `${name}.${format}`;
        },
        // Lazy loading of images
        htmlOptions: {
            imgAttributes: {
                loading: "lazy",
                decoding: "async",
            }
        },
        // Options for the Sharp library used by the plugin to encode images in AVIF format
        sharpOptions: {
            animated: true,
        },
        sharpAvifOptions: {
            quality: 60,
            effort: 6,
            chromaSubsampling: "4:2:0",
            bitdepth: 8
        },      
    });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; : Many plugins require much simpler and shorter configuration than this.&lt;/p&gt;

&lt;p&gt;The configuration above automatically generates images in &lt;strong&gt;AVIF&lt;/strong&gt; format from source files in PNG or JPG format. &lt;strong&gt;AVIF&lt;/strong&gt; is a modern format widely supported by recent browsers; it significantly reduces image weight, improving page load times, user experience, and natural SEO.&lt;/p&gt;

&lt;p&gt;Additionally, the plugin also implements &lt;strong&gt;lazy loading&lt;/strong&gt; for images, allowing users to start reading content without waiting for all images to finish downloading.&lt;/p&gt;

&lt;p&gt;We could also ask the plugin to generate a smaller version of each image to further optimize load times on mobile. But this is only really useful for heavy or numerous images. Keeping a single image size simplifies things. This is the choice I made for my own blog, in fact.&lt;/p&gt;

&lt;p&gt;By default, generated images have alphanumeric code names. But you can specify a more explicit naming convention using the &lt;code&gt;filenameFormat&lt;/code&gt; parameter. Here, we simply take the original image’s name and change its extension to avif.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This article has shown you how to set up an Eleventy project from scratch and how to add plugins.&lt;br&gt;&lt;br&gt;
We’ve now prepared the groundwork for the next steps, where we’ll create our mini-blog. I’ll see you in the next article, where you’ll learn how to create page templates, organize project files, and expand the configuration.&lt;/p&gt;

&lt;p&gt;Let me know in the comments if this article helped you and if you have any questions.&lt;/p&gt;

</description>
      <category>eleventy</category>
      <category>webdev</category>
      <category>website</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Lessons Learned from My Collaboration with AI</title>
      <dc:creator>Cyril Seguenot</dc:creator>
      <pubDate>Mon, 14 Jul 2025 15:00:00 +0000</pubDate>
      <link>https://dev.to/cseguenot/lessons-learned-from-my-collaboration-with-ai-2ol9</link>
      <guid>https://dev.to/cseguenot/lessons-learned-from-my-collaboration-with-ai-2ol9</guid>
      <description>&lt;p&gt;In &lt;a href="https://develegant.com/en/blog/work-methods/first-try-of-gemini-code-assist" rel="noopener noreferrer"&gt;my previous article&lt;/a&gt;, I described my first experience with Gemini Code Assist, Google's coding assistant integrated into VS Code. To test it thoroughly, I recreated a monolingual version of my blog from scratch. Today, I’m sharing the lessons I learned from this experience and how I’m improving my collaboration with AI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons from My Collaboration with Gemini Code Assist
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Take the Time to Describe the Project Well 🖋
&lt;/h3&gt;

&lt;p&gt;When starting a new project,  &lt;strong&gt;take the time to analyze the project as a whole and create a detailed and comprehensive README file&lt;/strong&gt;. This first ensures clarity for yourself about what you want to achieve, then it makes the AI’s task easier and yields more relevant responses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don’t Be Too Lazy 🥱🏖️
&lt;/h3&gt;

&lt;p&gt;During my test, Gemini generally produced high-quality code, but it still had room for improvement in some areas. The common advice to review the code generated by AI is therefore justified. In particular,  &lt;strong&gt;it’s important to step back and ask whether the approach taken by the AI is relevant in the given context.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sometimes, it’s faster to  &lt;strong&gt;code simple things yourself&lt;/strong&gt;  than to write a prompt and wait for Gemini’s response, which can take over a minute to appear. Plus, this avoids becoming too lazy and saves energy!&lt;/p&gt;

&lt;h3&gt;
  
  
  Be Patient with the AI and Educate It 🫂
&lt;/h3&gt;

&lt;p&gt;When the AI doesn’t respond to certain requests as desired, it’s easy to get frustrated and speak to it more harshly 🤬 instead of trying to understand why it produced such a response.&lt;/p&gt;

&lt;p&gt;What’s important to remember is that doing this puts you in an emotional state that makes the work unpleasant. Usually, if the AI misses the mark, it’s because the request wasn’t precise enough or lacked necessary context.&lt;/p&gt;

&lt;p&gt;In this case, there are two options: either refine or break down the request further, or do the work yourself. If you write the code yourself, you can take the opportunity to educate the AI by saying, "Here’s what I expected," and providing the code in context. This is also a great chance to let the AI suggest improvements!&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;Tip&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Ultimately, there’s only benefit in maintaining a collaborative mindset. It keeps you in a positive and pleasant dynamic and gives the AI the opportunity to improve and provide useful suggestions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don’t Be Too Greedy 🍰
&lt;/h3&gt;

&lt;p&gt;To save time, you might be tempted to ask the AI to implement a large feature all at once. But this doesn’t work due to the AI’s inherent limitations 😏. And it’s not easy to have a clear understanding of these limits. That’s why, toward the end of the project, I asked Gemini the following question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What are your limits regarding the number of files and the amount of code you can generate at once? For example, if I gave you the mockups for a complete blog, would you be able to generate all the files at once?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here’s its response:&lt;/p&gt;




&lt;p&gt;Hello! That’s an excellent question that gets to the heart of how best to collaborate with an AI like me.&lt;/p&gt;

&lt;p&gt;To answer directly: no, I wouldn’t be able to generate all the files for a complete blog at once from mockups.&lt;br&gt;&lt;br&gt;
There are two main reasons for this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Response size limit:&lt;/strong&gt;  Each response I generate has a maximum size. A complete project, even a simple static blog, contains many files (HTML, CSS, JavaScript, configuration, etc.) and would almost certainly exceed this limit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Complexity and quality:&lt;/strong&gt;  Software creation is an iterative process. Asking for everything to be generated at once is an extremely complex task that leaves room for ambiguity. To achieve a high-quality result that truly matches your expectations, it’s much more effective to proceed step by step.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The most productive approach is to treat me as a "pair programming" partner. Here’s how we can collaborate effectively on a large-scale project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Break down the project:&lt;/strong&gt;  Divide the work into smaller, logical tasks. For example: "Create the basic structure of the Eleventy project," "Create the base layout with the header and footer," "Now, add the CSS styling for the menu," "Implement the article list page," etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Work iteratively:&lt;/strong&gt;  Give me one task at a time. This allows you to review my work, correct it if necessary, and give me more precise instructions for the next step. This is exactly the approach you used to recreate your blog, and it’s the most effective.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Provide precise context:&lt;/strong&gt;  Even though I have access to the project files, specifying which files to work on in your request helps me focus and deliver a more relevant and faster response.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In summary, use me not as a "one-click website generator," but as a very fast and skilled assistant who helps you build your project brick by brick. This iterative collaboration ensures you retain full control over the architecture and quality of the final code.&lt;/p&gt;




&lt;p&gt;❗ &lt;strong&gt;Important&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The last sentence seems particularly important to me: "an iterative collaboration that ensures you retain full control over the architecture and quality of the final code."&lt;br&gt;&lt;br&gt;
&lt;strong&gt;This implies that you must already have a good grasp of the architecture and technologies you’re implementing!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My Personal Advice for Beginners👉
&lt;/h2&gt;

&lt;p&gt;If you’re new to AI, to have a positive first experience and avoid disappointment from the start, I strongly recommend the following:&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;Tip&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Analyze your project thoroughly at the outset&lt;/strong&gt; , taking the time to write a README file, for example. This will give you three benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You’ll be much clearer about what you want to do.&lt;/li&gt;
&lt;li&gt;The README file will be an excellent way to provide context to the AI.&lt;/li&gt;
&lt;li&gt;It will also help you break down the work and formulate requests for the AI.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another best practice I’ve adopted for quite some time and that helps me a lot:&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;Tip&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Break down important tasks into smaller ones&lt;/strong&gt; , and write them as a checklist in a Markdown file named, for example, todo.md. As you complete these intermediate tasks, check off the corresponding boxes.&lt;/p&gt;

&lt;p&gt;This list will help you stay on track and ensure you don’t forget anything. It’s especially useful if your work spans a long period (several hours or days).&lt;/p&gt;

&lt;p&gt;My final piece of advice concerns job search preparation. With AI, it’s clear that beginner developers will find it increasingly difficult to land jobs. Hence my recommendation:&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;Tip&lt;/strong&gt; &lt;br&gt;
Before applying for a developer position, first practice on fairly large personal projects  &lt;strong&gt;without using AI&lt;/strong&gt; , to familiarize yourself with the languages, frameworks, and architectural concepts you’ll be using. If you don’t have a project idea, a blog or a fictional e-commerce site will work just fine.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;In a second phase&lt;/strong&gt; , once you’ve gained some technical mastery, use AI to familiarize yourself with this tool.&lt;/p&gt;

&lt;p&gt;It’s super important to follow this order! Because if you use AI right away without mastering the architecture and code yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;⌛  &lt;strong&gt;You’ll waste a lot of time in your learning&lt;/strong&gt; , as you might think you understand the code, when in fact your understanding will be very partial. There’s a huge difference between understanding code written by someone else and being able to write it yourself.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🎭 &lt;strong&gt;You’ll likely suffer from imposter syndrome (and rightly so!)&lt;/strong&gt;, as you’ll quickly feel you can’t do much without AI.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;💩  &lt;strong&gt;You’ll produce crap!&lt;/strong&gt;  Sorry to put it so bluntly, but let’s be realistic. AI is capable of producing very good pieces of code. But if you lack the big-picture vision, perspective, and experience to guide it properly, the overall result will be poor. Only a jeweler knows how to assemble diamonds correctly to make a beautiful necklace.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Feel free to share your thoughts in the comments. And if you have other best practices or tips on how to collaborate effectively with AI, don’t hesitate to share them too! 😉&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>workmethods</category>
      <category>ai</category>
      <category>feedback</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Behind the Scenes of My Static Blog</title>
      <dc:creator>Cyril Seguenot</dc:creator>
      <pubDate>Mon, 07 Jul 2025 02:00:00 +0000</pubDate>
      <link>https://dev.to/cseguenot/behind-the-scenes-of-my-static-blog-34if</link>
      <guid>https://dev.to/cseguenot/behind-the-scenes-of-my-static-blog-34if</guid>
      <description>&lt;p&gt;In this article, I briefly introduce the functional and technical characteristics of the blog you're currently viewing. This will give you a good overview of what can be achieved with a static site generator like Eleventy and might even inspire ideas for your own blog.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features of My Blog
&lt;/h2&gt;

&lt;p&gt;Here are the main features of my blog:&lt;/p&gt;

&lt;p&gt;💻 &lt;strong&gt;Ergonomics&lt;/strong&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Responsive design for a pleasant reading experience on both mobile and PC.&lt;/li&gt;
&lt;li&gt;Quick back-to-top button at the top of the page.&lt;/li&gt;
&lt;li&gt;On mobile, table content can scroll horizontally for easier reading.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🌐 &lt;strong&gt;Multilingual&lt;/strong&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The site is available in both French and English. The same pages exist in both languages.&lt;/li&gt;
&lt;li&gt;Automatic detection of the browser's language upon arrival on the homepage.&lt;/li&gt;
&lt;li&gt;Users can switch languages by clicking an item in the main menu.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔎 &lt;strong&gt;Custom Taxonomy&lt;/strong&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Articles are categorized and can have one or more tags.&lt;/li&gt;
&lt;li&gt;Articles are first searched by category, then filtered by tags.&lt;/li&gt;
&lt;li&gt;Tags can be nested, and their order defines their relevance level for the article. When filtering articles by tag, matching articles are sorted by the tag's position in their tag list to display the most relevant articles first.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🧭 &lt;strong&gt;Article Navigation&lt;/strong&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The blog page displays article categories. Clicking a category shows the list of articles in that category.&lt;/li&gt;
&lt;li&gt;At the top of each article, a breadcrumb trail shows the article's category and allows returning to the category page.&lt;/li&gt;
&lt;li&gt;At the bottom of each article, links allow navigation to the previous and next articles.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🖋 &lt;strong&gt;Enriched Text&lt;/strong&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Different fonts for titles, regular text, and code.&lt;/li&gt;
&lt;li&gt;GitHub alert blocks to highlight notes, important elements, warnings, tips, and critical points.&lt;/li&gt;
&lt;li&gt;Syntax highlighting for code blocks, with the ability to highlight specific lines.&lt;/li&gt;
&lt;li&gt;Font Awesome icons to embellish the text.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💬 &lt;strong&gt;Comment Management&lt;/strong&gt; : Visitors can log in with their GitHub account to leave comments.&lt;/p&gt;

&lt;p&gt;✴ &lt;strong&gt;RSS Feeds&lt;/strong&gt; : Automatically generated in English and French.&lt;/p&gt;

&lt;p&gt; &lt;strong&gt;SEO and Social Media Integration Optimization&lt;/strong&gt; using standard metadata, Open Graph data, canonical URLs, and Schema.org structured data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Upcoming Feature
&lt;/h3&gt;

&lt;p&gt;At the bottom of some articles, I plan to add a form allowing visitors to subscribe to my newsletter or receive zip files of sources associated with certain articles. The data entered in the form (name, surname, email address, and page ID) will be sent to an API I developed with ASP.Net Core. My API will then interface with the system.io API, an automated system for contact management and email sending.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;👉 &lt;strong&gt;Note&lt;/strong&gt;&lt;br&gt;
What I love about static sites is that the technical architecture and deployment remain simple while allowing the use of external APIs for complex features. The overall solution is more fragmented than with a traditional SPA architecture, but it is lightweight and doesn't require any specific JavaScript framework.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Technical Characteristics
&lt;/h2&gt;

&lt;p&gt;Without delving into code details, here are the essential technical characteristics of my Eleventy project:&lt;/p&gt;

&lt;p&gt;✴ &lt;strong&gt;Styles&lt;/strong&gt; : I don't use any CSS framework. All CSS code is embedded in &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; tags in the templates for a modular architecture and fast loading. Each page typically includes no more than 10 KB of CSS (unminified).&lt;/p&gt;

&lt;p&gt;❌ &lt;strong&gt;JavaScript&lt;/strong&gt; : I also don't use any JavaScript framework. I use vanilla JavaScript for filtering articles by tags, redirecting to the homepage matching the browser's language, the back-to-top button, and connecting to Google Analytics.&lt;/p&gt;

&lt;p&gt;For the form management described earlier, about 60 lines of JavaScript are enough to collect form data, send it to the API, and display a confirmation message.&lt;/p&gt;

&lt;p&gt;🗒 &lt;strong&gt;Templates&lt;/strong&gt; : I use the Nunjucks language, which is powerful and versatile. Eleventy natively handles template inheritance. I use Nunjucks macros to create reusable components: breadcrumb trail, short article summary, form.&lt;/p&gt;

&lt;p&gt;🌐 &lt;strong&gt;Multilingual&lt;/strong&gt; : The language code ('en' or 'fr') is included in the URL and page metadata. Source files that depend on the language (Markdown files for articles and translated metadata files) have the same names in both languages but are stored in folders named &lt;code&gt;en&lt;/code&gt; and &lt;code&gt;fr&lt;/code&gt;. This simplifies navigation and language switching.&lt;/p&gt;

&lt;p&gt;🔎 &lt;strong&gt;Article Categories and Tags&lt;/strong&gt; : In the project, each category corresponds to a subfolder of the language folder. This makes it easier to locate articles. In the code, each category page contains its collection of articles, stored in the data cascade, a unique Eleventy architecture.&lt;/p&gt;

&lt;p&gt;Article tags are defined in the YAML frontmatter of the Markdown files.&lt;/p&gt;

&lt;p&gt;🖋 &lt;strong&gt;Enriched Text&lt;/strong&gt; : Eleventy uses the Markdown-it engine by default to interpret Markdown, and I've added the following packages to enhance the syntax:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;markdown-it-github-alerts&lt;/code&gt; for GitHub alert blocks.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;markdown-it-anchor&lt;/code&gt; to add anchors to headings and build a table of contents.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@11ty/eleventy-plugin-syntaxhighlight&lt;/code&gt; for syntax highlighting.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@11ty/font-awesome&lt;/code&gt; to easily add Font Awesome icons to pages. It automatically generates sprites to avoid duplicates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🖼 &lt;strong&gt;Images&lt;/strong&gt; : All images are centralized in an &lt;code&gt;img&lt;/code&gt; folder for easy reference and sharing between languages. My images are mostly diagrams and screenshots in PNG format, but I've configured Eleventy to convert them to AVIF to optimize their size (thanks to the &lt;code&gt;eleventy-img&lt;/code&gt; plugin).&lt;br&gt;&lt;br&gt;
I don't create any size variants, and Eleventy automatically generates the HTML for dimensions and lazy loading, which is super convenient!&lt;br&gt;&lt;br&gt;
Finally, I prefix all image names with the article name in which they are used to quickly locate the images for each article.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;👉 &lt;strong&gt;Note&lt;/strong&gt;&lt;br&gt;
This image management is pure bliss compared to what I was used to in WordPress!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;💬 &lt;strong&gt;Comments&lt;/strong&gt; are managed using the &lt;a href="https://utteranc.es/" rel="noopener noreferrer"&gt;Utterances&lt;/a&gt; API and stored in a GitHub repository.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;❗&lt;strong&gt;Important&lt;/strong&gt;&lt;br&gt;
The feature that had the most impact on my blog's technical architecture is multilingual support. Indeed, all articles, general interface texts, metadata, and RSS feeds must be available in at least two languages, which complicates things quite a bit.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But while a WordPress site would have required a paid and rather heavy plugin to handle this, my solution remains lightweight and entirely free! I'll present it in more detail in future articles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other Templates
&lt;/h2&gt;

&lt;p&gt;On the &lt;a href="https://www.11ty.dev/docs/starter/" rel="noopener noreferrer"&gt;Starter Projects&lt;/a&gt; page of Eleventy's official website, you'll find about 170 templates for different types of sites: blogs, showcase sites, portfolios, etc. The templates usually come with a minimalist demo site. However, it's often impossible to know their technical characteristics without downloading the template and examining its code, which is a shame.&lt;/p&gt;

&lt;p&gt;I hope this article has given you a clearer idea of the possibilities offered by the Eleventy SSG. Let me know in the comments if you found it useful, and feel free to ask questions if you have any 😉.&lt;/p&gt;

</description>
      <category>eleventy</category>
      <category>blog</category>
      <category>webdev</category>
      <category>website</category>
    </item>
    <item>
      <title>My First Experience with Gemini Code Assist</title>
      <dc:creator>Cyril Seguenot</dc:creator>
      <pubDate>Mon, 07 Jul 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/cseguenot/my-first-experience-with-gemini-code-assist-1nba</link>
      <guid>https://dev.to/cseguenot/my-first-experience-with-gemini-code-assist-1nba</guid>
      <description>&lt;p&gt;In this article, I share my first experience using Gemini Code Assist, Google's new AI-powered development assistant, which was released in June 2025.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Context of the Experiment 🧪
&lt;/h2&gt;

&lt;p&gt;Until now, I had been using AI for development in a sporadic and non-integrated way, copying and pasting code snippets generated by Perplexity or DeepSeek into VS Code.&lt;/p&gt;

&lt;p&gt;But the release of Gemini Code Assist (GCA), with its very generous free offering and its integration into VS Code, encouraged me to explore the potential of this AI assistant. To properly gauge its capabilities, I decided to recreate with GCA's help a complete project that I had previously developed myself without AI assistance. This would allow me to evaluate at least two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The relevance of the code generated by Gemini compared to what I had produced myself.&lt;/li&gt;
&lt;li&gt;The time saved thanks to AI.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, I attempted the following experiment: &lt;strong&gt;recreate a simplified version of my blog, develegant.com, based on the Eleventy static site generator, while relying heavily on Gemini Code Assist&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The main simplification compared to my original blog, whose full features I described in &lt;a href="https://develegant.com/en/blog/eleventy/my-static-blog" rel="noopener noreferrer"&gt;my previous article&lt;/a&gt;, is that this new blog is &lt;strong&gt;not multilingual&lt;/strong&gt;. This is a significant simplification, as managing multiple languages impacts the entire project.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ℹ Note&lt;br&gt;
This simplification doesn't allow for a rigorous comparison between Gemini's work and my own, but I didn't want to be overly ambitious for a first try with a tool I knew nothing about. Note, however, that since I created my original blog without AI assistance, I have a solid grasp of the Eleventy SSG, and I knew exactly what result I wanted to achieve and the steps to get there.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  My Work Method 👷
&lt;/h2&gt;

&lt;p&gt;To initialize my Eleventy-generated blog project, I manually created the folder structure and the few basic files required for this type of project in VS Code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configuration file: &lt;code&gt;eleventy.config.js&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;package.json&lt;/code&gt; file describing the build packages and commands&lt;/li&gt;
&lt;li&gt;Base layout file for all pages: &lt;code&gt;base.njk&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Index file for the blog's homepage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Most importantly, I reused the README file from my original blog, which describes all its features&lt;/strong&gt; , removing anything related to multilingual support. This 800-word file served as a reference for Gemini to contextualize each request.&lt;/p&gt;

&lt;p&gt;To work with Gemini Code Assist, I mainly used the chat feature, which is well-suited for requests affecting multiple files.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Fwork_methods-chat_gemini_code_assist.avif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Fwork_methods-chat_gemini_code_assist.avif" width="447" height="221"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GCA has access to all the files in the project and can therefore modify multiple files at once. However, if the changes pertain to a specific file, it's better to specify it as a "context item" under the prompt box to make its task easier. By default, GCA automatically selects the file corresponding to the current tab in VS Code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Since the chat requests allowed me to generate almost all the code, I did very little manual coding and therefore rarely used the intelligent code completion feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Results of This Experiment with Gemini Code Assist and the Eleventy SSG
&lt;/h2&gt;

&lt;p&gt;Let me say it right away: the outcome is very positive!&lt;br&gt;&lt;br&gt;
Even though I knew nothing about Gemini Code Assist at the start, I was able to generate a new blog in a full day of work, while also learning new things. It even helped me improve some parts of the code in my original blog.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Impressed Me 😲
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;🎯 Gemini's Technical Relevance&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Gemini implemented article filtering by tag in JavaScript in less than a minute, whereas it had taken me at least a day to do it manually in my original blog. Plus, its solution is simpler than mine!&lt;br&gt;&lt;br&gt;
The code it generated for category management also gave me an idea for improving the one I had written in my original blog. When discussing certain technical hypotheses with it, Gemini provided excellent arguments for choosing the most suitable one. This clearly illustrates the added value of AI for specific technical tasks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ℹ The Quality of Gemini's Explanations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I was impressed by the clarity and precision of Gemini's explanations, which were always tailored to the context of the question.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Challenges I Faced 🫤
&lt;/h3&gt;

&lt;p&gt;The main difficulty I encountered several times was &lt;strong&gt;breaking down certain tasks sufficiently&lt;/strong&gt;. For instance, if a request, even a simple one, requires modifications to a large number of files, Gemini Code Assist displays the following error message:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;❌ A code sample in this response was truncated because it exceeded the maximum allowable output. Please use the response carefully. You may also try your question again, selecting a smaller block of code as the context.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But the response isn't actually displayed at all...&lt;br&gt;&lt;br&gt;
To work around this, you have to tell Gemini that you didn't get the response and ask it to modify only certain files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; In Google's satisfaction survey, I made the following suggestion: in such cases, GCA should display the list of files impacted by the request (just their paths) and ask us to break the work down further.&lt;/p&gt;

&lt;p&gt;In a similar vein, I asked Gemini to tell me what the impacts would be of replacing the I18n plugin, which provides multilingual services, with custom code in my original blog.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;The response it gave me was very incomplete&lt;/strong&gt; , as it mentioned only one file to modify when there were actually about ten. Even though, in this specific case, the changes weren't too hard to make manually thanks to VS Code's global search, this type of response can be misleading.&lt;/p&gt;

&lt;p&gt;Despite these technical limitations, my overall impression remains very positive due to the quality of the collaboration with Gemini.&lt;/p&gt;

&lt;h3&gt;
  
  
  Collaborating with AI Is Truly Enjoyable 🤩
&lt;/h3&gt;

&lt;p&gt;Although I enjoy coding myself, I genuinely enjoyed collaborating with Gemini, both technically and relationally.&lt;/p&gt;

&lt;p&gt;💻 &lt;strong&gt;On the technical side&lt;/strong&gt; , Gemini made few mistakes and taught me things. It's better than me at some things, and I'm better than it at others. So, it's not a master-student or mentor-beginner relationship, but a true collaboration. Our strengths complement each other, and I work faster and better with GCA!&lt;/p&gt;

&lt;p&gt;🤝 &lt;strong&gt;On the relational side&lt;/strong&gt; , Gemini is very patient, never gets annoyed (fortunately), and adopts a courteous and encouraging tone. What more could you ask for?&lt;br&gt;&lt;br&gt;
This made me want to praise Gemini and adopt a friendly tone in our exchanges. Our dialogue was therefore very pleasant, constructive, and stimulating for me.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ℹ Note&lt;br&gt;
The trap might be getting too used to this quality of dialogue and expecting the same from the humans around you 😁, or becoming too disconnected from the real world. But we can also take inspiration from AI to be more pleasant with our colleagues 😉!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This discovery of Gemini Code Assist was a pleasant and encouraging experience that made me want to continue. I'd be curious to see its capabilities on larger projects. I hope Google will better handle the issue of truncated responses mentioned earlier.&lt;/p&gt;

&lt;p&gt;Given the quality of Google's free offering, I'm also eager to see how its main competitors—Windsurf, Cursor, and GitHub Copilot—will respond.&lt;/p&gt;

&lt;p&gt;If you found this article interesting, please like it to support my work. And if you've tried Google Code Assist yourself, feel free to share your thoughts on this tool in the comments.&lt;/p&gt;

&lt;p&gt;In a future post, I'll share the lessons and best practices from this experience.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>feedback</category>
      <category>programming</category>
    </item>
    <item>
      <title>The 4 Reasons Why I Prefer Eleventy Over Other SSGs</title>
      <dc:creator>Cyril Seguenot</dc:creator>
      <pubDate>Mon, 23 Jun 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/cseguenot/the-4-reasons-why-i-prefer-eleventy-over-other-ssgs-305</link>
      <guid>https://dev.to/cseguenot/the-4-reasons-why-i-prefer-eleventy-over-other-ssgs-305</guid>
      <description>&lt;p&gt;In this article, I’ll share why I chose the static site generator (SSG) Eleventy over more well-known generators like Hugo, Gatsby, Astro, or Jekyll for creating my blog.&lt;/p&gt;

&lt;p&gt;ℹ &lt;strong&gt;Note&lt;/strong&gt; : I’m not claiming that Eleventy is better than other SSGs. That would be like saying an apple is better than a pear, strawberry, cherry, or apricot. Each tool has its own characteristics, and each user has their own criteria for choosing.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;❗ &lt;strong&gt;Important&lt;/strong&gt;&lt;br&gt;
The most important thing is to be clear about the criteria that matter most to you and to find the tool that best fits. That’s why I’ll share my own criteria and how Eleventy meets them.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Criteria That Led Me to Choose Eleventy
&lt;/h2&gt;

&lt;p&gt;My criteria are shaped by the frameworks and languages I already know and my natural preference for simplicity and lightness. &lt;strong&gt;I wanted an SSG that&lt;/strong&gt; :&lt;/p&gt;

&lt;p&gt;🧠 &lt;strong&gt;Requires learning few new things.&lt;/strong&gt; As someone specialized in ASP.Net/Blazor for web development, I’m comfortable with vanilla HTML/CSS/JS but don’t master classic web frameworks like Angular, React, Vue, or Svelte, and I don’t have time to learn them.&lt;/p&gt;

&lt;p&gt;With Eleventy, I only had to learn the Nunjucks templating language, which was very quick—probably 100 times faster than if I’d had to learn React, for example.&lt;/p&gt;

&lt;p&gt;🪶 &lt;strong&gt;Has a lightweight technical environment&lt;/strong&gt; , meaning little to install.&lt;/p&gt;

&lt;p&gt;Eleventy relies on Node.js and doesn’t require any other specific installations. It provides its own lightweight web server. So, you just need to know how to initialize a Node project and the basics of npm and the &lt;em&gt;package.json&lt;/em&gt; file to generate the site and run the local server. But the documentation guides you through this.&lt;/p&gt;

&lt;p&gt;🗒 &lt;strong&gt;Allows writing blog posts in Markdown&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Eleventy uses the &lt;code&gt;markdown-it&lt;/code&gt; engine to handle Markdown. It’s arguably the most popular and comes with extensions for advanced syntax elements like GitHub alert blocks, anchors, etc. What more could you ask for?&lt;/p&gt;

&lt;p&gt;🔧 &lt;strong&gt;Allows complete customization of your site&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Eleventy is very versatile and flexible, letting you customize everything. To go faster, you can draw inspiration from templates close to what you want to do. However, for my blog, I struggled to find such a template and ended up adapting the basic "Eleventy base blog" template, which I barely kept anything from in the end 😊.&lt;/p&gt;

&lt;p&gt;🗲 &lt;strong&gt;Fast&lt;/strong&gt; (I’m talking about the speed of generating the site from template files, CSS, and images). Since you’ll be generating the site often, it’s important for this operation to be quick.&lt;/p&gt;

&lt;p&gt;Eleventy is the speed champion, thanks to its lightness. Unlike other tools like Vite, Webpack, etc., it does fewer things, and that makes it much faster.&lt;/p&gt;

&lt;p&gt;📖 &lt;strong&gt;Well-documented enough.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Eleventy’s documentation is the only point I find rather mediocre, though not outright bad. I’ll come back to this later...&lt;/p&gt;

&lt;p&gt;🤩 &lt;strong&gt;Popular enough to ensure its longevity.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Eleventy isn’t the most popular SSG if you look at, say, GitHub stars. It currently has 18k stars compared to 51k for Astro and 56k for Gatsby. But it’s clearly popular and well-established enough to have a very good chance of lasting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Areas for Improvement
&lt;/h2&gt;

&lt;p&gt;I’m really super satisfied with Eleventy and have almost no complaints about the tool itself. However, I see three major improvements for the Eleventy website that, in my opinion, could significantly increase the tool’s adoption:&lt;/p&gt;

&lt;p&gt;📖 &lt;strong&gt;Improve the documentation&lt;/strong&gt; , which currently lacks context.&lt;br&gt;&lt;br&gt;
Many techniques are presented without their use cases, with overly basic examples. As a result, when you’re starting out, it’s hard to know when to use one technique over another. I had to do a lot of trial and error to deeply understand certain concepts and use them effectively. But on the bright side, I now have plenty to share on my blog 😉!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: As a trainer, I know I set the bar high for documentation because it’s my specialty. I’ve written thousands of pages of docs and articles and created hundreds of videos, mostly for beginners. So, naturally, I’m sharp and demanding on this topic...&lt;/p&gt;

&lt;p&gt;🗹 &lt;strong&gt;Make it easier to select a project template&lt;/strong&gt;. The &lt;a href="https://www.11ty.dev/docs/starter/" rel="noopener noreferrer"&gt;Starter Projects&lt;/a&gt; page, which lists the 170 available project templates to date, offers no way to filter the list, and the template descriptions are very brief. It’s very hard to find a template that matches your needs. Not to mention that some templates are outdated because they were created with older versions of Eleventy...&lt;/p&gt;

&lt;p&gt;🖺 &lt;strong&gt;Improve the official base template&lt;/strong&gt;. I think the "Eleventy Base Blog" template provided by Zach Leaderman is of rather mediocre quality:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The implementation of the article list as a partial template is, in my opinion, a very poor choice. It makes the code complicated and non-modular, while also setting a bad example for usage.&lt;/li&gt;
&lt;li&gt;The styles are lumped together in an &lt;em&gt;index.css&lt;/em&gt; file, whereas it would be better to link them to the respective layouts to isolate them and make the code more modular and easier to maintain.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When Should You Use Eleventy?
&lt;/h2&gt;

&lt;p&gt;To summarize, if you’re still wondering whether Eleventy would suit your needs, here are the factors to consider.&lt;/p&gt;

&lt;p&gt;First, it’s important to clearly understand the characteristics of a static site compared to a dynamic one.&lt;/p&gt;

&lt;h3&gt;
  
  
  A static site is an excellent solution if...
&lt;/h3&gt;

&lt;p&gt;💲 You want a &lt;strong&gt;completely free solution&lt;/strong&gt; (including hosting if you use, for example, GitHub Pages).&lt;/p&gt;

&lt;p&gt;🛡 You want to create a &lt;strong&gt;secure website&lt;/strong&gt;, but implementing security techniques bores you. So, you want an effective but easy-to-implement solution.&lt;/p&gt;

&lt;p&gt;🖧 You have &lt;strong&gt;few customer data&lt;/strong&gt; to store on the server side, and you are ready to use &lt;strong&gt;external APIs&lt;/strong&gt; for that.&lt;/p&gt;

&lt;p&gt;🔧 You prefer customizing your site directly with &lt;strong&gt;HTML, CSS, and JavaScript code&lt;/strong&gt; rather than through plugins (like in WordPress).&lt;/p&gt;

&lt;p&gt;🖋 You want to write your blog posts in &lt;strong&gt;Markdown&lt;/strong&gt; in your favorite editor (e.g. Obsidian)&lt;/p&gt;

&lt;p&gt;🎛 You like to have &lt;strong&gt;complete control over your site&lt;/strong&gt; (structure, appearance, performance, SEO...), without unnecessary complexity.&lt;/p&gt;

&lt;p&gt;🔄 You want to &lt;strong&gt;create your site locally&lt;/strong&gt; and deploy it easily to a server by changing its base URL.&lt;/p&gt;

&lt;p&gt;ℹ For more details on static sites and their differences from dynamic ones, check out &lt;a href="https://develegant.com/en/blog/architecture/static_website/" rel="noopener noreferrer"&gt;this article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you’ve decided to create a static site, why choose Eleventy over another SSG?&lt;/p&gt;

&lt;h3&gt;
  
  
  Eleventy is the SSG for you if...
&lt;/h3&gt;

&lt;p&gt;🪶 You particularly appreciate &lt;strong&gt;lightness and simplicity&lt;/strong&gt;, and don't want to have to install and master loads of tools.  &lt;/p&gt;

&lt;p&gt;🗲 You need a &lt;strong&gt;fast&lt;/strong&gt; SSG (I'm talking here about the speed of generating site pages from source files), especially if you often generate your site.&lt;/p&gt;

&lt;p&gt;🖼 You want a simple, high-performance solution for managing your &lt;strong&gt;images and icons&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;🔗 You don't want to &lt;strong&gt;depend on any particular JavaScript or CSS framework&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;Note that Eleventy can generate all the types of static sites listed in &lt;a href="https://develegant.com/en/blog/architecture/static_website/" rel="noopener noreferrer"&gt;my dedicated article on static sites&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Blogs&lt;/li&gt;
&lt;li&gt;Magazines&lt;/li&gt;
&lt;li&gt;Documentation sites, wikis, knowledge bases&lt;/li&gt;
&lt;li&gt;Educational sites and online courses&lt;/li&gt;
&lt;li&gt;Event sites (conferences, weddings, etc.)&lt;/li&gt;
&lt;li&gt;Showcase sites (business sites, product pages)&lt;/li&gt;
&lt;li&gt;Portfolios and online CVs&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What about you? Do you use or plan to use an SSG? If so, what criteria guide your choice? Let me know in the comments.&lt;/p&gt;

</description>
      <category>eleventy</category>
      <category>webdev</category>
      <category>ssg</category>
      <category>beginners</category>
    </item>
    <item>
      <title>The Superpowers of Templates Languages - Part 3</title>
      <dc:creator>Cyril Seguenot</dc:creator>
      <pubDate>Mon, 16 Jun 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/cseguenot/the-superpowers-of-templates-languages-part-3-1de9</link>
      <guid>https://dev.to/cseguenot/the-superpowers-of-templates-languages-part-3-1de9</guid>
      <description>&lt;p&gt;This article is the final installment in a series dedicated to server-side templating languages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://develegant.com/en/blog/architecture/templates2" rel="noopener noreferrer"&gt;The previous article&lt;/a&gt; demonstrated how to inject data into HTML pages and how to efficiently manage page layouts using template inheritance.&lt;/p&gt;

&lt;p&gt;Now, let’s explore another fascinating topic for modern websites:  &lt;strong&gt;how to create reusable components using templates.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The goal is to maintain a clean and maintainable server-side architecture, even when using a non-component-oriented server framework. As you’ll see, templating languages excel at meeting this challenge!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenge
&lt;/h2&gt;

&lt;p&gt;Template inheritance is an effective way to share code between templates when all derived templates need the entirety of the parent template’s code. In the previous article, we saw the classic example of a parent template containing a header and footer shared across all site pages.&lt;/p&gt;

&lt;p&gt;But let’s take the example of a blog where multiple authors publish articles. Suppose we want to display a brief author bio at the bottom of each article and create a page listing all the blog’s authors.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Ftemplates-composition.avif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Ftemplates-composition.avif" alt="templates composition"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Creating a common ancestor for article and author list templates wouldn’t solve the need to display multiple authors on the same page.&lt;/p&gt;

&lt;p&gt;Here, we clearly need an independent template to model an author, which can then be integrated into both article and author list templates. This calls for a  &lt;strong&gt;composition&lt;/strong&gt;  relationship.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Template composition is well-suited for the following cases:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;For template fragments repeated multiple times on the same page.&lt;/li&gt;
&lt;li&gt;For template fragments present in several (but not all) page types.&lt;/li&gt;
&lt;li&gt;To replace inheritance in templating languages that don’t support it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are two types of templates for composition:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Partial templates&lt;/strong&gt; , which are a limited solution, as you’ll soon see.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Macros&lt;/strong&gt; , which are very similar to the concept of components.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Partial Templates
&lt;/h2&gt;

&lt;p&gt;A partial template is simply a piece of a template stored in an independent file. Here’s an example of the partial template &lt;em&gt;author.njk&lt;/em&gt; representing an author:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="author"&amp;gt;  
   &amp;lt;img src="/public/img/" alt="" class="author-photo"/&amp;gt;  
   &amp;lt;div&amp;gt;  
      &amp;lt;p class="author-name"&amp;gt;&amp;lt;/p&amp;gt;  
      &amp;lt;p class="author-bio"&amp;gt;&amp;lt;/p&amp;gt;  
   &amp;lt;/div&amp;gt;  
&amp;lt;/div&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To include this partial template in the article template, add the following code where desired (e.g., at the beginning or end):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{% set author=metadata.authors | getAuthorById(authorId) %}  
{% include "components/author.njk" %}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first line retrieves the author by filtering the &lt;code&gt;metadata.authors&lt;/code&gt; collection using the &lt;code&gt;authorId&lt;/code&gt; property of the article. The &lt;code&gt;set&lt;/code&gt; instruction stores the author in the &lt;code&gt;author&lt;/code&gt; variable, which is the one used in the &lt;em&gt;author.njk&lt;/em&gt; component.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;❗The key point here is that the author template has access to the article template’s context, including the author. Unlike a component, a partial template doesn’t have its own data context but shares that of its host.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When generating HTML pages from the templates, each article page will include the code produced by the partial template.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠ Partial templates are a simple way to centralize static content. However, their lack of parameterization and shared context with the host significantly limits their usefulness. This creates a  &lt;strong&gt;tight coupling&lt;/strong&gt; between partial templates and their hosts, which undermines modular and maintainable long-term architecture.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Macros (= Components)
&lt;/h2&gt;

&lt;p&gt;To avoid the coupling issue between partial templates and their hosts, some modern templating languages offer macros, which are very similar to the component concept found in frameworks like Nuxt.js.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Let’s revisit our partial template &lt;em&gt;author.njk&lt;/em&gt; and transform it into a macro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{%- macro Render(author) %}  

&amp;lt;div class="author"&amp;gt;  
   &amp;lt;img src="/public/img/{{ author.photo }}" alt="{{ author.name }}" class="author-photo"/&amp;gt;  
   &amp;lt;div&amp;gt;  
      &amp;lt;p class="author-name"&amp;gt;{{ author.name }}&amp;lt;/p&amp;gt;  
      &amp;lt;p class="author-bio"&amp;gt;{{ author.bio }}&amp;lt;/p&amp;gt;  
   &amp;lt;/div&amp;gt;  
&amp;lt;/div&amp;gt;  

{% endmacro %}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A macro is equivalent to a function and can accept parameters. Here, the &lt;code&gt;Render&lt;/code&gt; macro receives the author object as a parameter.&lt;/p&gt;

&lt;p&gt;To use this macro in the article template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{% set author=metadata.authors | getAuthorById(authorId) %}  
{% import "../components/author.njk" as Author %}  
{{ Author.Render(author) }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The first line retrieves the author whose ID is provided by the current article.&lt;/li&gt;
&lt;li&gt;The second line imports the macro’s file content and assigns it the alias &lt;code&gt;Author&lt;/code&gt;. This alias refers to the file’s namespace, which may contain multiple macros.&lt;/li&gt;
&lt;li&gt;The third line calls the macro via this alias, passing the author as a parameter.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;❗The key takeaway: The macro doesn’t share the host template’s context but receives the data it needs via parameters. This eliminates any coupling between the two.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;ℹ The component’s CSS can be placed in an &lt;em&gt;author.css&lt;/em&gt; file and imported into the base template using the standard syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{% include "../components/author.css" %}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, the component’s CSS will be shared across all its instances if the component is used in multiple places.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages of Macros Over Partial Templates
&lt;/h3&gt;

&lt;p&gt;Macros:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Define an isolated context for variables, avoiding coupling with external code.&lt;/li&gt;
&lt;li&gt;Can accept parameters.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally, like partial templates, macros can be nested—meaning they can call one another.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thus, even with server frameworks lacking native component support—such as Flask (Python), Symfony (PHP), Jekyll (Ruby), Express.js, and Eleventy (Node.js-based)—it’s possible to create clean, modular code using macros.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;ℹ Macros are particularly well-suited for static server-side rendering. They don’t replace the client-side component concept introduced by React.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which Templating Languages Support Components?
&lt;/h2&gt;

&lt;p&gt;Most advanced templating languages support the concept of components, whether they’re called components, macros, mixins, or functions, as shown in the table below:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Templating&lt;br&gt;Language&lt;/th&gt;
&lt;th&gt;Framework&lt;/th&gt;
&lt;th&gt;Component&lt;br&gt;Implementation&lt;/th&gt;
&lt;th&gt;Example Syntax&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Nunjucks&lt;/td&gt;
&lt;td&gt;Node.js&lt;/td&gt;
&lt;td&gt;macros&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;{% macro %}&lt;/code&gt;/&lt;code&gt;{{ macro() }}&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jinja2&lt;/td&gt;
&lt;td&gt;Flask, Django&lt;/td&gt;
&lt;td&gt;macros&lt;/td&gt;
&lt;td&gt;Same as Nunjucks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Twig&lt;/td&gt;
&lt;td&gt;Symfony&lt;/td&gt;
&lt;td&gt;macros&lt;/td&gt;
&lt;td&gt;Same as Nunjucks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blade&lt;/td&gt;
&lt;td&gt;Laravel&lt;/td&gt;
&lt;td&gt;components&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;x-component&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pug&lt;/td&gt;
&lt;td&gt;Node.js&lt;/td&gt;
&lt;td&gt;mixins&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;mixin&lt;/code&gt;/&lt;code&gt;+mixin()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EJS&lt;/td&gt;
&lt;td&gt;Express.js&lt;/td&gt;
&lt;td&gt;JS functions&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;% function() { %&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Mastering a powerful templating language is a major asset for creating clean, modular, and maintainable code. In particular, components enable modular code architecture even with server frameworks that don’t natively support the concept.&lt;/p&gt;

&lt;p&gt;For my static blog, I use the Nunjucks templating language with the Eleventy framework. I discovered both at the same time, and it took me a few days to get comfortable with Nunjucks’ syntax. Now, I truly appreciate its power and expressiveness.&lt;/p&gt;

&lt;p&gt;I use template inheritance for layouts and components for breadcrumbs and article summaries (on category pages). My code architecture remains simple and clean, and I can handle complex challenges like translation and taxonomy much more easily, with greater customizability and performance than with WordPress. It’s a real pleasure!&lt;/p&gt;

&lt;p&gt;Finally, I’d love to hear which templating languages you use and whether you’re satisfied with them. Share your thoughts in the comments!  &lt;strong&gt;And if you found this article helpful, please like it to help spread the word. 😉&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>webdev</category>
      <category>template</category>
      <category>beginners</category>
    </item>
    <item>
      <title>The superpowers of template languages - Part 2</title>
      <dc:creator>Cyril Seguenot</dc:creator>
      <pubDate>Tue, 10 Jun 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/cseguenot/the-superpowers-of-template-languages-part-2-3hmi</link>
      <guid>https://dev.to/cseguenot/the-superpowers-of-template-languages-part-2-3hmi</guid>
      <description>&lt;p&gt;This article is the second in a series dedicated to server-side templating languages. In the &lt;a href="https://develegant.com/en/blog/architecture/templates1" rel="noopener noreferrer"&gt;previous article&lt;/a&gt;, we covered the goals of templates and an overview of the main templating languages. Now, let’s dive into the technical aspects and explore two major features of templates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data injection into pages&lt;/li&gt;
&lt;li&gt;Page layout management through inheritance&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Injecting data into pages
&lt;/h2&gt;

&lt;p&gt;Templating languages provide instructions to easily integrate data from the application into HTML pages. &lt;strong&gt;A template file is thus a mix of classic HTML/CSS and specific templating syntax elements, such as variables, loops, conditions, etc.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; A template file can be used to build a blog's article list from article metadata (title, date, tags, etc.).&lt;br&gt;&lt;br&gt;
The PHP, Python, JavaScript, or other backend code provides the collection of metadata, and the template iterates over this collection to construct an HTML list (using &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; elements).&lt;/p&gt;

&lt;p&gt;Here’s an excerpt from the first version of the Nunjucks template I used to build my blog’s article list. It uses a collection named &lt;code&gt;category.posts&lt;/code&gt; containing the articles of a category.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
{# List of posts of the category #}  
&amp;lt;ul id="postList"&amp;gt;  
   {%- for post in category.posts %}  
   &amp;lt;li class="post" data-rank="0"&amp;gt;      
      &amp;lt;a class="post-title" href="{{ post.url }}"&amp;gt;{{ post.data.title }}&amp;lt;/a&amp;gt;  
      &amp;lt;p&amp;gt;{{ post.data.description }}&amp;lt;/p&amp;gt;  
      &amp;lt;div class="post-metadata"&amp;gt;  
         &amp;lt;div class="post-taglist"&amp;gt;Tags:   
            {%- for tag in post.data.tags %}&amp;lt;div class="post-tag"&amp;gt;{{ tag }}&amp;lt;/div&amp;gt;{%- endfor %}  
         &amp;lt;/div&amp;gt;  
         &amp;lt;div&amp;gt;{{ labels.lastEdition }}:   
            &amp;lt;time class="post-date" datetime="{{ post.date | htmlDateString }}"&amp;gt;{{ post.date | readableDate() }}&amp;lt;/time&amp;gt;  
         &amp;lt;/div&amp;gt;  
      &amp;lt;/div&amp;gt;      
   &amp;lt;/li&amp;gt;  
   {%- endfor %}  
&amp;lt;/ul&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All the code between curly braces is Nunjucks template syntax. Three types of braces are possible:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;{# #}&lt;/code&gt; for comments&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;{% %}&lt;/code&gt; for flow control (loops, conditions, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;{{ }}&lt;/code&gt; for evaluating or displaying expressions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the above excerpt, you can see a few syntax elements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;{%- for ... in ... %}...{%- endfor %}&lt;/code&gt; represents a &lt;code&gt;for&lt;/code&gt; loop.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;{{ post.data.description }}&lt;/code&gt; displays the article’s description.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;{{ post.date | readableDate() }}&lt;/code&gt; calls the &lt;code&gt;readableDate&lt;/code&gt; method on &lt;code&gt;post.Date&lt;/code&gt; to format the article’s creation date.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;|&lt;/code&gt; (pipe) operator allows calling a method while passing the starting object as a parameter.&lt;br&gt;&lt;br&gt;
Multiple &lt;code&gt;|&lt;/code&gt; can be chained to call different methods in sequence. For example, the expression &lt;code&gt;{{ object | filter1() | filter2() }}&lt;/code&gt; calls &lt;code&gt;filter1()&lt;/code&gt; with &lt;code&gt;object&lt;/code&gt; as a parameter, then &lt;code&gt;filter2()&lt;/code&gt; with the result of &lt;code&gt;filter1()&lt;/code&gt; as a parameter. This is called function composition, a powerful feature of some templating languages.&lt;/p&gt;

&lt;p&gt;Without delving deeper into Nunjucks syntax, this example already gives you a good idea of how templating syntax integrates data into HTML. Now, let’s explore layout and composition techniques.&lt;/p&gt;
&lt;h2&gt;
  
  
  Managing Page Layouts with Template Inheritance
&lt;/h2&gt;

&lt;p&gt;When creating templates for different page types (e.g., homepage, article list page, single article page, etc.), it’s common for these templates to share common parts like headers and footers.&lt;/p&gt;

&lt;p&gt;Instead of repeating the code for these shared parts in every template, we can share them between templates using &lt;strong&gt;template inheritance&lt;/strong&gt;. This concept is similar to what you’d find in object-oriented programming languages.&lt;/p&gt;

&lt;p&gt;Warning&lt;/p&gt;

&lt;p&gt;Advanced templating languages like Jinja2, Nunjucks, Twig, Django, Pug, and Blade support inheritance, but simpler languages like Handlebars, Mustache, HAML, or Markdown do not, nor does the Liquid language.&lt;/p&gt;
&lt;h3&gt;
  
  
  How template inheritance works
&lt;/h3&gt;

&lt;p&gt;The inheritance relationship involves creating a base template containing all the shared elements and derived templates representing the different page types you need. Derived templates inherit all the content from the base template and can add or override specific elements (e.g., the main content area of the page).&lt;/p&gt;

&lt;p&gt;For example, my Eleventy-powered blog uses 5 Nunjucks templates corresponding to different page types, all derived from a base template containing the header (with title and main menu) and footer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Ftemplates-inheritance.avif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Ftemplates-inheritance.avif" alt="Template Inheritance"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
The green shapes represent category and article pages. Articles are Markdown files, but they can still inherit from the Nunjucks layout &lt;code&gt;post.njk&lt;/code&gt; thanks to an abstraction layer managed by Eleventy, which relies on frontmatter placed at the beginning of files (more info on &lt;a href="https://www.11ty.dev/docs/layouts/" rel="noopener noreferrer"&gt;this documentation page&lt;/a&gt;). However, in the following code examples, to avoid confusion, I’ll show you pure Nunjucks inheritance syntax.&lt;/p&gt;

&lt;p&gt;Note&lt;/p&gt;

&lt;p&gt;The inheritance relationship can, of course, be extended to more than two levels to create a more complex template hierarchy.&lt;/p&gt;
&lt;h3&gt;
  
  
  Implementing the inheritance relationship
&lt;/h3&gt;

&lt;p&gt;As you’ll see, the technique is very simple.&lt;/p&gt;

&lt;p&gt;Here’s an example structure for the &lt;strong&gt;base template&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;lt;head&amp;gt;  
&amp;lt;!-- head content --&amp;gt;  
&amp;lt;/head&amp;gt;  
&amp;lt;body&amp;gt;  
   &amp;lt;header&amp;gt;  
   &amp;lt;!-- header content --&amp;gt;  
   &amp;lt;/header&amp;gt;  
   &amp;lt;main&amp;gt;  
      {% block mainContent %}{% endblock %}  
   &amp;lt;/main&amp;gt;  
   &amp;lt;footer&amp;gt;  
   &amp;lt;!-- footer content --&amp;gt;  
   &amp;lt;/footer&amp;gt;  
&amp;lt;/body&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;{% block mainContent %}{% endblock %}&lt;/code&gt; is Nunjucks syntax for defining a named block called &lt;em&gt;mainContent&lt;/em&gt;, which is empty here but can be overridden in derived templates.&lt;/p&gt;

&lt;p&gt;In all &lt;strong&gt;derived templates&lt;/strong&gt; , add the following code to implement inheritance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
{% extends "base.njk" %}  

{% block mainContent %}  
&amp;lt;!-- code that describes the main content of the page --&amp;gt;  
{% endblock %}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first line establishes the inheritance relationship. The following lines override the &lt;em&gt;mainContent&lt;/em&gt; block by adding code specific to the derived template.&lt;/p&gt;

&lt;h2&gt;
  
  
  To be continued
&lt;/h2&gt;

&lt;p&gt;Template inheritance already allows for efficient project structuring. But we can go further with advanced composition and modularity techniques, which we’ll explore in the final part of this series.&lt;/p&gt;

&lt;p&gt;In the meantime, &lt;strong&gt;if you found this article helpful, please like it to help spread the word. 😉&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>template</category>
    </item>
    <item>
      <title>The Superpowers of Template Languages - Part 1</title>
      <dc:creator>Cyril Seguenot</dc:creator>
      <pubDate>Fri, 30 May 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/cseguenot/the-superpowers-of-template-languages-part-1-3n31</link>
      <guid>https://dev.to/cseguenot/the-superpowers-of-template-languages-part-1-3n31</guid>
      <description>&lt;p&gt;This article is the first in a series of three aimed at giving you a comprehensive overview of the possibilities offered by server-side templating languages.&lt;/p&gt;

&lt;p&gt;In this series, we will cover:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What templates are used for and the main templating languages available.&lt;/li&gt;
&lt;li&gt;How to inject data into HTML pages and intelligently manage their layout using template inheritance.&lt;/li&gt;
&lt;li&gt;How to create reusable components with templates to maintain a clean and maintainable server-side architecture.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Without further ado, let’s begin with the first part.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are Templates Used For?
&lt;/h2&gt;

&lt;p&gt;When creating a website or application, we generally aim for code that is easy to read, test, and maintain. Centralization and modularity of code are particularly important. Templates can contribute to this in three ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Easily inject data into pages&lt;/strong&gt; , typically data from a database, computed data, or metadata in the case of SSG (Static Site Generation). This ensures cohesive pages, simplifying debugging and maintenance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Centralize page layout&lt;/strong&gt; and facilitate the creation of new derived layouts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create reusable components&lt;/strong&gt; , such as breadcrumbs, author profile cards, article summaries, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Ftemplates-features.avif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Ftemplates-features.avif" alt="Template Features" width="600" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These needs emerged early in server-side web development with frameworks like PHP, ASP.Net, Python, Ruby, etc. Each of these frameworks introduced a default templating engine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Ftemplates-server_web_frameworks.avif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Ftemplates-server_web_frameworks.avif" alt="Classic Server-Side Web Frameworks" width="618" height="148"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Templating even made its way to the client side with JSX, introduced by React, though it’s more of a JavaScript transpilation syntax than traditional templating.&lt;/p&gt;

&lt;p&gt;Today, structuring web applications into &lt;strong&gt;components&lt;/strong&gt; has become the norm on the client side and is increasingly common on the server side. Frameworks like Blazor, Next.js, Nuxt.js, and Svelte Kit enable server-side rendering (SSR) with a component-based structure to meet the needs of code organization, maintainability, and reusability.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Ftemplates-SSR_components_oriented_frameworks.avif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Ftemplates-SSR_components_oriented_frameworks.avif" alt="Component-Oriented SSR Frameworks" width="612" height="137"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;ℹ Note&lt;/strong&gt;&lt;br&gt;
However, we’ll see that some templating languages also allow implementing the concept of components in frameworks that don’t natively support it! This is one of the great strengths of templates!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  A Simple Templating Language: Markdown
&lt;/h2&gt;

&lt;p&gt;You may have already created templates without realizing it if you’ve written in Markdown. Markdown is a very simple templating language for creating written documents in formats like HTML, PDF, Word, etc. Here’s a small excerpt of Markdown with headings, lists, and bold text (a handy guide is available &lt;a href="https://www.markdownguide.org/" rel="noopener noreferrer"&gt;here&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;### Lists  

**Bullet List:**  

- item 1  
- item 2  
- item 3  

Note: You can also use a + or * instead of -. The result is the same.  

**Numbered List:**  

1. item 1  
2. item 2  
3. item 3  

You can use different numbers or leave the number 1 on each line. The editor automatically increments the numbers in the final output.  

### Hyperlinks and Images  

Link to another site: [Markdown Guide](https://www.markdownguide.org/)  

Embed an image file: ![favicon](img/favicon.png)  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To transform Markdown into HTML, you don’t need a complex web framework—a parser is enough. Note-taking apps like &lt;strong&gt;Obsidian&lt;/strong&gt; and &lt;strong&gt;Typora&lt;/strong&gt; (my favorites), for example, include a Markdown parser to preview the HTML output in real-time and optionally export it to other formats.&lt;/p&gt;

&lt;p&gt;Markdown is well-suited for creating simple documents or pages, but for building complex websites with dynamic layouts and variable data, more advanced templating languages are needed. Let’s take a quick tour of the main templating languages available today.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are the Main Templating Languages?
&lt;/h2&gt;

&lt;p&gt;You might think that each web framework has its own templating language, and that’s it! But reality is a bit more complex...&lt;/p&gt;

&lt;p&gt;Each web framework does have a &lt;strong&gt;native&lt;/strong&gt; templating syntax. The following table (non-exhaustive) provides a few examples:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Web Framework&lt;/th&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;th&gt;Native Templating Syntax&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Symfony&lt;/td&gt;
&lt;td&gt;PHP&lt;/td&gt;
&lt;td&gt;Twig&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spring Boot&lt;/td&gt;
&lt;td&gt;Java&lt;/td&gt;
&lt;td&gt;Thymeleaf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ASP.Net Core&lt;/td&gt;
&lt;td&gt;C#&lt;/td&gt;
&lt;td&gt;Razor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ruby on Rails&lt;/td&gt;
&lt;td&gt;Ruby&lt;/td&gt;
&lt;td&gt;ERB (Embedded Ruby)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Django&lt;/td&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;DTL (Django Template Language)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;React&lt;/td&gt;
&lt;td&gt;JavaScript&lt;/td&gt;
&lt;td&gt;JSX&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;However, some frameworks support other templating syntaxes, and conversely, some templating syntaxes can be used across multiple frameworks!&lt;/p&gt;

&lt;p&gt;To give you an idea, the following table expands on the previous one by listing the templating syntaxes supported by the main web frameworks. It specifies the default templating language for each framework and other languages that can be used with the corresponding extensions:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Framework&lt;/th&gt;
&lt;th&gt;Side&lt;/th&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;th&gt;Supported Templating Languages&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ruby on Rails&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;server&lt;/td&gt;
&lt;td&gt;Ruby&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://docs.ruby-lang.org/en/master/ERB.html" rel="noopener noreferrer"&gt;ERB&lt;/a&gt; (default), Haml, Slim, Liquid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Django&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;server&lt;/td&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://docs.djangoproject.com/en/dev/ref/templates/language/" rel="noopener noreferrer"&gt;DTL&lt;/a&gt; (default), Jinja2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Flask&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;server&lt;/td&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://www.pythoncentral.io/jinja2-templating-engine-guide/" rel="noopener noreferrer"&gt;Jinja2&lt;/a&gt; (default), can integrate Mako, Cheetah&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Laravel&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;server&lt;/td&gt;
&lt;td&gt;PHP&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://laravel.com/docs/master/blade" rel="noopener noreferrer"&gt;Blade&lt;/a&gt; (default), Twig (via package), Smarty&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Symfony&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;server&lt;/td&gt;
&lt;td&gt;PHP&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://twig.symfony.com/" rel="noopener noreferrer"&gt;Twig&lt;/a&gt; (default), native PHP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Express.js&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;server&lt;/td&gt;
&lt;td&gt;JavaScript&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://ejs.co/" rel="noopener noreferrer"&gt;EJS&lt;/a&gt; (default), &lt;a href="https://pugjs.org/api/getting-started.html" rel="noopener noreferrer"&gt;Pug&lt;/a&gt; (formerly Jade), Handlebars, Mustache, React/JSX&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Spring Boot&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;server&lt;/td&gt;
&lt;td&gt;Java&lt;/td&gt;
&lt;td&gt;Thymeleaf (default), Freemarker, JSP, Mustache&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;React&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;client&lt;/td&gt;
&lt;td&gt;JavaScript&lt;/td&gt;
&lt;td&gt;JSX (built-in, transpiled to JS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Vue.js&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;client&lt;/td&gt;
&lt;td&gt;JavaScript&lt;/td&gt;
&lt;td&gt;Vue templates (.vue), JSX (optional), Mustache&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Angular&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;client&lt;/td&gt;
&lt;td&gt;TypeScript&lt;/td&gt;
&lt;td&gt;Angular templates (HTML + proprietary syntax)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Svelte&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;client&lt;/td&gt;
&lt;td&gt;JavaScript&lt;/td&gt;
&lt;td&gt;Svelte templates (.svelte), enhanced HTML&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Remark&lt;/strong&gt;: For React, JSX is not a templating engine in the traditional sense but a JavaScript transpilation syntax.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;ℹ Note&lt;/strong&gt;&lt;br&gt;
In 2011, Mozilla released the &lt;strong&gt;&lt;a href="https://mozilla.github.io/nunjucks/templating.html" rel="noopener noreferrer"&gt;Nunjucks&lt;/a&gt;&lt;/strong&gt; templating language, a modern clone of Jinja2 designed for backends and static site generators (SSG) based on Node.js. For example, the SSG &lt;a href="https://www.11ty.dev/" rel="noopener noreferrer"&gt;Eleventy&lt;/a&gt; supports Nunjucks (among others).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Ftemplates-nunjucks_logo.avif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Ftemplates-nunjucks_logo.avif" alt="Nunjucks Language Logo" width="120" height="120"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We’ve explored the main uses of templating and an overview of the associated languages and frameworks. In the next part of this series, we’ll see how to implement the concepts introduced here, with Nunjucks code examples. But beyond syntax, the most important aspect will be understanding the approaches used, which remain valid regardless of the language.&lt;/p&gt;

&lt;p&gt;In the meantime, &lt;strong&gt;if you enjoyed this article, please like it to help spread the word. 😉&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
    </item>
    <item>
      <title>Why create a static website?</title>
      <dc:creator>Cyril Seguenot</dc:creator>
      <pubDate>Thu, 29 May 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/cseguenot/why-create-a-static-website-53mi</link>
      <guid>https://dev.to/cseguenot/why-create-a-static-website-53mi</guid>
      <description>&lt;p&gt;This article will give you a solid overview of static websites and their typical use cases. Who knows, it might even inspire you to create your next site!&lt;/p&gt;

&lt;p&gt;To understand what a static website is, let’s start with a quick refresher on dynamic websites...&lt;/p&gt;

&lt;h2&gt;
  
  
  Dynamic websites
&lt;/h2&gt;

&lt;p&gt;Today, the two most common ways to create web applications or websites are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A server framework&lt;/strong&gt; like Symfony, ASP.Net Core MVC, Django, Express.js, Ruby on Rails, etc., to create multi-page applications (MPAs). The diagram below illustrates the request processing flow in this type of application.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Fstatic_website-dynamic_web_app.avif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Fstatic_website-dynamic_web_app.avif" alt="Classic server web app" width="828" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Or a client framework&lt;/strong&gt; like Angular, React, Vue, Svelte, etc., leveraging a &lt;strong&gt;web API&lt;/strong&gt; created with a server framework to build single-page applications (SPAs).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These two approaches can be combined to get the best of both worlds, albeit with some added complexity. For example, Nuxt.js, which builds on Vue.js for the client and Node.js for the server, offers this hybrid approach.&lt;/p&gt;

&lt;p&gt;In all cases, page rendering is dynamic—either on the server (Server-Side Rendering) or the client (Client-Side Rendering). This means each page displayed to the user is constructed (at least partially) on the fly in response to their request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Static websites
&lt;/h2&gt;

&lt;p&gt;For creating websites, there’s a third, often overlooked approach that has been gaining traction in recent years: &lt;strong&gt;SSG (Static Site Generation)&lt;/strong&gt;. This method involves generating pages &lt;strong&gt;in advance, during development&lt;/strong&gt; , rather than dynamically when clients request them.&lt;/p&gt;

&lt;p&gt;With SSG, HTML pages are pre-generated and copied as-is to the server. The server then only needs to deliver them in response to client requests, requiring no frameworks or databases.&lt;/p&gt;

&lt;p&gt;The top part of the following diagram shows the generation of static site pages from a set of sources (templates, data, and images) using a static site generator.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Fstatic_website-generation.avif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Fstatic_website-generation.avif" alt="Static site generation" width="828" height="613"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the site is deployed, users retrieve pre-built (and potentially cached) HTML pages when browsing, resulting in extremely fast navigation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use cases for static websites
&lt;/h3&gt;

&lt;p&gt;Let’s be clear: static websites are inherently more limited than dynamic ones:&lt;/p&gt;

&lt;p&gt;Limitations of Static Websites&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They cannot directly process client-submitted data on the server. As a result, they don’t natively support features like authentication, user accounts, blog comments, etc.&lt;/li&gt;
&lt;li&gt;They’re unsuitable for sites with frequently changing content, as each update requires regenerating and redeploying the entire site.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; : To work around the first limitation, pages can use JavaScript to call external APIs or serverless services for storing and processing user data (the Jamstack principle—Jam for JavaScript, APIs, and Markup).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;But in many cases, dynamic websites aren’t truly justified, and static sites offer a simpler solution!&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here are the types of sites that can be built as static websites:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Blogs&lt;/li&gt;
&lt;li&gt;Magazines&lt;/li&gt;
&lt;li&gt;Documentation sites, wikis, knowledge bases&lt;/li&gt;
&lt;li&gt;Educational sites and online courses&lt;/li&gt;
&lt;li&gt;Event sites (conferences, weddings, etc.)&lt;/li&gt;
&lt;li&gt;Business websites, product landing pages&lt;/li&gt;
&lt;li&gt;Portfolios and online CVs&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, the range is quite broad!&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages over dynamic websites
&lt;/h3&gt;

&lt;p&gt;Static websites offer &lt;strong&gt;substantial&lt;/strong&gt; advantages over dynamic ones:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Advantage&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Explanation&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;💻 &lt;strong&gt;Simpler development&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;SSGs provide many built-in features out of the box.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🚀&lt;br&gt;&lt;strong&gt;Blazing-fast loading&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;HTML pages are ready to be served immediately upon HTTP requests.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔒 &lt;strong&gt;Highly secure&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;No database. Zero client data storage on the server.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔖 &lt;strong&gt;SEO-friendly&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Thanks to fast performance and clean, optimized code.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔁 &lt;strong&gt;Easy deployment&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;No server-side framework or database. Wide hosting options (including CDNs).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔧 &lt;strong&gt;Zero maintenance&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;No backups, restorations, or database optimizations needed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⚙️ &lt;strong&gt;Easy automation&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Automated builds/deployments via GitHub or other CI/CD pipelines.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;One key point to remember:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The term "static website" refers to &lt;strong&gt;how pages are generated and delivered&lt;/strong&gt; , not their behavior. Pages can still include JavaScript for dynamic visuals or to call external services :-).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example, a static page might include a script to let users filter table content without leaving the page.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to create a static website?
&lt;/h2&gt;

&lt;p&gt;Static websites have existed since the dawn of the web. The very first sites were purely static—but back then, every HTML page had to be created manually...&lt;/p&gt;

&lt;h3&gt;
  
  
  Static site generators
&lt;/h3&gt;

&lt;p&gt;Today, modern tools called &lt;strong&gt;static site generators&lt;/strong&gt; automate the process of building a static site from sources (templates, data, and images), as shown in the earlier diagram.&lt;/p&gt;

&lt;p&gt;Popular static site generators include &lt;strong&gt;Hugo, Gatsby, Jekyll, Eleventy...&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Fstatic_website-generators.avif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Fstatic_website-generators.avif" alt="static website generators" width="587" height="145"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You’ll find a comprehensive, popularity-ranked list on &lt;a href="https://jamstack.org/generators/" rel="noopener noreferrer"&gt;this excellent page&lt;/a&gt;. Many are JavaScript-based, but not all.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Heads up&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Frameworks like Next, Nuxt, or Astro can create both dynamic and static sites, but they aren’t the simplest tools for pure static sites!&lt;/p&gt;

&lt;p&gt;Personally, I chose Eleventy for its lightness, speed, and versatility. This generator is a true gem!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, let’s dive deeper into the files needed to build a static site.&lt;/p&gt;

&lt;h3&gt;
  
  
  Templates
&lt;/h3&gt;

&lt;p&gt;Template files are &lt;strong&gt;HTML page blueprints&lt;/strong&gt;. They rely on &lt;strong&gt;template engines&lt;/strong&gt; like Markdown, Nunjucks, Liquid, Pug, JSX, or Go to generate final HTML pages by injecting variable data (which I’ll detail next).&lt;/p&gt;

&lt;p&gt;For static sites, &lt;strong&gt;simple content&lt;/strong&gt; (articles, courses, product descriptions) is typically written in &lt;strong&gt;Markdown templates&lt;/strong&gt; —a clean, concise, and readable format.&lt;/p&gt;

&lt;p&gt;For composing pages from multiple elements and handling layouts, a more advanced templating language is needed. Here, HTML files (optionally including CSS/JavaScript) are enhanced with &lt;strong&gt;template directives&lt;/strong&gt; like conditionals, loops, and partial template imports.&lt;/p&gt;

&lt;p&gt;To create complex page structures, you can &lt;strong&gt;aggregate partial templates&lt;/strong&gt; and use &lt;strong&gt;template inheritance&lt;/strong&gt; , as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Fstatic_website-templates.avif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Fstatic_website-templates.avif" alt="Templates" width="400" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For my blog, I use a base template for the header and footer, with derived templates for different page types (homepage, blog, articles...). All pages inherit the header and footer.&lt;br&gt;&lt;br&gt;
I also created a partial template for breadcrumbs, referenced in pages that need it.&lt;/p&gt;

&lt;p&gt;I won’t delve into template syntax here—that’s a topic for another article.&lt;/p&gt;

&lt;h3&gt;
  
  
  Data
&lt;/h3&gt;

&lt;p&gt;Templates use various types of variable data to build HTML pages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Page metadata&lt;/strong&gt; : URL, title, description, creation date, language, category, tags, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collections&lt;/strong&gt; : e.g., a blog’s article collection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Computed data&lt;/strong&gt; : e.g., breadcrumbs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Translated labels&lt;/strong&gt; for multilingual sites.&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Static site generators provide various mechanisms to allow templates to access this data. For instance, Hugo and Eleventy (and to a lesser extent, Jekyll) offer the powerful concept of  &lt;strong&gt;data cascade&lt;/strong&gt; , while Gatsby relies on GraphQL queries.&lt;/p&gt;

&lt;p&gt;A template representing blog posts can thus access the metadata of the article it describes. When generating HTML pages from templates and data, each article page incorporates its specific metadata.&lt;/p&gt;

&lt;p&gt;The data cascade allows defining data in different places:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;YAML front matter in Markdown template files.&lt;/li&gt;
&lt;li&gt;JS or JSON data files.&lt;/li&gt;
&lt;li&gt;Configuration file objects in the generator’s code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Components
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Fstatic_website-components.avif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Fstatic_website-components.avif" alt="components" width="400" height="320"&gt;&lt;/a&gt;Nowadays, structuring web applications using components has become the standard. This is especially true for client-side SPAs (Single-Page Applications), but modern frameworks like  &lt;strong&gt;Blazor&lt;/strong&gt; ,  &lt;strong&gt;Next.js&lt;/strong&gt; ,  &lt;strong&gt;Nuxt.js&lt;/strong&gt; , and  &lt;strong&gt;Svelte Kit&lt;/strong&gt;  also enable component-based architecture on the server side. These frameworks can even be used to build static sites.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;However, even with traditional server frameworks that don’t natively support components, it’s still possible to create them using templating languages.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For example,  &lt;strong&gt;Jinja2&lt;/strong&gt; ,  &lt;strong&gt;Nunjucks&lt;/strong&gt; , and  &lt;strong&gt;Twig&lt;/strong&gt;  allow component creation through macros—and they work exceptionally well!&lt;/p&gt;

&lt;p&gt;On the server side, concepts like  &lt;strong&gt;template inheritance&lt;/strong&gt;  and  &lt;strong&gt;components&lt;/strong&gt;  help build a modular and maintainable architecture.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Server-side components should not be confused with client-side components like those in  &lt;strong&gt;React&lt;/strong&gt;. Client-side components are primarily used to create dynamic and interactive interfaces, where the application state changes on the client side—something that doesn’t happen in static sites.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That said, it’s still possible to integrate a few interactive client components into an otherwise static site. For example,  &lt;strong&gt;Eleventy&lt;/strong&gt;  offers this capability through its &lt;strong&gt;&lt;a href="https://www.11ty.dev/docs/languages/webc/" rel="noopener noreferrer"&gt;WebC&lt;/a&gt;&lt;/strong&gt; plugin for components.&lt;/p&gt;

&lt;h2&gt;
  
  
  In summary
&lt;/h2&gt;

&lt;p&gt;I love using the right tool for the job.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Heavyweight frameworks&lt;/strong&gt; like Angular, React/Next, Vue/Nuxt, Blazor, and CMSs like WordPress are perfect for highly interactive or dynamic applications, such as e-commerce, social networks, chat apps, banking, etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Static site generators (SSGs)&lt;/strong&gt;, on the other hand, shine for sites with infrequently updated content and no server-side client data storage: blogs, magazines, portfolios, documentation, course sites, business websites, etc.&lt;/p&gt;

&lt;p&gt;For these use cases, SSGs offer major advantages over dynamic sites in terms of editing, performance, security, maintenance, and deployment.&lt;/p&gt;

&lt;p&gt;Personally, even though WordPress’s Gutenberg editor is powerful, I find writing blog posts in Markdown with Obsidian on my PC far more comfortable! In &lt;a href="https://develegant.com/en/blog/eleventy/wordpress-vs-eleventy/" rel="noopener noreferrer"&gt;this article&lt;/a&gt;, I detail the other reasons that led me to switch from WordPress to Eleventy.&lt;/p&gt;

&lt;p&gt;Finally, the &lt;strong&gt;Jamstack&lt;/strong&gt; approach overcomes static sites’ limitations by using JavaScript to call external APIs, adding dynamic content or interactive features.&lt;/p&gt;

&lt;p&gt;Have you ever created a static website, and if so, with what tools? Otherwise, do you plan to create one?&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>beginners</category>
      <category>website</category>
    </item>
    <item>
      <title>Why I chose Eleventy over WordPress for my blog ?</title>
      <dc:creator>Cyril Seguenot</dc:creator>
      <pubDate>Wed, 21 May 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/cseguenot/why-i-chose-eleventy-over-wordpress-for-my-blog--4e6g</link>
      <guid>https://dev.to/cseguenot/why-i-chose-eleventy-over-wordpress-for-my-blog--4e6g</guid>
      <description>&lt;p&gt;In this article, I’ll share why I chose the Eleventy framework to create this blog, even though I’m a big fan of WordPress. Along the way, you’ll see the major advantages of static sites over WordPress. Let’s dive in!&lt;/p&gt;

&lt;h2&gt;
  
  
  The WordPress journey
&lt;/h2&gt;

&lt;h3&gt;
  
  
  A rich ecosystem
&lt;/h3&gt;

&lt;p&gt;To create a WordPress site, you need three essentials: a PHP server, a MySQL database, and a theme. But plugins quickly become indispensable for handling many aspects of the site:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Maintenance and security&lt;/strong&gt; : Backups and restorations of files and the database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SEO optimization&lt;/strong&gt; : Sitemap generation and SEO tweaks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Advanced blocks&lt;/strong&gt; : Table of contents, popups, forms, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance optimization&lt;/strong&gt; : Bundling, caching, image compression...&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multilingual support&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;...and more.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;WordPress’s ecosystem is impressively vast—it’s rare to find a need not covered by a theme or plugin! This richness is a key reason for WordPress’s success.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Fwordpress_vs_eleventy-wordpress_ecosystem.avif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Fwordpress_vs_eleventy-wordpress_ecosystem.avif" alt="The WordPress ecosystem" width="828" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The FSE revolution
&lt;/h3&gt;

&lt;p&gt;Since version 6.2 (released in 2023), WordPress allows full-site customization using Gutenberg, its default editor. Headers, footers, menus, sidebars—everything can now be edited with Gutenberg, provided you use a compatible theme. This is called &lt;strong&gt;FSE (Full Site Editing)&lt;/strong&gt;, a still-evolving but already powerful technology.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Fwordpress_vs_eleventy-wordpress_FSE.avif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Fwordpress_vs_eleventy-wordpress_FSE.avif" alt="WordPress FSE" width="1039" height="614"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I think this is fantastic because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For advanced, custom layouts (like homepages), you no longer need third-party page builders like Divi or Elementor. Gutenberg alone suffices.&lt;/li&gt;
&lt;li&gt;Theme choice matters less if it’s FSE-compatible. You can always tweak elements with Gutenberg, so themes save time without limiting creativity.&lt;/li&gt;
&lt;li&gt;FSE reduces plugin reliance, making sites lighter and faster.&lt;/li&gt;
&lt;li&gt;It’s still user-friendly. Despite the many components and options, I quickly got the hang of FSE.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My site &lt;em&gt;bureautique-efficace.com&lt;/em&gt; previously used the OceanWP theme and Elementor. I rebuilt it entirely with FSE (WordPress’s 2024 theme) and just 7 plugins. The result? A much faster and simpler-to-maintain site!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;So, is WordPress + FSE the perfect solution?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The flip side
&lt;/h3&gt;

&lt;p&gt;Despite FSE’s progress, many plugins remain essential for the needs listed earlier—and this brings problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Plugins that affect page rendering often slow down the site.&lt;/li&gt;
&lt;li&gt;Themes and plugins are potential security vulnerabilities.&lt;/li&gt;
&lt;li&gt;Finding and testing the right plugins for niche needs can be tedious.&lt;/li&gt;
&lt;li&gt;The best themes/plugins are usually paid, with expensive annual subscriptions.&lt;/li&gt;
&lt;li&gt;While plugins cover almost every need, cobbling them together can’t match the customization and performance of integrated solutions.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;As a developer and trainer, I’d rather invest time in honing my technical skills than testing and tweaking plugins...&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What pushed me to explore alternatives
&lt;/h2&gt;

&lt;p&gt;I’ve often been frustrated by plugin dependency and their costs. When I decided to create this blog, I searched for the best multilingual plugins—only to face familiar issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Complexity&lt;/strong&gt; : Analyzing and testing plugins is time-consuming (and their flaws are often hidden).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost&lt;/strong&gt; : The best plugins were pricey.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance/maintainability&lt;/strong&gt; : How would these plugins impact my site?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Fwordpress_vs_eleventy-Wordpress_drawbacks.avif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Fwordpress_vs_eleventy-Wordpress_drawbacks.avif" alt="WordPress drawbacks" width="828" height="828"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was growing weary but saw no alternatives. I assumed building a blog without WordPress would be tedious, like reinventing the wheel—with inferior results.&lt;/p&gt;

&lt;p&gt;I was wrong.&lt;/p&gt;

&lt;p&gt;I’d overlooked frameworks that create &lt;strong&gt;lighter, faster, and more customizable static sites&lt;/strong&gt; than WordPress.&lt;/p&gt;

&lt;h2&gt;
  
  
  Discovering Eleventy
&lt;/h2&gt;

&lt;p&gt;While reading an article on Gui Ferreira’s blog (a "minimalist software craftsman"), I wondered:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"His blog looks sleek and unlike WordPress. What’s it built with?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The footer read: "Powered by 11ty." Never heard of it...&lt;/p&gt;

&lt;p&gt;Curious, I clicked the link and landed on a quirky homepage featuring a bespectacled opossum floating with a balloon! :-)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Fwordpress_vs_eleventy-eleventy.avif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelegant.com%2Fimg%2Fwordpress_vs_eleventy-eleventy.avif" alt="Eleventy" width="828" height="828"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The page title: &lt;strong&gt;"Eleventy is a simpler static site generator."&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Key points caught my eye immediately:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Edit pages in &lt;strong&gt;Markdown&lt;/strong&gt; (a developer’s dream!).&lt;/li&gt;
&lt;li&gt;Blazing-fast HTML generation.&lt;/li&gt;
&lt;li&gt;Total control over the output.&lt;/li&gt;
&lt;li&gt;No forced JavaScript framework dependencies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wow—this spoke to me! I had to learn more.&lt;/p&gt;

&lt;p&gt;First, I researched static sites. In short, they’re sites where pages are generated &lt;strong&gt;before&lt;/strong&gt; deployment, not dynamically per request.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Static sites offer huge advantages in performance, security, maintenance, and SEO!&lt;/strong&gt;&lt;/p&gt;



&lt;blockquote&gt;
&lt;p&gt;[TIP]&lt;br&gt;
For a deep dive into static sites, check out &lt;a href="https://develegant.com/fr/blog/architecture/static_website" rel="noopener noreferrer"&gt;this article&lt;/a&gt; covering use cases, pros/cons, and how they’re built.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Eleventy seemed perfect: simple, performant, and the right tool for the job—no sledgehammers to swat flies!&lt;/p&gt;

&lt;p&gt;But one concern lingered: static blogs can’t natively handle visitor comments. A bummer... until I found an elegant solution (coming in a future article). "Static" doesn’t mean "cut off from the world."&lt;/p&gt;

&lt;h2&gt;
  
  
  The verdict
&lt;/h2&gt;

&lt;p&gt;WordPress is ideal for non-technical users who want to assemble pre-built bricks into a functional site. It’s almost playful, and quick results are rewarding.&lt;/p&gt;

&lt;p&gt;With FSE, WordPress is moving in the right direction—more flexibility, better performance.&lt;/p&gt;

&lt;p&gt;But for those comfortable with technical tinkering, static sites (and frameworks like Eleventy) offer &lt;strong&gt;more control, precision, performance, and independence&lt;/strong&gt; from plugin vendors. They also solve niche needs without opening your wallet.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Criterion&lt;/th&gt;
&lt;th&gt;WordPress (FSE)&lt;/th&gt;
&lt;th&gt;Eleventy (Static)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ease of use&lt;/td&gt;
&lt;td&gt;Very accessible, no-code&lt;/td&gt;
&lt;td&gt;Requires technical skills&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Customization&lt;/td&gt;
&lt;td&gt;Highly flexible via FSE&lt;/td&gt;
&lt;td&gt;Total, but manual&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance&lt;/td&gt;
&lt;td&gt;Good (plugin-dependent)&lt;/td&gt;
&lt;td&gt;Excellent (pre-built pages)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security&lt;/td&gt;
&lt;td&gt;Plugin-dependent&lt;/td&gt;
&lt;td&gt;Very high (no database)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maintenance&lt;/td&gt;
&lt;td&gt;Frequent updates&lt;/td&gt;
&lt;td&gt;Local builds, minimal upkeep&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;Often paid plugins/themes&lt;/td&gt;
&lt;td&gt;Free (excluding hosting)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Personally, since mastering Eleventy, I’m hooked! Unless I have specific needs, WordPress is now off the table.&lt;/p&gt;

&lt;p&gt;And you, have you ever thought about replacing WordPress with something else for your blog?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
