Changelog
A note on Pure Blog's direction
Pure Blog does exactly what I want from a blogging platform, and I'm really happy with where it's landed. At this point, I consider it feature complete β which means I won't be accepting new feature requests.
If you've opened a feature request, thank you, but it's unlikely to be implemented.
What I will continue to accept:
- Bug reports β if something's broken, I want to know.
- Translation improvements β some non-English translations are AI-generated and could use native speaker review.
- New translations β if you want to add a new language, submit a PR using
/lang/en.phpas a reference.
Thanks for using Pure Blog. I hope it serves you as well as it serves me. π
Unreleased
Bug fixes
Added autocomplete="off" to all text inputs and textareas in the post and page editors to suppress browser input history suggestions.
v2.2.0 β 27 March 2026
Upgrading from v2.1.0? The in-app updater in v2.1.0 used an allowlist that didn't include all new files. Before running the update, manually replace admin/settings-updates.php with the v2.2.0 version β this ensures the updater can pull down everything correctly, including sitemap.php.
Translations
A large number of strings across admin were hardcoded in English and never passed through the translation system. The affected areas are: the 404 page heading and body; the Header Injects, Footer Injects, and Cache section titles in Site Settings (plus four inject field labels); all image upload and delete error messages; autosave JSON error responses; the post and page preview fallback title; all ~30 error and status messages in the updater (settings-updates.php); the admin footer credits and link labels; the language-file-missing warning in the admin header; and all 14 user-facing strings in the editor JavaScript (autosave status, restore banner, copy confirmation, upload prompts, and more). JavaScript strings are now serialised from PHP via window.PureblogEditorConfig.strings so they pass through the translation system at render time.
All eight language packs have been updated. A pre-existing key (admin.editor.error_empty_slug) was also missing from the German, Dutch, Portuguese, and Spanish packs and has been added. All new non-English translations were produced by AI β if you're a native speaker and spot anything that sounds unnatural, please open an issue or submit a PR.
Added
A sitemap.php is now included in the root of every Pure Blog install. It outputs a standard XML sitemap covering the homepage (priority 1.0), all published pages (0.8), and all published posts (0.9), each with a lastmod date. Requests to /sitemap.xml are automatically redirected to sitemap.php via .htaccess, so Google Search Console and other tools that expect a static URL work without any extra config. Thanks to @adegans for the suggestion.
OpenGraph meta tags are now more complete. Previously only og:image was output. Pages and posts now also emit og:type (article for posts, website for everything else), og:url, og:site_name, og:title, og:description, and og:locale (derived from the configured language). This improves link previews when sharing on Mastodon and other platforms. Thanks to @reederda for the suggestion.
The RSS feed now combines two layers of caching. Server-side: the generated XML is cached and reused across requests for the duration of the RSS TTL (Settings β Site), avoiding redundant Markdown rendering. HTTP: Cache-Control, Last-Modified, Expires, and ETag headers are sent so RSS readers that respect them won't re-fetch the feed until it changes, saving bandwidth entirely. Clients that do re-request get a 304 Not Modified response if the feed hasn't changed. Thanks to @adegans for the suggestion.
Fixed
The admin nav menu was constrained to 60rem by a shared .mid rule, making the max-width on .admin-nav ineffective. The nav list now has its own max-width: 70rem so the menu can use more available width.
The updater could silently delete the root .htaccess file after an update. If reading the existing .htaccess failed quietly during the pre-update snapshot, it would be absent from the preserved-files list and then removed by the post-update cleanup pass. The cleanup now also skips any .htaccess inside the backup/ directory, which previously caused backup copies to be deleted and left rollbacks unable to restore the file.
The file picker button in the post and page editors now correctly filters for AVIF files in browsers that don't map image/avif to the image/* wildcard. Drag-and-drop was already working. Thanks to @msone for the report.
v2.1.0 β 26 March 2026
Added
The search page is now a manageable page in the dashboard. A default content/pages/search.md page ships with new installs and is added automatically on update. The search form and results render below any page content you add. The active search page can be changed (or disabled) from Settings β Site, alongside the homepage and blog page selectors. The old search.php and search/ files are removed automatically on update.
Autosave no longer overwrites the live post. Changes are now written to a temporary file in content/autosaves/ and never touch the published content until you manually save. When you return to edit a post or page with pending autosaved changes, a banner appears offering to Restore or Discard them, with a View toggle to inspect the autosaved content before deciding. Thanks to @BumbleSusan for the report.
AVIF image uploads are now supported alongside JPG, PNG, GIF, and WebP. Thanks to @msone for the request.
Fixed
Post and page status labels ("Draft" / "Published") in the admin dashboard and pages list are now translated. Thanks to @justdaj for the report.
The Theme and CSS settings pages were almost entirely hardcoded in English. All labels, section headings, colour field names, reset buttons, and layout options are now fully translated across all eight language packs.
The German translation has been revised based on community feedback: "Website" is replaced with "Blog" throughout settings, the nav link is now "Blog ansehen", the last-published stat reads "JΓΌngster Beitrag", and font/colour/layout labels use more natural German terminology. Thanks to Michael for the feedback on both German translations, and broader gaps.
Changed
Admin notices now use a 2px coloured border with normal text and a light tinted background, rather than coloured text. Success notices are green-tinted, error notices are red-tinted, with appropriate dark mode variants.
v2.0.0 β 24 March 2026
Added
apply_filter() helper function and an on_filter_content hook. Defining on_filter_content(string $markdown): string in hooks.php or content/functions.php lets you transform post/page content after built-in shortcodes are processed but before Markdown conversion β enabling custom shortcodes, embeds, and other content transforms without touching core.
Search excerpt length is now configurable in site settings. Defaults to 2500 characters per post (up from 500), improving search accuracy without significantly increasing memory usage. Set to 0 to index full post content. Thanks to @werschreibt for the report.
The post and page editor now autosaves 10 seconds after the last change, but only once a post has been manually saved (i.e. a slug exists). A subtle "Autosaved HH:MM" indicator appears in the editor toolbar.
Internationalisation (i18n) support. UI strings are now loaded from per-language PHP array files in lang/ (e.g. lang/en.php, lang/de.php). The existing language config key selects the active language file. A t() helper function handles dot-notation key lookup and {placeholder} substitution throughout templates. Falls back gracefully to English if no matching lang file exists.
- Eight language packs included: English (
en), French (fr), German (de), Italian (it), Spanish (es), Portuguese (pt), Dutch (nl), and Romanian (ro).- Note: The Portuguese and Italian langage packs are still being reviewed, so may contain errors. Please submit a PR if you find any.
- Date localisation β month and day names in formatted dates are translated automatically via the lang file's
date.months,date.months_short,date.days, anddate.days_shortarrays. No new dependencies; works with the existingdate_formatconfig setting. - Setup wizard now includes a language select dropdown built from all available
lang/*.phpfiles. Changing the language reloads the setup page in the chosen language immediately, before any config file exists. Language names are shown in their native language.
The tag field in the post editor now suggests existing tags as you type. Suggestions are sourced from content/tag-index.json and are filtered token-by-token after each comma, so multi-tag lists work without losing previous entries. Keyboard navigation (arrow keys, Enter, Tab, Escape) is supported.
Fixed
save_page()now busts the internal pages cache after writing, so subsequent calls toget_page_by_slug()within the same request reflect the updated content.save_post()already did this implicitly viabuild_search_index(); pages were inconsistent.- Post and page content is now saved with Unix line endings (LF). Previously, browsers submitted textarea content with Windows-style CRLF line endings, which were written as-is to
.mdfiles, causing^Mcharacters to appear when editing files in Vim and other Unix tools. - Raw
.mdsource files incontent/are no longer publicly accessible. Requests are routed throughindex.phpand return a 404. A newcontent/.htaccesshandles the routing so the fix propagates through updates without touching the root.htaccess. - Post excerpts no longer strip hyphens from mid-word compounds (e.g. German words like
Datenstrom-Yellow-Instanz). The excerpt sanitiser now targets Markdown syntax precisely β list markers, blockquotes, ATX headings, setext headers, and inline emphasis β rather than stripping-globally. Thanks to @werschreibt for the report. - Saving a post or page whose title contains only special characters (e.g.
!!!) now shows a validation error instead of creating an uneditable file with an empty slug. Thanks to @werschreibt for the report. <time>elements now include a properdatetimeattribute with a full ISO 8601 timestamp and timezone offset (e.g.2026-03-23T14:30:00+01:00), fixing an HTML validation error. Thanks to @werschreibt for the PR.- Fixed several broken paths when Pure Blog is installed in a subfolder. Page preview, image upload, image delete, and the image URLs generated by the editor all hardcoded root-relative paths (e.g.
/admin/edit-post.php) instead of usingbase_path(), causing 404 errors for anyone not running at the domain root. Thanks to the reporter on issue #32.
Contributors
- My sincere thanks go to the following people who helped to create the language translations:
- Jan van den Berg for sparking some ideas that made their way in as new features.
1.9.7 β 21 March 2026
Fixed
- Image uploads now work for posts and pages whose titles contain umlauts or other diacritics (e.g. "Γber").
slugify()now transliterates common diacritics to ASCII equivalents (ΓΌβue, ΓΆβoe, Γ€βae, Γβss, etc.), andis_safe_image_slug()now accepts Unicode letters so existing pages with umlaut slugs are not blocked.
1.9.6 β 19 March 2026
Fixed
- Custom routes now accept
/as a valid path, allowing acontent/includesfile to be used as the homepage by mapping/ | /content/includes/filename.phpin the Custom Routes setting.
1.9.5 β 18 March 2026
Improved
- Search now splits multi-word queries and matches each term independently (AND logic), so searching for "wordpress jekyll" returns posts that contain both words anywhere across the title, description, excerpt, or tags β rather than requiring the exact phrase. Emoji and other non-text characters are also stripped from the search haystack before matching, so posts with emoji in their titles (e.g. "π A Book I Read") are found correctly.
1.9.4 β 17 March 2026
Added
load_yaml_list()now supports YAML block scalars (|) in string fields, allowing multi-line text in data files such as book summaries.
Fixed
- RSS feed now includes
xmlns:atomnamespace andatom:link rel="self"for broader feed reader compatibility. Relative fragment URLs (e.g. footnote links) in feed content are now made absolute.
1.9.3 β 16 March 2026
Added
- Configurable HTML language setting. A
languagefield (BCP 47 tag, e.g.en,fr,pt-BR) is now available in site settings and the setup wizard. Previously thelangattribute in the HTML header, admin panel, and RSS feed was hardcoded toen(#20).
Removed
hide_homepage_titleandhide_blog_page_titlesettings. The underlying title rendering was never implemented, making these settings non-functional. Page titles are managed within page content directly (#21).
Fixed
- Numeric tags (e.g.
2026) causing a 500 error on the admin dashboard. PHP coerces numeric string array keys to integers, which then failed a strict type check when passed toe()(#23). - Guard
require_once ParsedownPureblog.phpwithis_file()so installs upgrading from a version that predates that file don't fatal-crash on any markdown render.
Thanks to @werschreibt for the issue submissions.
1.9.2 β 13 March 2026
Fixed
- Added PHP 7.4 polyfills for
str_starts_with()andstr_contains(). These functions were introduced in PHP 8.0; installs on PHP 7.4 would fatal-crash on any page load after upgrading to 1.9.0 or 1.9.1.
1.9.1 β 13 March 2026
Added
ParsedownPureblogβ a subclass of ParsedownExtra that adds paragraph-level CSS class attribute support ({.class}). Useful for notice boxes and other styled blocks. Inline attributes on links and images were already supported via ParsedownExtra.
1.9.0 β 13 March 2026
Added
- Subfolder hosting support. Pure Blog can now be installed in a subdirectory (e.g.
example.com/blog) without manual path configuration. A newbase_path()function auto-detects the install prefix by comparing the app root toDOCUMENT_ROOT. Ifbase_urlis set in config it must include the full path (e.g.https://example.com/blog).
Changed
- All internal links, redirects, asset URLs, admin navigation, and SVG sprite references are now subfolder-aware.
1.8.1 β 12 March 2026
Fixed
- Path traversal vulnerability in image upload and delete operations (#16).
- Code blocks inside post headers rendering incorrectly.
1.8.0 β 10 March 2026
Added
- Custom post layouts β define per-post layout templates from the editor.
- Custom functions support β drop a
functions.phpinto/contentto extend Pure Blog without modifying core files.
1.7.1 β 6 March 2026
Fixed
- Improved HTML markup syntax highlighting in dark mode admin editor.
- Added theme hints to the settings UI to help orient new users.
1.7.0 β 2 March 2026
Added
- Page-level output caching, including correct cache-keying for paginated views.
Fixed
- Square OG image logic corrected; duplicate OG field removed.
1.6.5 β 28 February 2026
Fixed
- Square OG image selection logic.
1.6.4 β 26 February 2026
Added
- Locale support for date formatting.
1.6.3 β 25 February 2026
Fixed
- Tags not working correctly for posts written in non-Latin languages.
1.6.2 β 16 February 2026
Added
- Option to hide the blog feed page entirely.
1.6.1 β 16 February 2026
Fixed
- Hard-coded YAML key lookups left over from test code.
1.6.0 β 14 February 2026
Added
- Custom routes β map arbitrary URL paths to content templates via config.
1.5.8 β 14 February 2026
Fixed
- Pagination broken on search results pages.
1.5.7 β 13 February 2026
Fixed
- ParsedownExtra failing to render emoji correctly.
1.5.6 β 13 February 2026
Fixed
- Auto-updater incorrectly reporting "unknown" as the current version.
- Auto-updater VERSION file not written correctly after update.
1.5.5 β 13 February 2026
Fixed
- Critical bug causing admin hooks to not fire correctly.
1.5.4 β 13 February 2026
Added
- Site title in the admin header is now a link to the live site.
Fixed
- Improved version detection reliability in the auto-updater.
1.5.3 β 12 February 2026
Fixed
- Minor internal functions.php patch.
1.5.2 β 11 February 2026
Fixed
.htaccessis now never overwritten during an auto-update.- Excerpt regex updated to prevent link text being stripped from post excerpts (PR #13, thanks @LukeKeller).
1.5.1 β 11 February 2026
Fixed
- Minor patches following the 1.5.0 release.
1.5.0 β 11 February 2026
Added
- In-app auto-updater. Check for and apply new Pure Blog releases directly from the admin settings panel, with automatic backup and rollback.
1.4.0 β 10 February 2026
Added
- ParsedownExtra library bundled β enables extended Markdown syntax (tables, footnotes, attribute syntax, etc.).
- Canonical
<link>tag in HTML<head>. - CSS classes on tag list elements for theme styling.
Changed
- Masthead layout refactored into a dedicated include.
1.3.1 β 9 February 2026
Fixed
- Post navigation (previous/next) link tweaks.
1.3.0 β 8 February 2026
Added
- Shortcodes, partials, and content injects β embed reusable content snippets inside posts and pages.
- Footer embed support.
Fixed
- Issue #5.
1.2.0 β 8 February 2026
Added
- Hooks system β register PHP callbacks to extend core behaviour without editing core files.
site_emailglobal config option.- Data files β load structured YAML/JSON data from
/content/datainto templates. - Improved URL handling for RSS feed and search.
Fixed
- Liquid/code block rendering in sidebar code blocks.
- Various admin UI fixes.
- Background flash (FOUC) during CSS processing eliminated by inlining custom styles.
1.1.x and earlier β 6 February 2026
Initial development releases. Core flat-file blogging engine with Markdown posts and pages, admin panel, tag support, RSS feed, and search.