# complite > A complete Eleventy blogging solution. SEO / GEO / AI ready. complite is a batteries-included Eleventy 3 template for fast, minimal blogs. Zero client-side JavaScript by default, full dark mode, PHP-powered search, contact form with bot protection, and a sane content model so you can focus on the writing. --- ## Welcome to complite Date: May 20, 2026 Author: Your Name Tags: post, eleventy, getting-started You're looking at the first post of a new site built with complite — a complete Eleventy blogging solution for people who write in Markdown and ship static HTML. This post is a quick tour of what's included and how to get started. ## What you get Out of the box, complite ships with: - **Eleventy 3** with ESM configuration and Liquid templates - **Five layouts**: home, blog archive, article, author profile, and a generic page - **Dark mode** that works without JavaScript, using a three-layer CSS priority system - **RSS feed** with an XSL stylesheet for human-readable browser rendering - **JSON-LD** structured data for search engines - **Full-text search** powered by SQLite and PHP with fuzzy matching - **Syntax highlighting** via Prism, loaded only on pages that need it - **Contact form** backed by a PHP handler with honeypot spam protection ## Project structure The source lives in `src/`. Data files in `src/_data/` control the site's identity. Layouts and partials live in `src/_includes/`. Blog posts go in `src/blog/posts/`. ```text src/ ├── _data/ # site.json, users.json, person.json ├── _includes/ │ ├── layouts/ # base, home, article, blog, author, contact, page │ └── partials/ # nav, footer, post-card, pagination, ... ├── blog/posts/ # your markdown posts ├── static/ # CSS, favicons, images └── index.liquid # homepage ``` ## Writing your first post Create a new `.md` file in `src/blog/posts/` with front matter like this: ```yaml --- title: "My First Post" description: "A short description for search engines and social cards." date: 2026-05-21 author: admin tags: - writing --- ``` Then write your content in Markdown. Eleventy handles the rest — layout, navigation, RSS, sitemap, and social cards are all automatic. ## Configuration Edit three files to make complite yours: 1. **`src/_data/site.json`** — site title, URL, description, email 2. **`src/_data/users.json`** — author profiles (name, bio, social links) 3. **`src/_data/person.json`** — JSON-LD identity for search engines ## Running locally ```bash npm install npm run dev ``` The dev server starts at `http://localhost:8080` with live reload. For production builds: ```bash npm run build ``` This minifies HTML, inlines CSS/JS, and outputs everything to `_site/`. --- That's the tour. Delete this post when you're ready, or keep it as a reference. Happy writing. --- ## Why Static Site Generators Still Matter Date: May 15, 2026 Author: Your Name Tags: post, ssg, essay Every few years someone declares static site generators dead. And every few years, the sites that load fastest, break least, and survive the longest turn out to be static HTML. Here's why that keeps being true. ## Speed is a feature A static site is a collection of pre-built HTML files served directly by a web server. There's no database query, no server-side rendering, no cold start. The time between request and first byte is the time it takes to read a file from disk. This matters more than most developers think. Every 100ms of load time costs engagement. A static site served from a CDN routinely delivers sub-100ms response times worldwide. ## Security by absence The most secure code is no code. A static site has no server-side runtime, no database, no admin panel, no login form. The entire attack surface is a web server serving files. There are no SQL injection vulnerabilities because there is no SQL. There are no authentication bypasses because there is no authentication. There are no plugin vulnerabilities because there are no plugins running on the server. ## Version control is your CMS Every piece of content is a file in a Git repository. This gives you: - **History**: every change is tracked, attributable, and reversible - **Branching**: draft posts live on branches, merged when ready - **Collaboration**: pull requests for content review - **Backup**: the repository *is* the backup No database dumps. No export tools. No migration scripts. `git clone` gives you the entire site. ## The build step is a feature, not a tax Critics call the build step a disadvantage. It's actually where the magic happens: - Markdown is compiled to semantic HTML - Templates generate consistent layouts - Images are optimized and resized - CSS and JavaScript are minified - Sitemaps, RSS feeds, and social cards are created automatically All of this happens once at build time, not on every request. The result is a set of files that can be served by any web server, cached aggressively, and deployed anywhere. ## When not to use a static site Static sites are wrong for: - Applications that require real-time user interaction (chat, dashboards) - Content that changes per-user (personalization, authentication) - Sites where non-technical editors need a visual CMS For blogs, documentation, portfolios, landing pages, and any content that changes less often than it's read — static is the right default. --- The web started static. The best parts of it still are. --- ## Dark Mode Done Right: A CSS-First Approach Date: May 10, 2026 Author: Your Name Tags: post, css, design, tutorial Most dark mode implementations fall into one of two camps: CSS-only (respects system preference but offers no toggle) or JavaScript-only (requires JS to work at all). This starter uses a three-layer approach that combines the best of both. ## The three layers ### Layer 1: System preference (lowest priority) The base layer uses the `prefers-color-scheme` media query. This works without any JavaScript: ```css @media (prefers-color-scheme: dark) { :root { --bg: oklch(15% 0.008 250); --fg: oklch(95% 0.005 250); /* ... all dark mode variables */ } } ``` If your operating system is set to dark mode, the site follows automatically. No JavaScript required. ### Layer 2: JavaScript data attribute (overrides system) When a user explicitly chooses a theme via the toggle, JavaScript sets a `data-theme` attribute on `` and saves the choice to `localStorage`: ```css :root[data-theme="dark"] { --bg: oklch(15% 0.008 250); /* ... dark variables */ } :root[data-theme="light"] { --bg: oklch(99% 0.002 250); /* ... light variables */ } ``` This overrides the system preference because attribute selectors have higher specificity than media queries in the cascade. ### Layer 3: CSS `:has()` radio check (highest priority) The theme toggle is implemented as a pair of radio buttons. When a radio button is checked, CSS `:has()` applies the theme immediately — no JavaScript needed for the visual change: ```css :root:has(#mode_dark:checked) { --bg: oklch(15% 0.008 250); /* ... dark variables */ } :root:has(#mode_light:checked) { --bg: oklch(99% 0.002 250); /* ... light variables */ } ``` The `:has()` selector has the highest specificity, so it overrides both the system preference and the JavaScript attribute. ## Why radio buttons instead of a button? Traditional theme toggles use a `