Changelog
Release Notes
Every feature, every improvement, every fix since v1.0.0.
Page 13 of 20 — 576 releases, newest first.
Cloudflare Exception Rules Now Actually Apply: Right Permission, Modern API, Your Own Rules Preserved
Improved
- Removed the colored left-rail line from the sidebar warning cards (a design-system rule) and reworked them into clean, softly tinted alert cards -- amber for attention, blue for info -- that fit the rest of the admin.
Fixed
- Fixed "Apply exception rules" failing with an Authentication error even when the token had "Firewall Services -> Edit". Diagnosed against the live Cloudflare API: the legacy Firewall Rules API is now frozen (maintenance mode, no new rules), and modern WAF custom rules (Rulesets API) require the separate "Zone WAF" permission -- which "Firewall Services" does not grant. The setup wizard now asks for "Zone -> Zone WAF -> Edit" (with a note explaining why), and every permission error message names the exact permission needed.
- The jekcms exception rules now use a proper skip action that bypasses the relevant Cloudflare security products (WAF managed, browser integrity check, security level, rate limiting, UA/zone lockdown) for the automation and crawler paths, instead of an ineffective placeholder.
- Applying the exceptions no longer wipes your own custom WAF rules. The plugin now reads the existing rules first, refreshes only the jekcms ones, and preserves everything else -- so re-applying is safe and idempotent.
Cloudflare Wizard: "Connect" Now Really Connects, Clearer Token Steps, Calmer Sidebar
Improved
- The token step now walks through Cloudflare's real screens in order: My Profile -> API Tokens -> Create Token, then explicitly "under Custom token click Get started" (so users do not pick a template that grants the wrong permissions), then naming the token (Token name, e.g. jekcms) before the permission table. This closes the most common wrong-permission trap.
- Reworked the setup wizard into the same calm two-column layout as the connected panel: the step-by-step guide on the left, the critical warnings in a refined right-hand sidebar. Removed the remaining red boxes in the wizard (red read as an error); warnings are now amber "attention" / blue "info" with a clean left-rail accent instead of the previous generic colored icon tiles.
Fixed
- Fixed a bug where the setup wizard's "Connect" button never actually connected. The test-mode toggle was accidentally nested as a <form> inside the connect <form>; browsers flatten nested forms, so pressing Connect submitted the toggle action instead -- the token was never saved or verified and the panel stayed stuck in test (mock) mode no matter what. The two forms are now separate, and connecting with a real token always runs a real verification (and clears any leftover test mode).
Cloudflare Panel: Real Action Feedback, Permission Diagnostics and a Calmer Layout
Improved
- Reworked the connected Cloudflare panel into a two-column layout: the actionable cards (status, recommended settings, automation exceptions, your own rules) sit in the main column, and the "Critical warnings" moved into a calm right-hand sidebar. The warnings are no longer shown as loud red error boxes -- red read like something was broken; they are now amber "attention" and blue "info" notes.
- Unified the panel header (title + description on one clean band with a direct "Open Cloudflare dashboard" button once connected), and the marketing value strip now only shows before you connect, so the connected panel leads with live status instead of a sales pitch.
Fixed
- Fixed missing feedback on the Cloudflare panel: Purge cache, I'm Under Attack, Apply recommended and Apply exceptions all reloaded the page silently with no confirmation. The panel was writing its flash message under one key while the admin renderer read another, so nothing ever showed. Every action now shows a clear success / warning / error banner.
- Fixed the SSL and Security tiles showing a bare "?" with no explanation when the connected API token lacked the Zone Settings permission. The panel now detects the read failure, shows a plain-language notice telling you to recreate the token with "Zone Settings -> Edit" (and surfaces Cloudflare's own error), instead of a silent question mark.
Cloudflare Setup Wizard: Cleaner Layout and a Token Table That Mirrors Cloudflare
Improved
- The token step now shows the required permissions as a table that matches Cloudflare's real "Create Token" screen one-to-one (Group / Item / Access), plus a matching Zone Resources row (Include / Specific zone / your domain). You can copy each dropdown value straight across instead of decoding a run-on sentence.
Fixed
- Fixed a layout bug in the Cloudflare setup wizard where the click-path chips (Domains, Add domain, Overview, etc.) were placed inline inside wrapping paragraph text; their padding was taller than the line, so wrapped lines overlapped and the guide looked jumbled. Each navigation path now sits on its own dedicated breadcrumb row with chevrons, so the text stays clean at every width.
Cloudflare Wizard Matched to the Real Onboarding Flow: DNSSEC, AI Policies, and the MX/TXT Nuance
Improved
- The Cloudflare setup wizard now mirrors Cloudflare's current add-site flow step by step: Domains → Add domain → "Connect a domain", the new "AI training & search policies" screen (with a jekcms recommendation — Search: Allow and Agent: Allow so you stay visible to search and AI answer engines, matching your llms.txt), picking the Free plan, and reviewing the auto-scanned DNS records before activation.
- Two easy-to-miss but breaking details are now called out explicitly. Turn DNSSEC OFF at your registrar before switching nameservers — leaving it on while you move NS to Cloudflare makes the site completely unreachable. And keep email records (MX, SPF/DKIM TXT) grey "DNS only" while web records (A/AAAA/CNAME) go orange (proxied) — proxying mail records breaks delivery.
- The token step now points at the shorter path too (Overview → API → "Get your API token", or My Profile → API Tokens), and the step indicator reflects the real four phases: Connect, Plan + DNS, NS, Token.
Cloudflare Wizard Leveled Up: Polished Steps, Current Dashboard Paths, and a Bot Fight Mode Warning
Improved
- The Cloudflare setup wizard was rebuilt to feel like a real onboarding flow: a visual step indicator, a value strip (protection / speed / jekcms-aware), and richer step content with breadcrumb-style dashboard paths that match Cloudflare's current interface — creating a custom token now lists the exact permissions to grant (Zone Read, Zone Settings Edit, Cache Purge, Firewall Services Edit) scoped to the one site, and each step points at the right menu (Overview, DNS, My Profile → API Tokens).
- A critical-warnings block now surfaces two things the API can't safely automate: keep Free-plan Bot Fight Mode OFF — it is aggressive and does NOT honor the jekcms skip rules, so turning it on breaks scheduled publishing, n8n and search/AdSense crawling — and make sure your DNS records are proxied (orange cloud) or the whole CDN/WAF layer is bypassed. The advanced panel also links straight to Cloudflare's Bot settings and WAF custom-rules pages.
New Plugin: Cloudflare — a CDN + WAF Edge Layer With a jekcms-Aware Setup Wizard
Added
- A Cloudflare plugin puts an optional CDN + WAF layer in front of your site — extra protection and speed on top of jekcms's built-in security (2FA, encrypted keys, signed updates), not instead of it. A four-step wizard walks you through it: create a free Cloudflare account and add your domain, change your nameservers (with the exact NS to set at your registrar), create a scoped API token (the wizard lists the precise permissions — Zone Settings, Cache Purge, Firewall — limited to this one site), then paste the token to connect. The token is stored encrypted with the same AES-256-GCM vault used for AI keys, and is never shown again.
- One click applies the settings that actually fit jekcms — and each one explains why: SSL Full (Strict) because "Flexible" would loop against the server's own http→https redirect; Always Use HTTPS; a TLS 1.2 floor; HTTP/3 and Brotli for speed; a sensible security level and browser integrity check.
- A second one-click step writes the exception rules that keep jekcms working behind Cloudflare — the part a generic plugin gets wrong. Cloudflare's bot/challenge layer is told to skip /api/v1 (n8n and integrations), the scheduled-publishing loopback and the analytics beacon, and robots/sitemap/ads.txt — without these, scheduled posts, automation and search/AdSense crawling silently break. The real visitor IP is already restored safely from CF-Connecting-IP for rate limiting and logs.
- The status panel shows zone/SSL/security state live, offers one-click cache purge and an "I'm Under Attack" switch, and deep-links to Cloudflare's own WAF editor for your custom rules — deliberately kept there, since a mis-written rule can lock you out. Publishing, updating or deleting a post now purges the affected URLs from the edge automatically. A test (mock) mode lets you preview the whole flow before connecting a real token.
Dark Theme Pass: the Root Cause of White Boxes Fixed, With a Permanent Guard
Improved
- The SERP Identity report's code window now uses a fixed GitHub-dark palette — identical and fully readable in both the light and the dark admin theme, instead of inheriting ambient colors that could lose contrast.
Fixed
- Several admin screens kept glaring white patches in dark mode — the contact messages card, the sticky "Save settings" bar, the social-profiles box on the user form, the backup info strip. The root cause was one pattern, not many bugs: pages referenced CSS variables under local names (--card-bg, --admin-surface, --bg-subtle…) that the admin stylesheet never defines, so their light fallback color won in every theme. Those names are now bridged to the real theme tokens in one place, the remaining hardcoded light strips were converted to tokens, and a static guard runs with the release gate: any future undefined variable with a light fallback fails the build before it can ship a white box.
- Browser autofill was punching light-lavender fields into dark forms (social connections, backup inputs). Autofilled inputs now keep the admin theme's own background and text color.
SEO Tools Accuracy Pass: ads.txt False Negative, Honest Heading Warnings, Stale-Year Scanner, and a Code-Style SERP Report
Improved
- The SERP Identity Check turned from a raw text dump — unreadable on the dark admin theme — into a GitHub-style code window: line numbers, syntax coloring on the admin's own theme tokens (correct in light and dark), a clean/review status chip, one-click copy, and the old plain-text output still available for support scripts.
Fixed
- SEO Health Check could report ads.txt (and favicon) as missing while the file was live: the checker requests a byte range, and web servers answer static files with HTTP 206 Partial Content — which the check treated as failure. 206 is now recognized as success and redirects are followed, so sites with a physical ads.txt are reported truthfully.
- The Heading Fixer's "starts lowercase" warning looked wrong because it never said WHICH heading it meant — it checks subheadings inside the article body, not the post title, so a flag on "Linux RAID Setup: mdadm…" read like a false alarm. The warning is now honest twice over: the label says "a content subheading", the message quotes the actual heading text, and the technical-term whitelist grew by ~40 commands (mdadm, vmstat, iostat, netsh, adb and friends) so command-titled sections are no longer flagged at all.
- The Year Updater only suggested last year by default, quietly missing older leftovers. It now scans every title and slug for any past year and shows them as clickable chips — "2021: 4 posts, 2019: 2 posts" — one click selects that year for the bulk update.
Advanced SEO Ships Active by Default — the Single SEO Panel Works Out of the Box
Improved
- The Advanced SEO hub — the single panel that 2.46.2 made the one way into every SEO tool — used to require manual activation on a fresh install, which would have left new sites with the old scattered entry points until someone flipped the switch. The plugin now activates itself on first install, so the sidebar entry, the module menu and the single-navigation routing are all there from minute one. Existing installs are untouched: whatever activation state you chose stays exactly as it is.
One SEO Panel: Duplicate Entry Points Now Route to the Advanced SEO Hub, Legacy Duplicate Screens Retired
Fixed
- The standalone SEO Optimizer page and the Advanced SEO hub were the same tool with two front doors: the dashboard's "SEO score" tiles opened /seo-optimizer.php directly, where the sidebar showed no active section and the hub's module menu was missing. Every tool embedded in the Advanced SEO hub (optimizer tabs, health check, heading fixer, content optimizer, auto-linker, redirects and friends) now routes its direct URL into the hub with the right module selected — old links and bookmarks keep working, the sidebar highlights correctly, and there is exactly one way in. The routing is careful: POST requests, embedded (iframe) loads and unknown internal tabs are never redirected, and if the Advanced SEO plugin is deactivated the standalone pages behave exactly as before.
- Two hidden screens left over from old versions were retired into safe redirects, found by a full inbound-link scan of the admin: "Advanced Ad Manager" duplicated banners.php on the same database table, and "Content Scheduler" duplicated the Content Queue — worse, it carried its own outdated CREATE TABLE that could seed a fresh install with the wrong schema. Both now 301 to their successors; nothing was deleted, old bookmarks land in the right place.
- The WordPress REST API migration tool existed but was linked from nowhere — you could only reach it by typing the URL. It now has a visible entry on the Import screen, next to the SQL/CSV path it complements.
Customizer Polish: Light/Dark Color Rows Are Now One Aligned Component
Fixed
- The light/dark color pair introduced in 2.46.0 looked cluttered: the disabled dark swatch was squeezed into a thin gray sliver by the flex layout, the two rows didn't line up, and the override checkbox floated awkwardly at the end. Each color is now a single aligned component — a fixed four-column grid (sun/moon tag, swatch, hex, control) shared by both rows, so swatches and hex fields sit exactly under each other; the checkbox became a proper toggle switch; and a disabled dark row dims cleanly with a "theme default" placeholder instead of collapsing.
Theme Customizer, Reworked: Separate Light & Dark Palettes, New Theme-Specific Sections
Added
- Every color in the theme customizer can now be set separately for light and dark mode. Each color shows a Light and a Dark picker; the dark value is written under the theme's real dark mechanism — the data-theme attribute on ten themes, the .dark-mode class on Finance, and the system preference (prefers-color-scheme) on Lifestyle. An "override" switch per color keeps the theme's own dark tone until you opt in, and themes without a dark mode (Crypto is light-only, Tech is dark-native) simply don't show dark pickers — no fake settings. All twelve theme-specific schemas gained the pairing automatically, without a single line changed in their definitions.
- Minimalist and Lifestyle — the two themes that had been falling back to a thin generic panel — got full, hand-written customizer schemas wired to their actual stylesheets: every color maps to the variable the theme really uses (defaults read from the CSS itself, including Minimalist's dark block), font pickers, layout controls (content width; on Lifestyle also section spacing and grid gap), and real section toggles that were wired into the templates — hero, categories bar and newsletter on the homepage; breadcrumbs, share buttons, author card and related posts on articles (Lifestyle additionally: table of contents and the popular-posts widget). Toggles physically remove the markup, they don't just hide it.
- The default schema for future themes also grew: heading, border and surface colors, body line-height, and font pickers that emit their CSS variables directly.
Improved
- jekcms.com now tells both stories on the features page: the reworked Theme Customizer (with its light/dark palettes) and the AdSense Readiness plugin shipped in 2.45 — described honestly, including that approval is always Google's call.
Fixed
- The Lifestyle theme's customizer had never actually worked: the theme's header never printed the customization stylesheet, so every saved setting was silently ignored. The calls are now in place — and covered by a behavior test that catches any theme dropping them again.
- The customizer spoke Turkish to English admins in two themes: Personal and Trends had their panel labels written in Turkish inside the theme definition, and the translation dictionary only worked in one direction. All their labels are now bilingual at the source, help texts pass through localization too, a reverse mapping catches any legacy Turkish label, and a new two-language scan across all fourteen themes runs with the test suite — zero leakage, permanently guarded.
AdSense Readiness: Stored Scans Auto-Refresh After a Plugin Update
Fixed
- After updating the plugin, the dashboard could keep showing the previous version's stored scan — old wording, and no "Show posts" modal button, because that list simply doesn't exist in the old result. The panel now compares the stored scan's plugin version on load and silently re-runs the audit when it's stale, so a new feature never appears to be "missing" just because the visible result predates it. The scan is measurement-only and changes nothing on the site.
AdSense Readiness: Sticky Insight Panel, Full-Width Header, and a Post-List Modal
Added
- Checks that carry a post list — thin content first — now open a modal: every affected post is listed by title with its word count, and clicking a row opens that post's edit screen in a new tab. No more hunting post IDs from a summary sentence; the list is capped at 200 rows with an honest "first N of M shown" note beyond that.
Improved
- The empty right side of the AdSense Readiness dashboard is now a sticky insight panel that follows you as you scroll. It carries the full "maturity — honest note" (why green checks alone don't guarantee approval, with your site's first-publish date and last-30-days output), an application-process card with the key numbers (2–14 day review, ~1 week wait after a rejection), and an application-day checklist: single-source AdSense snippet, automatic ads.txt verification, Search Console, and keep-publishing-during-review.
- The header now spans the full layout: the intro paragraph is no longer truncated into a narrow column, and the Re-scan button sits at the far right of the title row.
AdSense Readiness: 5 New Checks, a Legal-Page False Negative Fixed, and a Polished Dashboard
Added
- Five new checks in the AdSense Readiness audit. SSL certificate: a real TLS handshake verifies the chain and reports the issuer and days until expiry (expiring within 14 days warns, expired fails). Domain: the site must live on a real domain — an IP address or a bare host fails, and IDN (unicode) domains get a punycode heads-up. Google bot access: the homepage is actually requested with Googlebot and Mediapartners-Google user agents to prove the server doesn't block the crawlers AdSense review depends on (honestly labeled as an in-server test — a CDN/WAF in front should also be verified externally). noindex is now its own heavyweight check covering both the homepage meta tag and the SEO setting. Meta description: presence and length of the homepage description (target 120–160 characters).
Improved
- The dashboard got a design pass: the five category cards now sit in a single equal-width row with ellipsized titles (no more ragged two-line wrapping), and the previously empty right side of the score hero hosts a compact "maturity — honest note" summary with a link to the full text. Status filters became a proper segmented control, fix buttons are now solid primary actions, cards gained consistent depth and hover states, and the score ring color follows the overall verdict instead of the raw number — no more green ring next to "fix the gaps".
Fixed
- Legal pages were reported missing on sites that serve them through the built-in route templates instead of database pages. jekcms renders complete, AdSense-compliant legal texts at /privacy-policy, /cookie-policy and friends even when no page row exists — the audit now recognizes both paths (plus every slug alias, Turkish and English), and the About/Contact checks follow the same logic: a database page, a theme template or the contact-form plugin all count; only sites left with the bare built-in fallback get a warning.
- Clicking a category card scrolled the section heading under the fixed admin header, landing mid-section. Anchor targets now reserve headroom, so every jump lands with the section title fully visible.
New Plugin: AdSense Readiness — a Full Site Audit Through a Reviewer's Eyes
Added
- AdSense Readiness plugin: one click scans your site the way an AdSense reviewer would — about 30 real measurements across five areas. Content: published post count against the 25+ target, average post length, thin posts under 300 words listed one by one, category structure (no empty or 3-post-starved categories), duplicate titles, publishing freshness, leftover "lorem ipsum" and still-installed sample content. Legal & trust: all four legal pages (privacy, cookie, terms, disclaimer — the built-in generator creates them in one click if missing), a real About page, a reachable contact channel and the cookie-consent banner. Authors: every active author checked for a real bio in the 3–5 sentence sweet spot (overlong "epic" bios are flagged too), job title, photo, and posts piled onto a single admin account. Technical: HTTPS, site name/tagline/logo, live homepage fetch (indexability, schema, og:site_name, single H1), sitemap.xml, robots.txt access for Googlebot and Mediapartners-Google, 404 behavior and Search Console verification. AdSense: snippet detection with an explicit double-loader warning, and ads.txt validation against your pub-id.
- Every finding shows the measured value — "18 posts (target: at least 25)", not a vague tip — and ships with a direct fix link into the right admin screen: legal page generator, user profiles, category manager, settings. A weighted 0–100 readiness score with an animated gauge, per-category progress bars and status filters (missing / warnings / passed) make the gap list actionable at a glance.
- The report is honest by design: an unscored "maturity" panel states clearly that technical hygiene is necessary but not sufficient — real traffic, site age and perceived content value drive the final decision — and documents the typical 2–14 day review window and the wait-before-reapplying rule. The plugin never promises approval; it removes every reason to be rejected on the measurable side.
Person Publisher Support, an SEO Signal Test Matrix for All Themes, and Single-H1 / Language Fixes
Added
- Publisher type setting: a personal site can now publish its structured-data publisher as a Person instead of an Organization. Pick "Person" under Settings → SEO and the WebSite node, article publisher references and the about-page reference all switch to a single Person identity — with the contact e-mail expressed the way a Person node expects it. Business sites are untouched: the default remains Organization, and nothing changes unless you opt in.
- An SEO signal regression matrix now guards every release. It activates all fourteen themes in sequence on a live test install and asserts, for each one: exactly one WebSite JSON-LD node; the site name — Turkish characters included — reproduced identically in WebSite.name, og:site_name and the page title; no auto-generated alternateName; the correct publisher type (both Organization and Person modes are exercised); exactly one visible H1; the right html lang; canonical equal to og:url; valid JSON-LD; and no character corruption. The harness ships in the repository and runs as part of the release gate.
Improved
- One positioning sentence, everywhere: jekcms is a self-hosted blog CMS with built-in SEO and image optimization, running on standard PHP + MySQL hosting. The vague "Next-Gen Smart CMS" phrasing is gone from the homepage, metadata, structured data and the admin login — and so are claims we can't prove: "24/7 support" now reads as support actually works (e-mail, response within 24–48 business hours), "Enterprise Security" now names the real controls (2FA, CSRF protection, rate limiting), and the theme count says exactly 14. The n8n integration is described in one place, as what it is: content arrives as drafts and publishes only after your editorial approval. A security.txt contact file is now published as well.
Fixed
- The minimalist theme's homepage rendered two H1 headings — the brand in the header and the featured post title. The featured post title is now an H2, so every page has exactly one visible H1 and the brand heading keeps carrying the site-name signal to Google.
- Seven themes read the site language through a helper that falls back to Turkish, while the other themes fell back to English — on a fresh install where no language row existed yet, the same site could declare html lang="tr" on one theme and lang="en" on another. All fourteen themes now read the same source, which follows the language chosen during installation.
- The crypto theme's error and maintenance pages hardcoded lang="tr" regardless of the site's language; they now follow the site language setting.
- The "Powered by jekcms" footer credit across all themes now carries rel="nofollow". It is a technology credit for readers, not an SEO signal — sitewide template links from one network shouldn't pass link authority, and search engines discount them anyway.
Theme Switching Verified End-to-End — About and Contact Now Work on Every Theme
Improved
- Theme switching itself was exercised the way a real user would do it: all fourteen themes were activated in sequence on a live test install — each activation running the theme's own migration hook — and after every switch, eight real pages (home, a post, a category, search, about, contact, a static page, and the 404 page) were fetched over HTTP and checked for errors. 112 page loads, zero failures. Per-theme customizations were also verified to survive a switch away and back, without leaking into the other theme's settings. The test harness ships in the repository so this can be re-run before any release.
Fixed
- Switching themes no longer breaks the About and Contact pages. Eleven themes ship without their own about template (and two without a contact template); on a site that hadn't created those pages yet, switching from a theme that had the template to one that didn't turned working footer links into 404s. The router now falls back to an honest built-in default rendered through the theme's page template — with the contact form auto-injected — and the moment you create a real "about" or "contact" page in the admin, your content takes over.
- Three themes (crypto, minimalist, health) ignored page content handed to them by the router and re-queried the database by slug, which broke the new built-in defaults and any router-provided page. They now use the provided content first, exactly like the other eleven themes.
AI Keys Encrypted at Rest Everywhere, and the Main CI Pipeline Now Runs Every Quality Gate
Security
- AI provider API keys are now stored encrypted everywhere. The multi-key Gemini list and the flat provider key fields (OpenAI, Groq, Cohere, Claude) are encrypted with authenticated AES-256-GCM before they touch the database, the settings form shows only a masked hint and never echoes a stored key, and every consumer — content tools, cron, connection tests — reads through the same decryption gate. A one-shot migration converts existing records automatically on the next cron pass, verified end-to-end on a real database.
- Signing out is a pure POST form now. The interim design carried the CSRF token in a GET link, which could land in access logs, browser history and prefetchers; the admin logout links are now styled POST forms, so the token never appears in a URL.
- A short mixed-version window could crash AI key reads: the migration check called a brand-new method without guarding against the older class still being loaded mid-deploy. All migration detection now runs behind a guarded helper and inside its own try block, with failures logged instead of swallowed.
Improved
- The main GitHub deployment pipeline now runs the same quality gates as a local release: the fresh-install acceptance test, the hardening regression suite, the schema linter and the i18n linter all execute on every push to main — a regression in any of them stops the deployment before it reaches production. The hardening suite itself grew to 37 checks, including real cryptographic behavior tests for the new key vault (plaintext never lands in the stored JSON, legacy entries migrate, masked hints never leak the full value).
- The fresh-install schema now includes the multi-key AI columns, which previously existed only in a secondary schema file — saving multiple Gemini keys on a brand-new install could fail with a database error.
Review Follow-up: Crypto Edge Case, Transparent Secret Migration, CSRF-Protected Logout, and Permanent Hardening Tests
Security
- Stored secrets now migrate to authenticated encryption on their own. When an AI provider key or a Google OAuth token stored in the legacy format is read successfully, it is transparently re-saved in the new integrity-checked format — long-lived secrets no longer wait for the user to re-enter them.
- Signing out is now CSRF-protected. A plain GET to the logout address could previously be triggered by an external page to force-end an admin session; logout now requires a valid token (admin links carry it — still one click) and shows a small confirmation page otherwise.
- The audit fixes are locked in by a permanent hardening test suite that runs on every release: encryption round-trips including the empty-value and tampering cases, route targets that must exist, fail-closed API role checks, the cron result contract, and error-message masking. A regression in any of these now blocks the release.
Fixed
- Decrypting an encrypted empty value works again. The new authenticated-encryption format rejected the shortest valid packet (a zero-byte ciphertext), breaking the encrypt/decrypt round-trip contract for empty strings.
- The schema linter's success message now reports the number of currently open findings instead of the raw baseline line count, which had kept showing already-resolved entries.
Audit Fixes: Reliable Cron Output, Working /login Route, and Authenticated Encryption
Security
- Stored secrets are now protected with authenticated encryption. Encrypted values (AI provider keys, Google OAuth tokens) are written as versioned AES-256-GCM with integrity checking; existing records keep decrypting and migrate transparently as they are re-saved.
- The API's write authorization is now fail-closed: a user record with an empty or unknown role gets no write capabilities.
- API error responses no longer echo raw exception details. Clients receive a fixed message with a correlation ID; the full detail goes only to the server log.
Fixed
- The cron runner no longer crashes when a run is already in progress. The lock branch returned a bare error string while the CLI reporter expected structured results, producing a fatal error on every overlapping run — and the shutdown path then tried to send an HTTP status from the command line, masking the original error. The result contract is now uniform, the reporter is defensive, and CLI errors go to stderr with a proper exit code.
- The public /login and /logout routes work again. They pointed at an auth/ directory that never shipped, so every hit returned a server error; they now redirect to the admin login and logout pages.
- The optional AI bulk worker no longer logs database errors on installations without its table: the web-side tick now checks for the table first, exactly like the cron side always did.
- Two more fresh-install schema gaps closed by the new acceptance test: scheduled task results and the social queue's completion timestamp now exist in the shipped schema, and failed tasks write to the correct error column.
Offline Documentation in Every Package, and Fresh-Install Schema Repairs
Added
- The installation package now ships the full documentation offline. All 37 guides are bundled as self-contained HTML in both English and Turkish under documentation/ — no external assets, readable without an internet connection. The admin panel's "How to use this" links open the local copy first and only fall back to jekcms.com when the folder is absent, so in-product help keeps working even if the vendor site is unreachable.
- One-click sample content. On an empty site, the Posts screen now offers to load six short, well-formatted starter articles across three categories — with generated cover images — so a fresh install shows what your theme really looks like. The samples double as a formatting guide (headings, lists, quotes, images) and are removed with a single click, covers and categories included, without touching anything you created yourself.
- Fresh-install acceptance testing joined the release pipeline. Every release now installs the shipped database schema into a clean MySQL and runs the product's critical write paths against it in strict mode — the class of bug where code writes a column the packaged schema doesn't know is caught before a package ever reaches a customer. The internationalization check runs in the same pipeline, so untranslated admin text can no longer slip into a release unnoticed.
Fixed
- Creating an API key on a fresh install works again. The admin screen stores API keys as a SHA-256 hash, but the shipped schema still described the old plaintext-token layout, so the very first "Create key" click on a new install failed with a database error. The schema now matches the code, and existing installations are repaired automatically on their next cron pass.
- Automation logging and the social share queue no longer lose data on strict-mode databases. The automation log rejected entries whose source was "system" or "admin" (values the code actually writes), and the social queue had nowhere to store the published-at time and the platform's post ID after a successful share. Both tables are aligned with the code and heal themselves on existing installations.
- The pricing page FAQ no longer claims online payments are "coming soon" while the checkout buttons on the same page are live — it now explains card payment, instant delivery, and the invoice/bank-transfer option honestly, in both languages.
Auto-Activated Plugins Now Create Their Tables, a Rate-Limited License Endpoint, and Gates That Are Honestly Green
Security
- License activation is rate limited (20 attempts per IP per hour), matching the limiter the heartbeat already had.
Fixed
- Auto-activated plugins now install their database tables on a fresh install. A plugin marked AutoActivate was switched on automatically, but its activate.php — which creates the tables — only ever ran when you toggled the plugin by hand in the admin. On a brand-new install Newsletter therefore appeared active while newsletter_campaigns, email_templates, newsletter_queue, newsletter_clicks and email_logs were never created, and the Campaigns screen died with a fatal error. Activation now runs once per plugin version, is idempotent, adds no query on the hot path, and repairs installations that are already in the broken state on their next request. If one plugin fails to install its schema, the site stays up and the attempt is retried.
- Author social links, the reader-facing editorial box and the similarity gate carry the fixes shipped since 2.41.0: social profiles were invisible on author archives in seven themes, and the similarity gate now uses roughly a quarter of the memory it used to on large sites (measured: 64MB → 16MB on a 2,000-post blog).
Editorial Transparency Readers Can See, Paraphrase-Aware Similarity, and a Test That Actually Runs
Added
- "How this content was made" box: the editorial fields you fill in (AI usage disclosure, original-contribution note, sources, YMYL flag) are now shown to readers under the post — in every theme, with no template edits. Sources also continue to be emitted as schema.org citations. The box appears only when you have filled the fields in, and it can be turned off in Settings.
- Editorial fields are now part of the REST API: every post response carries an "editorial" object (ai_disclosure, original_notes, sources, ymyl), so external editors, archives and n8n flows can read and act on them.
- Editorial checklist in the post editor: missing sources, missing original-contribution note or an undisclosed AI usage are listed as informational reminders. YMYL-flagged posts without sources or without a human approval are called out. Nothing here ever blocks publishing.
Improved
- Content-similarity protection now catches rewrites, not just copies. Three measures work together: verbatim overlap (5-gram), partial copy (containment — a copied section buried inside an otherwise original post), and term overlap (TF-IDF cosine — the same article rewritten with different sentences). Each has its own threshold in Settings. The comparison window grew from the last 120 posts to a configurable 500, and each post is compared over its first 12,000 characters (chunked, so a wider scope does not raise memory use).
- Honest naming: this is lexical near-duplicate and term-overlap protection, not embedding-based semantic analysis. It catches verbatim copies, near-duplicates, reordered sentences, embedded partial copies and same-term rewrites; it does not claim to catch two posts that target the same search intent with entirely different wording. The acceptance test fails the build if the product ever over-claims this.
Fixed
- The publishing-policy acceptance test now proves behaviour instead of matching text. It builds an isolated MySQL fixture and measures the real decisions on real SQL: publish/block outcomes, gate_state persistence, the absence of fabricated approvals, approval invalidation on edit, seven content-similarity scenarios (verbatim, near-duplicate, reordered, partial, paraphrase, false-positive control, and window depth) and the editorial-field consumers. It runs on every push in CI. Previously it could report success while a fatal error had occurred; a fatal now fails the build.
Editorial Transparency, Near-Duplicate Protection, and a Tighter CSP
Added
- Editorial Details panel in the post editor: declare the sources a post is based on (one URL per line — they are emitted as schema.org citations on the published page), record an original-contribution note, disclose AI usage (none / AI-assisted / AI-generated, human-reviewed), and flag YMYL content. Everything is optional, stored per post, and requires no theme changes.
- Content-similarity protection in the quality gate: in addition to the existing title checks, the gate now measures body-level overlap between a new post and the last 120 published posts. Content that overlaps above the threshold (default 80%, configurable in Settings) is blocked before publishing; noticeably-similar content produces a cannibalization warning. This closes the near-duplicate class that title checks alone cannot see.
- The publishing-policy acceptance test now runs automatically: it is wired into both the local release gate and the CI pipeline, so no future change can silently reopen a publish path around the quality gate.
Security
- Content-Security-Policy hardened: 'unsafe-eval' removed from script-src after a full inventory (no first-party or third-party script in use requires eval). 'unsafe-inline' remains by documented decision — themes use inline scripts and the Custom Header Scripts feature outputs user-pasted snippets that cannot carry nonces.
Publishing Policy: One Gate, Your Choice, an Honest Record
Added
- A single publishing policy now governs every path that can put a post live — the AI draft screen, the content queue, scheduled publishing, the REST API and n8n webhooks. Automatic publishing remains entirely your choice: if you turn it on, posts go live without review, exactly as you asked. What changed is that no path can quietly skip the quality gate while it is switched on, and every publication is recorded honestly.
- Publication audit trail: each post now records how it reached the reader — its source (manual, AI, JSON, n8n, API, queue) and its publication mode (draft, scheduled, automatic, reviewed). When a human editor approves a post, jekcms stores who approved it, when, and a fingerprint of the exact content they approved. Automatic publishing never fabricates a human approval — it is recorded as automatic, plainly.
- Approval invalidation: if an approved post is edited afterwards, the stored fingerprint no longer matches and the old approval is treated as void.
- Risk notices in the admin: the AI Draft, JSON Import and content automation screens now carry a permanent, non-blocking note explaining that generated or imported content can be inaccurate or low-value, that publishing without review can affect search visibility, and that the choice of draft, schedule or direct publish is yours. Turning auto-publish on, or turning the quality gate off, shows a visible warning next to the setting — never a modal, never a forced checkbox.
Fixed
- The AI draft screen wrote posts straight to the database and never consulted the quality gate, even when the gate was switched on. It now goes through the same publishing policy as every other path; if the gate holds a post back, it is saved as a draft and the reasons are shown.
Honest Freshness Signals, a Content Quality Gate for Automation, and Full-Document Revision Restore
Added
- Editorial date model: posts now track "last meaningful content change" separately from internal system touches. Schema.org dateModified, article:modified_time and sitemap lastmod are generated from the new signal — so bulk SEO passes, counters and cache refreshes no longer make hundreds of posts look "updated today" to search engines. When editing a published post you can also override the automatic detection: mark a save as a content update or a technical fix.
- Content Quality Gate: every automated publish path — content queue approval and publish (single and bulk), scheduled publishing, REST API and n8n webhooks — runs the same deterministic quality checks before anything goes live: minimum content length, duplicate and near-duplicate titles, and broken local image references block publication with visible reasons; missing featured image, internal links or headings raise warnings. The gate re-runs at the moment of publishing (so post-approval edits are re-checked), and fails closed: if the check itself errors, nothing is published. Thresholds are configurable in Settings.
- Full-document revisions: each revision now stores a complete snapshot — SEO meta, categories, tags, featured image, author, status and dates — and restoring one brings back the content, SEO, taxonomy, featured image and author. Publication status and dates are deliberately not restored, so restoring never unpublishes a live post or rewrites its history. The state before a restore is saved as its own revision, and the revision limit is now configurable (default raised from 10 to 50).
- Author Person schema now includes verifiable sameAs links built from the author's social profiles and website, alongside the job title, bio and photo added in the previous release.
Improved
- The REST API now returns explicit ISO 8601 editorial dates (content_modified_at, reviewed_at) on post endpoints and accepts content_modified_at on writes, so migrations and rewrites can preserve original dates.
Fixed
- Schema dateModified and sitemap lastmod could report a date earlier than the publish date on scheduled posts; both are now clamped so a modification date never precedes publication.
- The sample admin account seeded by a manual database import now ships with an unusable password hash, and the installer sets real credentials as before.
Legal Pages Repaired and Expanded, Author Archives Fixed, Tag Indexing Made Consistent
Improved
- The default Cookie Policy was rewritten to be genuinely comprehensive in both languages: cookie categories with purposes, legal bases and durations in a table, first/third-party and session/persistent distinctions, named third parties with opt-out links, consent management and withdrawal, browser instructions, Do Not Track / Global Privacy Control, and a legal-basis section (KVKK on Turkish sites, GDPR/ePrivacy on English ones).
Fixed
- The built-in legal page templates shipped with corrupted text in all 13 themes — Turkish characters and arrow symbols rendered as garbage ("→", "Çerez") on fresh installs that had not saved their own legal pages. The templates were re-encoded and every character now renders correctly in both languages.
- Opening an author archive on the Personal theme returned a server error: a routing variable leaked into the template and shadowed the real author record. Author pages now render on every theme, and a non-existent author correctly returns 404.
- Tag archives could be indexed by search engines even while tag archives were disabled in SEO settings — the sitemap respected the setting but the page-level robots meta did not. With tag archives off (the default), every tag page is now noindex.
- On the Finance theme, the author box at the end of a post showed the author's name as plain text; it now links to the author's archive page, and the Pets theme's archive pages now emit a proper page title and meta description instead of just the site name.
Personal Theme: Full-Width Brand Logo with Automatic Light/Dark Switching
Added
- The Personal theme now supports a full-width brand logo in the header: upload your logo (and an optional dark variant) under Settings → Branding and it replaces the icon + site-name pair, switching automatically with the visitor's light/dark preference. The site name stays in the markup as a visually-hidden heading, so the Google site-name signal is preserved. Nothing changes for sites without an uploaded logo.
Go live today
Setup, content management, SEO and image optimization — all in one platform. Get started in 30 minutes.
View Pricing- Setup and live in 30 minutes
- 14 ready-made themes
- AVIF/WebP image optimization
- Automatic SEO — Sitemap, Schema.org
- Cookieless built-in analytics (ZeroTrack)