All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
0.5.0 - 2026-05-15
Added
mix sayfa.cleantask to remove the build output directorySayfa.Blocks.Cloudshared module for tag/category cloud renderingSayfa.Blocks.Helpersshared block utilitiesSayfa.ContentTypes.Basemacro to reduce content type boilerplate
Changed
- Refactored
CategoryCloudandTagCloudto use the newCloudmodule - Refactored all built-in content types (
Article,Note,Page,Project,Talk) to useBasemacro - Dev server modules (
Plug,Rebuilder,Watcher,Supervisor) refactored for clarity - Builder, Config, Template, Validator, Feed, Excerpt, Tailwind, SEO, and Image modules updated
- Default theme CSS and JS synced
Removed
- Deprecated
Sayfa.Blocks.RecentArticlesblock (superseded byRecentContentin v0.4.0)
Fixed
- Added
scroll-padding-topto prevent anchor links hiding behind the sticky header - Trimmed dead CSS classes and fixed JS selectors in the default theme
- Replaced
is-hiddenworkaround with proper Tailwindhiddenclass - Fixed reading progress bar selector guard, ToC scroll-spy selector, and copy-link null guard
- Modernized JS:
const/let, arrow functions,datasetAPI - Resolved Elixir 1.19 compiler warnings
- Made slug generation resilient in
mix sayfa.gen.content - Ensured
sayfa.gen.contenttests write to temp directories
Dependencies
- Bumped
mdexfrom 0.11.6 to 0.12.2 - Bumped
plug_cowboyfrom 2.8.0 to 2.8.1 - Bumped
credofrom 1.7.16 to 1.7.18
0.4.2 - 2026-03-06
Breaking Changes
heroblock removed:Sayfa.Blocks.Herohas been removed from the built-in block registry. The default home layout no longer renders a hero section — site title and description are already visible in the header, so the hero was redundant. Users who relied on@block.(:hero, ...)in custom layouts should replace it with content from theirindex.mdbody or a custom block. The.home-hero-sectionand.hero-subtitleCSS classes are also removed from the default theme.
0.4.1 - 2026-03-06
Fixed
- Hot reload CSS loss: Asset fingerprinting is now skipped during
mix sayfa.serve. Every hot reload previously accumulated old fingerprinted files indist/assets/(e.g.main.abc.abc.css), causing the browser to request a URL that no longer existed after the next rename. Dev mode useslocation.reload()for cache freshness so fingerprinting is unnecessary there. - Fingerprinted file accumulation on repeated
mix sayfa.buildruns:digest_assetsnow reads the previousmanifest.jsonand deletes all previously fingerprinted files before rescanningdist/assets/. This prevents old*.hash.css/*.hash.jsfiles from accumulating across repeated production builds.
Added
:fingerprintbuild option: Passfingerprint: falsetoSayfa.Builder.build/1to skip asset digesting (e.g. for custom dev tooling). Defaults totruesomix sayfa.buildbehaviour is unchanged.
0.4.0 - 2026-03-06
Breaking Changes
Postcontent type renamed toArticle:Sayfa.ContentTypes.Postis nowSayfa.ContentTypes.Article. Content files inposts/directories should move toarticles/, URLs change from/posts/{slug}/to/articles/{slug}/, and thelayout: "post"front matter key should be updated tolayout: "article". Therecent_postsandrelated_postsblocks are renamed torecent_articlesandrelated_articlesrespectively.
Added
- Asset digesting: The builder now computes content hashes for compiled CSS and JS files and rewrites references in the base layout to cache-busted URLs (e.g.
app-a1b2c3d4.css), enabling long-lived caching in production. - Language switcher
variant:assign: Render multiple language switcher instances on the same page with unique element IDs by passingvariant: :desktoporvariant: :mobile. The generated element ID becomeslang-switcher-desktop/lang-switcher-mobileinstead of the defaultlang-switcher. - Language switcher home fallback: The language switcher no longer hides when a page has no verified translation — it falls back to the target language's home path (
/or/lang/) so the switcher is always visible. AGENTS.md: Guidance file for AI coding agents working on the Sayfa codebase.
Changed
- Default theme rewritten with Catppuccin Latte/Mocha palette: The entire default theme CSS has been rewritten using the Catppuccin color system. Latte (light) and Mocha (dark) palettes auto-switch via
prefers-color-scheme. All palette tokens are registered as--color-ctp-*Tailwind utilities via@theme inline. Feed tooltip contrast meets WCAG AA in both modes. - Semantic CSS component classes: All block modules now emit semantic component class names (e.g.
.header-shell,.content-card,.toc-nav) instead of raw Tailwind utilities. Styles are centralized inmain.cssand reference--color-ctp-*/--site-*CSS variables for theming. - Breadcrumb block redesigned as a back-link: The full
<nav>breadcrumb trail is replaced with a minimal← Sectionback link for section content. Bare pages (nourl_prefix) emit only the JSON-LDBreadcrumbListstructured data without a visible link. List and home pages produce no output. - Arabic font loading stabilized:
@font-facedeclarations for Arabic fonts now load reliably across builds.
0.3.3 - 2026-02-28
Added
- Dedicated project and talk layouts: Projects and talks now render with full-featured layouts (
project.html.eex,talk.html.eex) instead of the bare page layout — displaying date, updated date, categories and tags as clickable archive links, copy link button, reading time, table of contents, cover image, and related content. The talk layout additionally surfacesevent,video, andslidesfront matter fields with dedicated UI. - Feed subscription links on list pages: Type index pages, tag archives, and category archives now display inline Atom/JSON feed links below the heading, with tooltip labels. Corresponding
<link rel="alternate">tags are also emitted in<head>. - JSON feeds for tag and category archives:
Feed.generate_json_for_tag/3andFeed.generate_json_for_category/3added; the builder now writes.jsonfeed files alongside the existing.xmlfiles for every tag and category archive. subscribe_via_atomandsubscribe_via_jsontranslation keys: Added to all 14 built-in language files (en, tr, de, es, fr, it, pt, ja, ko, zh, ar, ru, nl, pl).- Footer feed links: The footer block now renders inline Atom and JSON feed subscription links next to the copyright line.
Changed
- Project default layout:
Sayfa.ContentTypes.Projectnow uses"project"as its default layout (was"page"). - Talk default layout:
Sayfa.ContentTypes.Talknow uses"talk"as its default layout (was"page"). - Per-language feeds removed: The builder no longer generates separate
/tr/feed.xml(and similar) files per language — the root/feed.xmlalready includes all languages. DateFormat.format/3: Now acceptsnil(returns""),DateTime,NaiveDateTime, and ISO 8601 strings in addition toDatestructs.- Scaffold templates:
mix sayfa.newproject and talk example files updated — projects gain adate:field; talks renameslides_url:toslides:to match the new layout.
0.3.2 - 2026-02-28
Fixed
- Mobile code block overflow: Code blocks no longer cause horizontal page scroll on mobile —
max-width: 100%is now applied topreelements inside.prose-content, andmax-w-fulladded to the JS-enhanced code copy wrapper
0.3.1 - 2026-02-27
Changed
- Elixir requirement: Updated minimum Elixir version from
~> 1.18to~> 1.19 - Dependency updates: Updated core dependencies to latest stable versions — mdex
~> 0.11, yaml_elixir~> 2.12, xml_builder~> 2.4, plug_cowboy~> 2.8, file_system~> 1.1, ex_doc~> 0.40
Fixed
mix sayfa.newversion constraint: New sites were scaffolded with{:sayfa, "~> 0.1"}— now correctly uses"~> 0.3"- ExDoc module groups: Added 8 missing blocks to the docs module groups —
CategoryCloud,RecentContent,CopyLink,Breadcrumb,LanguageSwitcher,RelatedPosts,RelatedContent,Analytics
0.3.0 - 2026-02-27
Added
- Logo support in header: Set
logo: "/images/logo.svg"in site config to replace the plain text title with an image in the header block. Optionally setlogo_dark:for a separate dark-mode variant — the light logo gainsdark:hiddenand the dark logohidden dark:blockTailwind classes automatically. Falls back to text title when neither key is present. - Print styles: Built-in CSS print styles for clean printed pages
- View transitions: Smooth page transitions using the View Transitions API
- Highlight theme: Configurable syntax highlighting theme support
related_contentblock: Show related content across different content typesanalyticsblock: Built-in analytics integration block- Responsive images hook: Automatic
srcsetgeneration for responsive images mix sayfa.gen.imagestask: Image optimization pipeline scaffold (vips/ImageMagick)- Content validation: Validates required front matter fields during build and reports errors
- Prev/next navigation: Automatic previous/next content links generated by the builder
mix sayfa.gen.langtask: Add language support to an existing site- Multilingual content generation:
mix sayfa.newnow generates content files for non-default languages
Changed
- Output directory renamed: Default build output directory changed from
outputtodist - Nixpacks: Replaced Docker with Nixpacks configuration in the new site template
Fixed
- Image optimization script: Removed unsupported
--formatflag fromvips thumbnailcalls (format is inferred from file extension) - Image optimization script: Prevent duplicate processing — skip
*_1200.*files and already-optimized sources on reruns
0.2.0 - 2026-02-23
Added
- Internationalization: Translation system with 14 built-in languages (English, Turkish, German, Spanish, French, Italian, Portuguese, Japanese, Korean, Chinese, Arabic, Russian, Dutch, Polish)
- New Blocks: Language switcher, category cloud, related posts, breadcrumb, copy link
- Image Helper: Responsive image module with srcset, lazy loading, and WebP support
- Excerpt Extraction: Automatic content summaries for list pages and feeds
- Reading Progress: Visual progress bar and ToC scroll-spy for long articles
- Mix Tasks:
mix sayfa.gen.contentandmix sayfa.gen.layoutgenerators - SEO Enhancements: JSON-LD structured data, hreflang tags for multilingual content
- Multilingual Archives: Tag and category archive pages with language support
- Self-Hosted Fonts: Eliminate Google Fonts dependency for better privacy
- Deployment Support: Nixpacks config and GitHub Pages workflow
- Component Classes: Reusable Tailwind utilities for consistent styling
- Expanded Social Icons: Support for 24 social media platforms
Fixed
- Language switcher mobile functionality with unique IDs for desktop/mobile variants
- Localized home URL detection in header active state
- Translated reading time labels across all languages
- TailwindCSS typography plugin for proper prose styling
- URL generation with correct trailing slash handling
Changed
- Redesigned default theme layouts with Tailwind utilities
- Simplified block implementations to use component classes
- DevServer dependencies now required (no longer optional)
0.1.1 - 2026-02-11
Fixed
- Guard DevServer modules behind compile-time checks so the package works without optional dependencies installed
- Ensure application startup in Mix tasks (
sayfa.build,sayfa.serve)
0.1.0 - 2025-02-11
Initial release of Sayfa — a static site generator built in Elixir.
Added
Core
- Markdown parsing via MDEx (Rust NIF) with syntax highlighting
- YAML front matter extraction with known fields +
metacatch-all map - Two-struct content pipeline (
Content.Raw->Content) - Slug generation from filenames with date prefix stripping
- Collections API: filter by type/tag/category, sort by date, group, recent
Build Pipeline
- Full build orchestration (
Sayfa.Builder) - Three-layer template composition (content body -> layout -> base)
- EEx template rendering with
@blockhelper injection - Configuration system with defaults, app env, and runtime overrides
- Static asset copying
- Draft filtering
Content Types
- 5 built-in content types: Post, Note, Project, Talk, Page
- Content type behaviour for custom types (
Sayfa.Behaviours.ContentType) - Layout selection: front matter -> content type default -> fallback
- Category and tag archive page generation
- Pagination with configurable posts per page
Feeds & SEO
- Atom feed generation
- Sitemap XML generation
- SEO meta tags (Open Graph, description)
- Reading time calculation
- Table of contents extraction from headings
Blocks
- Block behaviour and registry system (
Sayfa.Behaviours.Block) @block.(:name, opts)helper available in all templates- 9 built-in blocks: hero, header, footer, social_links, toc, recent_posts, tag_cloud, reading_time, code_copy
Extensibility
- Hook behaviour with 4 pipeline stages: before_parse, after_parse, before_render, after_render
- Theme system with inheritance (custom theme -> parent -> default)
- Multilingual support (directory-based i18n)
Developer Experience
mix sayfa.new— project generator with sample contentmix sayfa.build— build with--source,--output,--drafts,--verboseflagsmix sayfa.serve— dev server with file watching and hot reload- Build caching for incremental rebuilds
- Verbose logging with per-stage timing