Changelog
Release Notes
Every feature, every improvement, every fix since v1.0.0.
Advanced SEO panel: deep audit of all 16 tools
Improved
- SEO Health Check is faster and more honest: on hosts where the site cannot reach itself it stops after one connection attempt instead of blocking for a minute, marks the affected checks as "could not be measured" instead of inventing phantom schema errors, and category/author/content-quality counts now use the same visibility rules as the real sitemap.
- SERP Identity Check never certifies "clean" when the live chain could not be measured, failing checks now show the expected-vs-actual values, and its HTML parsing tolerates attribute order and single quotes (fewer false alarms with custom themes).
- Generated image alt text is Turkish-aware (İstanbul stays İstanbul), media-library fallbacks no longer keep the file extension, and the alt fixer no longer produces a duplicate alt attribute when the image tag lists alt before src.
- The SEO tools' heavy statistics scans now run only on the tabs that display them, making the other tabs noticeably faster on large sites.
Fixed
- Heading Fixer no longer flattens sub-headings: content starting at H3 keeps its H4/H5 structure when shifted up (previously every heading could end up as H2, which also broke theme-generated tables of contents).
- "Send All Posts to IndexNow" now submits only publicly visible, indexable posts — member-only, private and noindex posts are excluded from the batch and from the counter.
- The single-post "Fix" button on the Content SEO tab now fills only the missing meta fields, matching "Fix All" — a hand-written meta title is no longer replaced when only the description was missing.
- The inline meta editor caps titles and descriptions at the real database budget (70/160 characters), so very long entries save cleanly instead of failing with a generic error.
- "Ping Sitemap" reports the real result: the retired Google/Bing ping endpoints no longer produce a false green success — the button now submits the sitemap via IndexNow and shows what actually happened.
- Slug Repair keeps its promise: repaired slugs now create automatic 301 redirects, only genuinely broken slugs are touched by default (hand-tuned slugs stay), and a new opt-in mode regenerates everything from titles when you really want that.
- Year Updater now also updates the SEO title used in Google results (previously only the on-page heading changed while the search snippet kept the old year), and running it back and forth can no longer create redirect loops.
- Redirect manager refuses rules that would loop (A→B while B→A exists, or a redirect pointing at itself via the full site URL) — these previously took the page down with an endless redirect.
- The "fix old URLs" scanner and fixer now share one pattern list built from your own site address, so the banner count and the actual fix always agree (the fixer previously used a stale fixed list and fixed nothing on most sites).
- Batch scans (strip links, fix URLs) use cursor paging so a row the transform cannot change no longer makes the progress loop run forever.
- Auto-linker and Orphan Content now handle Turkish İ/ı correctly — titles containing İ (İstanbul, İş...) can finally receive automatic internal links — and only publicly visible posts are suggested or linked.
- Content Optimizer preserves code blocks: cleanup no longer collapses indentation inside pre/code samples, keeps intentionally empty anchor/placeholder elements, and "reset" no longer deletes the content backups that make revert possible.
- Several admin listing screens in the SEO tools now escape post titles and scan results before rendering, and a few tool endpoints that write content are now administrator-only.
Post SEO analyzer: accuracy fixes and new checks
Improved
- Two new writing checks in the SEO analyzer: a transition-word check (are your sentences connected for flow?) and a long-section check (a stretch of 300+ words with no subheading is now suggested for a subheading) — both work in Turkish and English.
Fixed
- The live SEO score now judges the title by its full rendered length (your title plus the " | Site Name" the theme adds), so a title that looked fine but gets cut off in Google is now flagged — and the SERP preview's length number matches what is actually shown.
- Internal vs external link counting is corrected: a protocol-relative link to another site ("//example.com/…") is no longer miscounted as an internal link.
Migration/import and support module hardening
Improved
- The WordPress migrator plugin (for exporting a WordPress site) now writes its export into a private, per-run randomized folder and deletes the intermediate data files right after packaging, so an export can't be pulled from a predictable URL on servers where directory rules aren't enforced.
Fixed
- Imported content from every WordPress path (CSV, package and REST) now passes through the same content-cleaning step the editor uses, so a hand-edited export or a compromised source site can no longer smuggle active markup into your published posts.
- The REST and wizard migration tools are now administrator-only (they create posts and users and fetch remote content), and the wizard's per-post import step now requires a valid security token — matching the rest of the admin panel.
- Imported posts with an unknown status now land as drafts (in the review queue) instead of going straight live.
- Support ticket attachments can be downloaded again — the download link pointed at a page that did not exist, so staff could attach files but never open them; downloads are now served admin-only through a path-checked handler.
- Support ticket status and priority updates are validated against the allowed set, and the average-resolution-time metric now uses the real resolved/closed timestamps.
SEO plugins audit: social, distribution, Google, recipe
Improved
- Hardening across the SEO surface: social share links now use the canonical URL (so shared and syndicated links never point at a redirect), recipe structured-data text fields are stripped to plain text as Google expects, the browser-push subscribe endpoint is restricted to real push services (SSRF hardening) with a proper per-IP rate limit, and shipped recipe/quiz scripts and push fallback text no longer leak Turkish onto English sites.
Fixed
- Auto-publishing to social networks no longer broadcasts private, members-only, paid or password-protected posts — only fully public posts are shared, and a gated post's social description can never fall back to its full body (which also protected the Dev.to/Hashnode full-body syndication).
- The Google panel's GA4 / Tag Manager / AdSense settings actually take effect now — they were wired to a hook the themes never call, so enabling analytics in that panel injected nothing. They now flow through the site's single, consent-aware analytics injector, so there is one tag set (no double-counting) and cookie-consent is respected.
- The IndexNow "ping on publish" switch is now a real switch — instant indexing could not actually be turned off before, and the panel's "last submit" status was always blank; it now reflects real submissions.
Quiz plugin: premium polish and reliability
Improved
- Result sharing is more robust: X, WhatsApp and Facebook buttons always appear (previously the whole share row vanished on some browsers), a native share sheet is offered on mobile, and copy-link stays where the clipboard is available.
- Keyboard support: press 1–9 to pick an answer and Enter to advance — faster and more accessible play.
- The public play endpoints are now rate-limited against flooding, the instant-feedback endpoint too, and answer keys are returned only for the questions actually answered (no leaking a whole question bank).
- Completion IP addresses in the stats screen are now masked for privacy, and the standalone quiz page no longer shows its title twice.
Fixed
- Embedded quizzes could render with no styling and never start on themes that build a table of contents (they parse the post twice) — the quiz's stylesheet and script are now emitted on every embed, so quizzes always work wherever [quiz] is placed.
- The question/answer image picker stored an absolute URL that the front-end then prefixed again, producing broken images; picked images are now stored correctly and existing broken paths are healed automatically.
- Deleting a quiz now removes its questions, answers, result bands and play records instead of leaving them orphaned, and editing a quiz no longer accumulates dead answer rows; a one-time cleanup clears any leftovers on upgrade.
- Typing a slug that already belongs to another quiz no longer errors and loses your edit — it is made unique automatically.
- Personality quizzes ignore the question-bank subset setting so every result band stays reachable and two identical answer sets always give the same result.
Theme customizer: numeric dropdowns now save correctly
Fixed
- In the theme customizer, dropdown fields whose choices are numbers (for example the Recipes and Travel themes' "Grid columns" 2/3/4 selector) silently reverted to the default whenever you picked a different value — the saved value now sticks. All 14 themes' customizer fields were verified end to end (513 fields across colors, fonts, ranges, toggles, selects, code and image inputs) and theme switching, preview and one-click rollback were confirmed to keep a single clean settings row.
Newer-plugin audit: audience, editorial, edge & forms
Improved
- The editorial kanban board now supports real drag & drop between stages (the card's owner, date and note are preserved), overdue due-dates are highlighted, and editors — not just administrators — can use the board; plugin shortcuts in the admin sidebar are shown only to roles that can open them.
- CRM quality-of-life: a per-contact delete button (for erasure requests), segments show how many members are actually e-mailable, the contact list says when it is truncated, and the activity timeline no longer mixes in other people's form submissions for addresses containing wildcard characters.
- A/B tests: editing, activating or deleting an experiment now clears the page cache immediately (a just-activated test could look dead for the cache lifetime), the winner trophy waits for a sufficient sample, and equal conversion rates are compared exactly.
- Digital downloads and form autoresponders now throttle outgoing e-mail per recipient/site-wide, form values have a sane length cap, and the Cloudflare panel explains that HTML is only edge-cached if you add a Cache Rule.
Fixed
- Audience (CRM): unsubscribed and bounced newsletter contacts are no longer pulled into the audience or its CSV export, the export now carries a newsletter-consent column and streams any list size, contacts deleted at their source are removed on the next refresh, and the audience is refreshed automatically right before a segment broadcast so late subscribers are included.
- Editorial calendar: scheduled posts now actually appear on the calendar on their scheduled day (they were invisible before), a post set to pending elsewhere shows in the Review column, moving a card can no longer race a simultaneous publish, and permanently deleting a post cleans up its planning card.
- Web push: the plugin's settings no longer share storage keys with other plugins (toggling ZeroTrack could silently switch push off and vice versa — existing settings migrate automatically and VAPID keys are preserved so subscribers stay valid), the click counter only accepts clicks for real recent broadcasts with sane limits, and clearly-rejected fake subscriptions are pruned faster.
- Cloudflare: turning "I'm Under Attack" on now reports an error if the API call failed instead of a false success, edge cache purges no longer block post/settings saves (they are queued and sent once per request, also removing duplicate purge calls), scheduled posts published by a real system cron now purge the edge too, and a failed reconnect no longer leaves the panel in a half-connected demo state.
- Analytics real-IP: on sites directly behind Cloudflare, visitor IPs are now resolved from the edge header (validated against Cloudflare's official ranges), so unique-visitor counts, IP exclusions and the flood limiter work correctly instead of collapsing onto a handful of edge IPs.
- Form Builder: renaming a field's label no longer silently detaches historical submissions from their CSV/archive column (machine names are now persisted), field names can't collide with the hidden system fields, and forms embedded on cached pages no longer double-submit with a failed first attempt.
API authorization & content hardening
Fixed
- The automation/REST API now enforces the same role permissions everywhere: creating or deleting posts through the webhook endpoints, and managing categories, tags or comment moderation, now require the proper role — previously any valid API token could do these regardless of the account's role.
- Automation endpoints can no longer edit or delete another author's post, reassign a post's author, or save unsanitized HTML through the bulk publish/import paths (which could inject scripts) — ownership, byline and content cleaning now apply on those paths too.
- The bulk AI analysis job (which sends every post to the AI provider) now requires an administrator, and the per-post AI analysis is rate-limited, so a lower-privileged account can't burn through the site's AI key or quota.
- Search result pages on three themes now count matches the same way the list is built, so the pagination total is accurate and no empty "phantom" pages are produced.
- The marketing newsletter sign-up rate limit is now server-side (it could previously be reset by clearing cookies), the blog RSS feed pins its URLs to the real domain, and a saved post with an unparseable status value defaults safely instead of erroring.
Concurrency, scale & integrity deep-audit
Fixed
- A scheduled post is now published exactly once even if two schedulers happen to run at the same moment, so it can no longer fire duplicate auto-shares, duplicate newsletter sends or duplicate push notifications.
- Deleting a category through the API now refuses when posts are still attached (matching the admin panel), instead of silently stripping those posts of their category.
- Newsletter open and click counts are now counted atomically, so inbox pre-fetching (Gmail/Apple Mail) can no longer inflate the numbers with duplicate counts.
- Comment threads with thousands of replies now build in milliseconds instead of seconds — the threading was rebuilt to scale linearly.
- Dates that can't be parsed (e.g. a malformed or empty value from an old import) now render as blank instead of "1 January 1970", and a post scheduled with an unparseable date is held as scheduled instead of quietly going live immediately.
- Hardening & cleanup: the analytics beacon now ignores spoofed forwarded-IP headers and is flood-limited; the A/B conversion link only counts same-site clicks; saving a site-wide OG image now requires an admin; permanently deleting a post cleans up its view/reaction/rating rows; and login-link tokens plus old newsletter queue rows are now pruned so they don't grow forever.
Search, ads, quiz & security sweep
Fixed
- Instant search now actually uses the fast full-text index instead of silently falling back to a slow full-table scan on every keystroke, and the endpoint is rate-limited so it can't be hammered.
- Device-targeted ads are no longer frozen across devices by the page cache: the cache now keeps a separate copy per device class, so mobile visitors get mobile ads and desktop visitors get desktop ads instead of whichever device loaded the page first.
- Members/paid posts no longer leak their in-body images and embedded videos through the image and video sitemaps — only genuinely public posts contribute body media there (the cover image still appears, as before).
- Two-factor setup now refuses to enable if the secret can't be stored encrypted, instead of quietly saving it in plain text.
- Deleting a media file that's still used in posts now warns you it was in use (so broken image links aren't a silent surprise), and the download store limits how often the same email address can be sent a link (stops link-spam to someone else's inbox).
- Contact/lead forms: the form-builder honeypot no longer uses a field name that browsers autofill, which was silently dropping some genuine submissions; the quiz block now prints its stylesheet/script once per page even with multiple quizzes.
Editor, cache & membership audit
Fixed
- Autosave no longer touches a published post's live body: while you edit a post that's already online, the background save keeps your draft in the revisions list instead of pushing half-finished edits to the live page — nothing goes public until you press Update. New pages also keep their type instead of turning into blog posts.
- Members/paid recipe posts now keep the ingredient list, steps and structured recipe data behind the paywall — the card, the FAQ and the page's recipe schema are shown only to signed-in members, matching how the article body is gated.
- The page cache now refreshes correctly when you trash or restore a post or add a redirect, so removed content and new redirects take effect immediately instead of lingering for the cache lifetime. Cookie-free visitors also always get the site's default language, ending a case where the first visitor's language could stick for others.
- Editor hardening: the button block now rejects javascript:/data: links like the other blocks, content saved by non-admin authors is cleaned server-side, the SEO panel escapes check text, and restoring a revision keeps your hand-picked URL instead of regenerating it from the title.
- Importing images from another site is bounded and hardened further — a per-image size ceiling, certificate verification, and a pinned resolved address stop an oversized or tampered image from stalling the import.
- Storefront: the checkout success page now shows the license key only in a short window right after payment (it's always in your email and portal too), and the update-check endpoint is rate-limited and no longer reflects arbitrary origins.
Full-session audit hardening
Fixed
- For members/paid posts, the page meta description, social share tags and RSS fallback now stay inside the free teaser, so the summary shown to search engines and shared links never draws on gated text.
- Importing images from Ghost/Substack is now SSRF-hardened: image URLs from the uploaded file are checked to be public addresses (internal/cloud-metadata hosts are refused), redirects aren't followed, and oversized images are skipped so one bad file can't stall the import.
- Outgoing webhooks are bounded so an unreachable endpoint can't slow down publishing; deliveries that don't fit the window are logged as deferred and can be re-sent, and a webhook is refused rather than created if its secret can't be stored securely.
- Editor links now reject javascript:/data: URLs like the other card blocks, the snippet endpoint always returns clean JSON, reaction counts are shown only for public posts, and fast double-clicks on a reaction no longer error.
Webhook delivery log & one-click re-send
Improved
- Each outgoing webhook now shows its recent deliveries right under it — the event, the response status (success or the exact HTTP error), and when it happened. If one failed because your endpoint was momentarily down, a single "Re-send" button replays that exact payload with a fresh signature. The log keeps the last 100 deliveries per webhook and never stores your signing secret.
Ghost/Substack import now brings your images too
Improved
- When you import from Ghost or Substack, the images in your posts (and each post's cover) are now pulled into your own media library and converted to AVIF/WebP, and the post is rewritten to point at the local copies. Your migrated content keeps working even after the old site goes offline — no more hotlinked images that break later. It's a single checkbox on the import screen (on by default), matching the WordPress importer.
Multilingual archives & API stability
Fixed
- On multilingual sites, category, tag and author pages, related lists and widgets now show only your site-language posts again; translated posts stay reachable at their own address and are still discovered through their hreflang links.
- The REST API and magic-link sign-in now work reliably on every install, including brand-new ones, and importing from Ghost/Substack cleans up correctly even if the file has an error.
Deep audit hardening across membership, webhooks, editor & multilingual
Fixed
- Content gating is now consistent everywhere: /llms-full.txt, instant search and the About/Contact/FAQ/legal/homepage page routes all apply the same members/paid/private visibility gate as the rest of the site.
- Outgoing webhook signatures are now verifiable: the HMAC was being computed with the encrypted secret instead of the plaintext (a column length also truncated it), so every signature failed on the receiver — fixed end to end.
- A webhook signing secret can no longer be used as an admin API key.
- Newsletter segment sending can no longer silently fall back to the entire subscriber list when the CRM is unavailable or errors — it sends to nobody rather than everybody.
- Reply notifications no longer fire for unapproved/spam comments, so moderation-pending replies can't spray the whole thread by email.
- The paywall teaser is now safely capped even on very short posts, and the reaction bar can now be un-clicked and switched correctly with counts always coming from the server.
- Editor hardening: the snippet library and the bookmark fetcher are now restricted to content roles (not read-only subscribers); the bookmark fetcher pins the validated IP (DNS-rebinding), enforces a hard size cap, and resolves relative images correctly; product/bookmark/gallery/embed card links reject javascript:/data: URLs; the gallery block is now clickable and the four new blocks have their edit/delete toolbar.
- Magic-link sign-in/registration is now rate-limited (anti email-bombing), tokens are single-use under concurrency, and the new-member webhook fires only after the email is verified.
- Ghost/Substack import no longer triggers per-post newsletter/push/social/ping storms, survives BOM and malformed CSV rows, only raises the memory limit, maps Ghost visibility, and skips empty lexical-only posts.
- Multilingual: the language filter no longer breaks reactions, comments, pages, comment feeds or legacy-URL rescue on translated posts — it now applies only to genuine listing surfaces (archives, sitemap, feeds, search) while every translated post stays reachable at its own URL.
Multilingual content v1 + Ghost/Substack migration
Improved
- Multilingual content v1: give any post a language and link it to its translated counterpart from the editor's new Translation box. Linked pairs automatically emit hreflang alternate tags (plus x-default) so search engines serve the right language; archives, sitemap and feeds keep showing only the site language while translated posts live at their own URLs.
- A practical translation workflow ships with it: Duplicate the post, switch the copy's language, link it back by ID — done. No plugin, no separate site.
- Migrate from Ghost: upload the JSON export from Ghost admin and posts, pages, drafts, tags, publish dates and feature images come across — safe to re-run, existing slugs are skipped.
- Migrate from Substack: upload the export ZIP as-is and newsletter posts import with their full body and subtitle; "paid-only" posts automatically arrive with Premium (paid) visibility, matching the membership system one-to-one.
Integrations & engagement: webhooks, segments, reactions
Improved
- Outgoing webhooks are now real: pick events (post published/updated/deleted, new comment, new member), add an HTTPS URL, and jekcms sends signed JSON (HMAC signature header) the moment they happen — Zapier/n8n/Make ready, with a one-click test button.
- Newsletter campaigns can target CRM segments: choose a saved audience filter when sending and only matching active subscribers receive it — the "coming soon" broadcast gap is closed.
- Comment conversations now notify the whole thread: everyone above a new reply is emailed once (deduped), and every notification carries a one-click, tamper-proof opt-out link.
- Emoji reactions arrived on every theme: a theme-independent reaction bar appears under posts with live counts served from the API — fully compatible with the full-page cache; themes with their own reaction UI are automatically skipped.
Fixed
- A leftover placeholder in the cron was silently marking the social-media queue as completed without doing any work — removed; the social plugin's queue is no longer swallowed.
Editor: monetization cards, gallery, social embeds and snippets
Improved
- A Product/Affiliate card joined the editor: image, price, description and a call-to-action button whose link automatically carries rel="sponsored nofollow" — Google-compliant affiliate monetization in two clicks.
- Bookmark cards turn any URL into a rich preview: paste a link, hit Fetch, and the title, description, image and site name are pulled server-side (with strict SSRF protection) into an editable card.
- Gallery grids (2-4 columns) and social embeds arrived: Twitter/X, Instagram, TikTok and Vimeo links become real embeds on the page — the editor stores a neutral placeholder and the site hydrates it, so provider scripts load once and only where used.
- Snippets make repeated content one click: select anything in the editor, save it under a name, and insert it into any future post from the snippet library.
Premium (paid) membership tier
Improved
- Posts can now be marked "Paid members only": anonymous readers get a premium teaser with a join call, signed-in free members see an Upgrade card with your price and payment link, and premium members read everything.
- Selling is friction-free by design: paste any payment link (iyzico or Stripe payment page) plus an optional bank-transfer note in Settings, and when a payment arrives, one click on the Users screen upgrades the member — no gateway integration to configure.
- The member account page shows premium status and the upgrade offer; staff accounts always see full content, and paid posts stay in sitemaps and feeds as leak-proof teasers with correct paywall structured data.
Memberships: members-only content and passwordless sign-in
Improved
- Ghost-style memberships arrived: mark any post "Members only" and anonymous readers see a clean teaser with a join call-to-action while signed-in members read the full piece — on every theme, with zero theme changes.
- Readers join and sign in without passwords: a one-time magic link lands in their inbox (30-minute, single-use), a minimal account page lets them manage their name and newsletter subscription, and joining doubles as newsletter double opt-in.
- Members-only posts stay fully SEO-correct: they remain in sitemaps and feeds as teasers, never leak the gated body anywhere, and carry Google's official paywalled-content structured data so gating is not mistaken for cloaking.
- One-click post duplication (content, categories, tags and metadata copied into a fresh draft) joined the post list actions.
- Your content is never locked in: a new Export panel downloads everything as WordPress WXR, Ghost JSON or jekcms JSON — categories, tags and SEO fields included.
Full-page cache: millisecond pages for visitors
Improved
- A textbook full-page cache now serves the homepage, single posts, category, tag, author and date archives to anonymous visitors straight from disk — measured locally, pages dropped from 60-200ms to 4-9ms.
- Cached copies are invalidated exactly when content changes: saving a post, moderating a comment, editing categories/tags/menus/users, changing settings or the theme all clear the right copies immediately; a small share of requests still runs the full engine so scheduled tasks keep ticking.
- Comment and contact forms became cache-safe: the security token is no longer baked into the page — it is fetched the moment a visitor actually starts filling a form, so anonymous browsing stays completely cookie-free.
Fixed
- Every single visit was silently receiving a session cookie because the user loader started a session even when there was nothing to load — this broke the lazy-session design site-wide and made pages personally-addressed for no reason.
- Two themes' view counters opened a session per article view; they now use the cookie-free central counter, and A/B-test pages, dark-mode/language-cookie visitors and search results are correctly excluded from the cache.
Deep performance pass: queries, caching and page weight
Improved
- Repeated database work was eliminated across the board: prepared statements are reused, per-image lookups are memoized, sidebar aggregations are cached, empty results now cache correctly, and hot columns gained indexes.
- Theme pages got lighter: template-specific stylesheets load only on their own template, mobile-only CSS no longer blocks desktop rendering, fonts load from the page head instead of a chained CSS import, and analytics/ad hosts get an early connection.
- Saving a post now runs its category/tag/meta writes in a single transaction, and archive pages batch-load categories instead of querying once per card.
Fixed
- Six plugins were silently re-running their entire installation schema on every single page view due to a settings-key collision — the single biggest hidden cost on every site; pages now run dramatically fewer queries and zero writes.
- The featured-image helper returned the full-size original instead of the 1600px variant, so every theme preloaded multi-megabyte camera files as the hero image; the preload also now matches exactly what the browser will render.
- Browsers were told to keep HTML pages for a full hour with no way to refresh them — edits stayed invisible to returning visitors; pages are now edge-cached and browser-validated, and category/tag edits and new posts invalidate the right caches immediately.
- Sitemaps and feeds are written atomically with a generation lock — parallel crawler hits could previously read half-written XML or trigger simultaneous full regenerations.
Categories, archives and search: deep SEO pass
Improved
- Categories gained their own SEO title and SEO description fields in the admin panel, and parent categories now count and list their child categories' posts everywhere — archive pages, indexing rules and the sitemap agree.
- Site search now ranks results by relevance instead of date on every theme, search page titles are capped against keyword-injection spam, and paginated search links finally carry the query along.
- Date archives (old /archive/2026 style addresses) now get a descriptive page title, paginated archive pages carry a page number in their description, and every theme reports its real page size in structured data.
- The site description used by feeds and previews became editable in Settings — until now every installation shipped the same boilerplate sentence — and the homepage title can carry the site tagline.
Fixed
- Address-case variants of category, tag and author pages now redirect to the single canonical address instead of serving duplicate self-canonical copies, and deleted tags leave a proper "gone" record so search engines drop them quickly.
- Two themes silently lost every category description from search snippets over a variable-name mismatch, one theme pinned paginated archives' canonical to page one, and tag pages on two themes either listed the whole site or rendered without a title.
- Tag feeds became real: following a tag's feed used to silently hand subscribers the site-wide stream; category and tag feeds also stopped claiming to be the main feed, and feed images now declare their true format.
- Homepages that paginate now return an honest not-found beyond the last page and give page two and onward their own title and canonical; the theme demo search-blocking robots rule that hid the blog search's noindex from Google was lifted.
Single posts and author pages: deep SEO pass
Improved
- Author pages now carry a full social-profile card: stable identity across paginated pages, a real profile picture in link previews, richer profile structured data, and each author's own posts listed correctly on every theme.
- Article structured data now reports the approved comment count, and social share cards gained an image description, a reading-time line and the post's topic tags.
- Every theme's post page now shows the publish date in a machine-readable form, and the "Updated" stamp only appears when the content genuinely changed.
Fixed
- Bylines no longer invent a writer: when a post has no real author profile the name is shown as plain text instead of linking to an author page that never existed.
- The table of contents on the news theme now works on markdown-written posts, previous/next links on the starter theme point at the real post address, and the pets theme no longer emits a half-finished second copy of article metadata that contradicted the main one.
- Author boxes that were silently invisible now render: one theme queried profile fields under their old names, another never received the author's biography from the page at all.
SEO verification pass: second-round hardening
Fixed
- Database sessions now share the site's timezone, so a freshly published post appears in sitemaps immediately on every host instead of hours later on servers whose database clock runs in UTC.
- Sitemap index announcements now use exactly the same filters as the sitemap files themselves — no more announced-but-empty news/video maps, and trashed marketing posts finally disappear from the public blog, feed and sitemap.
- Old WordPress-style category/post addresses now hop straight to the real post, and every remaining "redirect to somewhere that 404s" chain (authors, categories, attachments, feeds, year archives) returns an honest not-found instead.
- The maintenance page now sends proper no-cache headers, uses the active theme's template, and error pages exist for every status the error route accepts.
- The theme demo gallery moved to a stable address (/demos) — its old address was shadowed on the server and had been unreachable from the navigation.
- Upload-folder protection files are written Apache-2.4-safe everywhere; on hosts without the legacy compatibility module they used to turn whole media folders into server errors. A permanent release-gate check now guards this class.
Deep SEO audit: crawling, presentation and media layer
Improved
- Crawlers can now fetch core stylesheet/script assets and search pages, so pages are rendered and evaluated with their real design and noindex hints are actually readable.
- Sitemaps got stricter: entry dates no longer drift on every visit, image entries always point at working files, scheduled/future content never appears early, and news/video sitemaps respect per-post indexing choices.
- Titles across all themes now follow the configured separator, add a page number on paginated archives, and no longer repeat the site name twice; archive descriptions can come from the tag or author's own text.
- Structured data is more consistent: language, titles and image formats now match across the page's tags, FAQ/HowTo blocks can no longer be emitted twice, and the publisher logo is a raster image with its true dimensions.
- Modern-format (AVIF/WebP) image sources are only offered when the file really exists — on hosts without those formats the browser now always gets a working image instead of a blank box.
- More images carry explicit dimensions and descriptive alt text, the correct hero image gets load priority on every theme, and automatic internal links open in the same tab as expected.
Fixed
- Addresses that do not exist now return a real "not found" status everywhere instead of silently redirecting to the homepage, so search consoles report them correctly and they drop out of indexes.
- Error responses are never cached as healthy pages anymore, and error/410 pages are proper, readable pages with charset, language and a link home.
- Duplicate-address cleanups: uppercase blog links, retired tag aliases, alternate sitemap/robots/feed addresses and www+http visits each collapse to a single canonical address in one redirect hop.
- Date archives are validated (invalid years return "not found") and marked not-to-be-indexed, closing a duplicate-content surface.
Verification pass: admin panel fixes
Security
- Saved AI keys in the multi-key list are no longer written into admin page HTML; rows show a masked “saved” state and each key only changes when you type a new value — leaving a row untouched keeps the stored key.
Fixed
- Some admin confirmation and validation messages (for example the new password-policy warning when adding a user) were saved but never shown on screen; the panel now displays messages from both internal channels.
- On installations whose database was missing two optional pieces, the settings page could cut off mid-render and adding a user could fail with a server error; the missing pieces are now provisioned and both flows were verified end-to-end.
Security hardening: broad audit across the product and site
Security
- Uploaded files are kept strictly non-executable everywhere: the upload-folder protection is now stronger and self-maintaining, and the blocked-extension list covers disguised double-extension names.
- Content upload endpoints now require an explicit upload permission tied to the account's role.
- Editor/API secrets (AI provider keys, SMTP password, webhook secrets) are no longer written into admin page HTML; fields show a “saved” state and only change when you type a new value.
- Order pages are tightened: cancelling an order requires the owner and a confirmed action, and guest checkout is scoped to the buyer’s own account.
- Anti-abuse limits are now enforced server-side on the contact form, verification-email resend, comment likes, newsletter signup and article voting.
- Payment confirmation now verifies the paid amount and currency against the order before completing it.
- The one-click Google connection now only works from a licensed customer domain, and several login/authorization edge cases were closed.
- Error responses no longer include internal technical details, and internal maintenance/report files are kept out of public deployments.
Compatibility: deep sweep for PHP 8.0 servers and lean setups
Fixed
- On servers running PHP 8.0 (the minimum supported version), several areas used a function that only exists in newer PHP: the site footer, the Personal theme and — most critically — the auto-update engine could crash. These now work on every supported PHP version.
- Publishing a post no longer depends on optional server pieces: the search-engine ping, encoding repair tools and the RSS import endpoint all degrade gracefully when a server component is missing, instead of stopping the whole operation.
- The installer now tells the truth about requirements: the cURL component (needed by updates, licensing and integrations) is checked as required rather than merely recommended, so problems surface at install time instead of weeks later.
- The pre-release safety check was deepened: it now also blocks any new code that would require a newer PHP than the product promises, alongside the existing optional-component guard.
Resilience: missing server components can no longer crash any operation
Fixed
- Following yesterday's upload fix, the entire product was swept for the same class of failure — features assuming an optional PHP server component is present. On lean hosting setups this could crash: WebP image reading during WordPress import, migration and Pinterest image generation; AVIF/WebP saving in thumbnail regeneration and the media optimizer; image processing entirely on servers without the GD component (the upload now keeps the original file instead of failing); and update, backup and package operations if the zip component is disabled. Every path now checks first and degrades gracefully with a clear message instead of a server error.
- This protection is now permanent: an automated check runs before every release and blocks any new code that uses an optional server component without a safety check.
Critical: image uploads were completely broken on some servers
Fixed
- On hosting where PHP's optional "fileinfo" extension is disabled, every image upload failed with a "mime_content_type" error — the editor's image dialog, the Pinterest image and the media library were all affected. The file type is now detected through a chain of safe fallbacks (including reading the image header directly), so uploads work on every hosting configuration. If your uploads were failing, update and try again — no other action needed.
Google Console: weekly email digest + rising/declining queries + opportunity list + cache fix
Added
- Weekly performance digest by e-mail: every week the plugin compares the last 7 days of Search Console, Analytics and AdSense with the previous week and sends a compact summary (with ▲▼ trends and the week's top queries) in the site language. Enable it in Settings; runs on the server cron, retries gracefully and never double-sends.
- Rising / declining queries: the Search Console tab now compares the selected period with the previous one and lists the queries that gained and lost the most clicks — including queries that disappeared entirely.
- Opportunity queries: keywords that show often in Google (ranking 4-20) but get few clicks — the fastest wins for title/description improvements, sorted by impressions.
- Pages losing traffic: content-refresh candidates ranked by click loss versus the previous period.
Fixed
- The API response cache effectively never worked on servers where PHP and MySQL run in different time zones: expiry times were written with the PHP clock but checked against the MySQL clock, so every cached entry was born already expired (by the zone offset) and every panel visit hit Google's APIs live — this is why the panel could feel slow or unstable. Expiry is now computed on the database clock.
Contact Form: reply from the panel + bulk actions + CSV export + phone field
Added
- Reply from the inbox: write your reply under the message and send it by e-mail without leaving the panel — the visitor receives it with their original message quoted, and the message is marked "replied" with the reply stored on the record. (The "replied" status existed but nothing ever set it; the old Reply button just opened your mail app.)
- Bulk actions: select multiple messages and mark read / spam / archive / delete in one go, plus one-click CSV export of the inbox (Excel-ready, with spreadsheet-formula injection neutralized).
- Optional phone field: enable it in settings and the form shows a phone input (validated loosely for international formats); the number appears under the sender in the panel and in the notification e-mail. Themes that pass their own field list are unaffected.
- Auto-reply personalization: the {name} tag in the auto-reply subject and body is replaced with the sender's name.
- Field-level error display on the form: validation errors now appear under the exact field and the first one is focused — the styling for this existed but was never used; visitors only saw a generic "check the form".
Fixed
- Spam-flagged messages were stored without any cap — a bot flood could grow the table indefinitely (the "no message is ever lost" design kept everything). The newest 300 spam records are now kept and older ones pruned, matching the Form Builder's protection.
Form Builder: conditional logic + multi-step forms + smarter validation
Added
- Conditional logic: any field can be shown only when another field meets a condition (equals / does not equal / is empty / is not empty / contains). Hidden fields are skipped by validation and never stored — the server re-evaluates every condition itself, so hand-crafted requests can't smuggle values in.
- Multi-step forms: drop a "page break" between fields and the form turns into steps with a progress indicator and back/next buttons; each step validates before advancing, and with JavaScript off everything gracefully falls back to a single long form.
- Per-field error display: validation errors now appear under the exact field (with the wizard jumping back to the right step and focusing it) instead of a single generic message.
- Multi-checkbox groups: a checkbox field with options now renders one checkbox per option, with "at least one required" enforced in the browser and on the server. Previously the options were validated but never rendered — the form always showed a single box.
- Duplicate form action in the list, and "redirect after submit" now actually redirects in the no-page-reload (AJAX) flow too.
Fixed
- A field saved without a width value (via the API or programmatically) crashed the save with an "Undefined array key" error; the admin form always sent a width, which masked it.
- The confirmation redirect URL is now validated when saving — non-http(s) addresses are rejected instead of being passed to the browser.
Web Push: campaign composer + click statistics + welcome notification + background secret-decryption fix
Added
- Campaign composer: write and send any notification (title, message, target URL, large image) to all subscribers from the admin panel — until now the panel could only send a fixed test message.
- Broadcast history with click tracking: every send (new post, campaign, test) is logged with delivered/failed counts, clicks and CTR. Clicks are counted by a lightweight beacon from the notification itself — no third-party service, no personal data.
- Welcome notification: optionally greet each new subscriber with a one-time, customizable notification the moment they subscribe — they immediately see that notifications work.
- Configurable opt-in button: position (bottom left/right), custom label, show delay, and a dismiss (✕) that snoozes the prompt for a configurable number of days. Previously the button was fixed, undismissable and shown forever.
- Rich notifications: new-post pushes now carry the post's featured image as a large picture on supported platforms; campaigns can attach one too.
- Subscriber analytics on the panel: growth in the last 7/30 days and a browser breakdown.
Fixed
- Background jobs (cron, deferred sending after the page is delivered) could silently fail to decrypt stored secrets: if any output had already been produced when the security layer initialised, session setup threw and decryption returned empty — for Web Push this meant the whole broadcast was silently skipped with an unusable VAPID key. Session configuration now degrades gracefully after output has started, so encrypted secrets remain readable in every background context.
Quiz: premium engine (timer, instant feedback, question bank, weighted personality) + fixes
Added
- Time limit per quiz: a countdown runs while playing and the quiz auto-submits with the answers picked so far when time runs out.
- Instant feedback mode: as soon as the reader picks an answer, right/wrong (and the explanation, if enabled) is shown before moving on. Correct answers still never appear in the page source — each check is answered by the server, and the endpoint only responds for quizzes that opted in.
- Question bank: shuffle question order and/or serve a fixed number of questions from the pool on every run — each play gets a different quiz. Scoring uses the served count, not the pool size.
- Weighted personality engine: every answer can carry points and the result card is chosen by the point total — the standard model of premium personality quizzes. Trivia scoring is unchanged.
- Result sharing: copy link, X, WhatsApp and Facebook buttons on the result screen, with the score or personality result in the share text.
- Duplicate quiz action in the admin list, drag-to-reorder questions in the editor, and a working media picker for quiz, question and answer images (the old "Browse" button always fell back to "enter the URL manually").
- The standalone quiz page now emits Quiz schema (JSON-LD) — deliberately without questions or answers, so correct answers stay out of the page source.
Fixed
- On themes that pre-parse content (e.g. to build a table of contents), the embedded quiz lost its stylesheet and script — questions never rendered. The assets now travel with every embed, and the view counter no longer double-counts on those themes.
- When editing an existing quiz, the field labels showed raw template code ("${QI18N.qText}") instead of text.
- The admin quiz screens mixed Turkish and English ("No quiz plays yet yok.", untranslated settings and buttons); the share image URL of the standalone quiz page was relative, so social preview cards came out empty.
Recipe Cards: visual recipe editor in the post editor + premium card features
Added
- The post editor gained a full Recipe panel: structured ingredient rows (quantity, unit, name, note) with group headings ("For the sauce"), drag-to-reorder steps with optional step photos, minute-based time fields with automatic total, servings, difficulty, course/cuisine suggestions, nutrition facts and an FAQ builder. Until now this rich recipe data could only be produced by the AI content pipeline — writing a recipe by hand meant raw ISO-8601 duration codes in the SEO schema panel.
- Bulk paste: paste a plain ingredient list ("200 g flour") or numbered steps and the panel splits quantity, unit and name into rows automatically.
- Recipe video support: paste a YouTube, Vimeo or mp4 link — the card embeds the player and YouTube videos are added to the Recipe schema as a VideoObject (eligible for video rich results).
- Cook mode on the recipe card: one tap keeps the phone screen awake while cooking (on supported browsers; the button hides itself elsewhere).
- "Copy list" button on the card copies the ingredient list — including scaled quantities when the reader changed the serving count.
- Printing now prints only the recipe card, not the whole page; a Notes/tips box and step photos are shown on the card as well.
- The [recipe] shortcode places the card wherever you want inside the content — and works on every theme, not just the recipes theme.
Fixed
- On a recipe post without a usable image, the plugin correctly skipped the Recipe schema node but silently dropped the FAQ schema with it — FAQ rich results were lost on exactly the posts that needed them. The FAQ schema is now emitted independently.
- Recipe difficulty was displayed in raw English data tokens ("easy") on Turkish sites; known values are now shown in the site language.
- Step photos were included in the schema but never shown to readers on the card; they now appear under their step.
Stories audit: "Latest Posts" statistics + navigation fix
Improved
- The whole plugin was re-verified live: poll vote integrity, per-visitor replay windows, reaction-switch accounting, slide ownership checks and the sanity of the new virtual-story validation (unknown posts rejected, polls not accepted on the automatic story).
Fixed
- Views, link clicks and emoji reactions on the automatic "Latest Posts" story were silently discarded by the server — visitors saw the reaction animation but nothing was ever counted, and the statistics page had no trace of the story most sites use the most. These events are now recorded (with the same replay protection as manual stories), reactions show up in the ambient emoji stream, and the statistics page gained a dedicated "Latest Posts" card breaking performance down per post.
- With "auto-advance to next story" turned off, swiping or tapping to the next story closed the viewer entirely instead of advancing. That setting now only controls what happens when a story finishes on its own — manual navigation always moves to the next story.
Web Push audit: no subscriber misses a notification + dead-subscription cleanup
Improved
- When the browser rotates a push subscription, the service worker now re-subscribes automatically instead of silently going quiet. Sending got faster on large lists (the signed authorization is computed once per push service instead of per subscriber) and the delivery connection is explicitly TLS-verified with redirects refused. The whole plugin was re-verified live against a mock push service: crypto self-test, dead-endpoint pruning, budget cursor, tick lock and intake validation all confirmed.
Fixed
- On sites with many push subscribers, publishing a post only notified as many browsers as fit into the sending time window — the rest simply never received that notification. Sending now remembers exactly where it stopped and continues in the background (server cron and page-triggered fallback, with a lock so no browser is ever notified twice) until every subscriber has been reached.
- Subscriptions that kept failing without properly expiring (persistent errors, unreachable endpoints) were retried forever on every publish, eating the sending window. After 8 consecutive failures a subscription is now cleaned up automatically.
- A subscription registered with a valid push service but corrupt encryption keys was accepted and then failed on every send; keys are now validated byte-for-byte at registration.
AI Images audit: pin domain fixed + scaling and provider improvements
Improved
- The visual-concept helper now uses the same hardened network settings as image generation (strict TLS, no redirects, response size cap), and the generation log cleans up entries older than 180 days by itself. The whole plugin was re-verified live: concurrency lock, daily cap, image validation, oversized-response cut-off and redirect refusal all confirmed working.
Fixed
- The "Pinterest / Recipes pin" style rendered a fixed website address into the bottom strip of every generated pin — regardless of which site generated it. The pin now carries the site's own domain automatically.
- The "posts with missing images" list loaded the full content of every published post into memory to count images; on a site with thousands of posts that could exhaust memory. Counting now happens inside the database and the screen stays fast at any size.
- With OpenRouter selected as provider, the settings screen still warned "no Gemini API key" and style-preview generation insisted on a Gemini key. Both now follow the selected provider.
jekcms.com audit: contact form repaired + language redirect fixed
Improved
- The marketing site was audited top to bottom: 38 pages in both languages (render integrity, silent log noise, titles, canonical and hreflang tags, single H1), all 88 internal links, sitemap/robots/feeds/docs search, payment checkout links and both forms — everything else came back healthy. The "Try the admin panel live" band on the themes page now sits below the theme list, and a new automated suite guards the form pipeline against regressions.
Fixed
- The jekcms.com contact form rejected every single submission with a "security token mismatch" error: the page stored its security token in one session while the receiving endpoint checked a different one, so the two could never match. The form now fetches a fresh token at the moment of submission — messages actually arrive and open a support ticket. The footer newsletter form carried a lighter version of the same risk and now uses the same always-fresh-token pattern.
- Opening a jekcms.com page with the ?lang=tr shortcut on a direct .php address redirected to a dead URL (for example /blog.php?lang=tr landed on a 404). The Turkish redirect target is now normalized to the clean address, and subdirectory installs no longer produce doubled paths.
General audit: post reactions/ratings completed + silent error floods ended
Improved
- The whole automated test battery was run end to end — 65+ suites, 2,000+ checks, all green — covering plugins, themes, mail, licensing, installers, customer portal and admin access controls.
Fixed
- The Entertainment theme's reaction buttons (🔥 ❤️ 😮) and star ratings were half-built: the interface was drawn and clicks were sent to the server, but the receiving endpoint never existed and the database tables were never created — counts always showed zero, reverted on reload, and every page view silently wrote errors to the log. The feature is now real end to end: one reaction and one rating per visitor (updatable), public-published posts only, rate-limited, and the tables create themselves on first use.
- The settings-change timeline (who changed which setting, with undo) had never worked: its query joined a table name that doesn't exist in the product, so the history always came back empty and every dashboard load added another silent error to the log. The audit found 1,600+ recorded changes that are now actually visible.
- Small persistent warnings cleaned up across jekcms.com: the admin invoice list read a wrong column name for due dates (overdue highlighting never fired), 404 pages warned about a missing canonical URL, the blog listing warned on every load, and two 2.65-era changelog entries had no title and rendered a warning on the public changelog page.
Customer accounts: clear verification flow + session security
Improved
- One password policy across the whole customer portal (register, reset, profile, sign-up modal): at least 8 characters with a letter and a digit, and obvious passwords are rejected — "12345678" is no longer a valid password for an account that holds licenses and purchase history. Both blog-site user management and the customer portal were audited end to end on a live environment: brute-force lockouts, role whitelists, IDOR scoping on orders/tickets/invoices/licenses, OAuth account-linking protections and 2FA flows all verified working.
Fixed
- An unverified customer account was silently bounced back to the sign-in page in an endless loop with no explanation — right after registering, after signing in with the correct password, and after changing the email address on file. Every entry point now explains what happened and links to "resend verification email"; registration no longer opens a session that gets dropped one request later, and changing your email signs you out cleanly with a clear note instead of appearing to crash.
- Profile password changes and admin-side password resets now bump the session version, so every other signed-in device is signed out immediately — only the device that changed the password stays in.
Editor SEO assistant: score verified live + 4 new checks
Added
- The post editor's SEO assistant gained four new checks, shown only when the issue actually exists: a stale year in the title (e.g. "2024 guide" in 2026), heading sections with no content under them, generic link text like "click here", and long articles (1000+ words) with fewer than two images.
Improved
- The SEO score engine was verified end to end in a real browser: a blank draft scores exactly 0, Turkish dotted-İ keyword matching and inflected-word density counting work, over-density and readability warnings fire correctly, and on every scenario the dial score matches the sum of the per-category points exactly. The computed score is also confirmed to be saved with the post and shown in the post list.
Newsletter: campaigns now send themselves
Improved
- The whole subscription pipeline was audited end to end on a live site: sign-up protections (honeypot, rate limit, spam filter, mail-bomb cap, address-disclosure parity), double opt-in with token rotation, one-click unsubscribe headers, open/click counters with signed links, and bounce pre-flight all verified working.
Fixed
- Newsletter campaigns only went out while an admin kept clicking "send next batch", or on servers with a manually configured cron job; on a typical installation a campaign larger than one batch — and every automatic new-post notification — sat in the queue forever. The queue is now processed automatically: the built-in scheduler drains it in small batches as the site gets visits, and the server cron (where present) drains it in full — with row-level locking so the two never send the same email twice, and nothing is sent while the newsletter is disabled or the plugin is deactivated.
Visual theme audit: readability and dark-mode fixes
Fixed
- Every theme was rendered in a real browser in both light and dark mode and measured for text readability; unreadable spots were corrected across nine themes — badge and button text on bright brand colors, faded date/muted text, table-of-contents boxes and post cards that stayed white in dark mode, a newsletter band whose white text vanished on its yellow gradient, and an oversized content image that forced horizontal scrolling.
- When you pick a light brand color in the customizer, badge/button text on that color now switches to dark automatically (and link-style brand text is deepened just enough to stay readable) instead of staying white and disappearing.
- The travel theme's default menu no longer links to pages that don't exist on the site; "Destinations/Tips" entries appear only when a matching category exists and point straight to it.
- The shared sidebar widgets (tags, categories, recent posts) now stay readable in dark mode on every theme, even when a theme doesn't define its own dark palette for them.
Theme audit: broken-image safety net + graceful demo-media fallback
Added
- A new deep theme audit exercises all 13 themes across eight page types each — checking rendering, single H1, canonical tags, encoding, leaked shortcodes, layout-section contracts and every referenced asset. All 517 checks pass on both an English and a Turkish site.
Improved
- The travel theme's showcase images (front-page slider, about page, archive banners) now appear only when the files actually exist on the installation; sites without the demo media pack get a clean dark banner instead of broken image icons.
Fixed
- Content written on a development machine could carry "localhost" image addresses into the live site, showing readers broken images (one live post was affected and has been repaired). Rendering now silently rewrites such development addresses to the site's real address — only inside image and link attributes, so articles that mention localhost in their text or code samples are untouched.
- The finance theme linked an apple-touch icon file that doesn't ship with the theme, producing a broken request on every page; the icon already comes from the site's central favicon pipeline, so the stray link was removed.
Site Versions screen + lasting analytics history + cleanup
Added
- License server: a new "Site Versions" screen lists every licensed installation that checks in with the update server — its domain, last reported version, PHP version and last-seen time — and flags at a glance which sites are up to date, which are running behind, and which have gone silent for two weeks. Check-ins are recorded only for valid licenses actively bound to the reporting domain.
Improved
- Analytics: the daily trend chart now also reads the permanent daily summaries, so date ranges older than the raw-data retention window (90 days by default) show real history instead of an empty chart. The summaries had been collected all along but were never displayed.
- The demo site now applies updates automatically every day and its nightly reset preserves that setting, so the public demo always showcases the current release.
Fixed
- Eight plugins registered an admin-menu hook that the panel never fires; the dead registrations were removed (menu entries continue to come from the panel's own list, nothing visible changes).
- The internal schema check misread SQL comments and nested data blocks, hiding real columns and reporting phantom ones; with the parser fixed and three schema reference files brought up to date, the known-issues backlog dropped from twelve to zero.
General audit: silent log flood stopped + plugin registration repair
Improved
- Four plugin distribution tools were missing two installations from their target lists, so future fixes for those plugins would silently skip them; the lists were completed (the same gap was fixed for the SEO panel earlier).
Fixed
- The admin dashboard queried social and push-notification tables even on installations where those plugins were never activated; the page rendered fine, but every single dashboard visit silently appended errors to the database log (one installation had accumulated 47,000 lines). The dashboard now checks the schema first and simply shows zeros, and it also adapts to older social-queue schemas instead of failing.
- The Google Console plugin's activation script used a wrong column name when registering itself, so it logged an error on every update and could fail to register on a fresh site; the column name was corrected.
- Two internal quality checks had fallen out of date after recent changes (quiz answer response and content-filter wiring) and reported false alarms; they now verify the actual behaviour instead of exact source text, and five already-resolved records were cleaned out of the schema check's known-issues list.
Both languages everywhere: 10 themes + admin panel fully TR/EN
Added
- A live bilingual audit tool now logs into the panel and crawls the critical admin screens and public pages of every site in BOTH languages, catching raw dictionary keys, Turkish text in English mode and English text in Turkish mode — 140 fleet checks and 45 deep checks all pass.
Fixed
- Around 1,100 hard-coded interface strings across ten themes (travel, pets, finance, minimalist, recipes, crypto, tech, entertainment, health, starter) now follow the site language: comment forms, newsletter boxes, search, 404 pages, pagination, reading time, share labels and screen-reader labels all render in Turkish on Turkish sites and English on English sites.
- The admin panel now honours the admin language setting consistently: the login screen tagline, every date (month names were printed in Turkish even in the English admin), the media upload box and the license screen no longer mix languages.
- Thirteen dictionary entries that displayed their internal key instead of text (e.g. the date filters on the Posts screen) and nine English dictionary entries that contained broken Turkish text (e.g. the login subtitle) were repaired in both languages.
- A site language saved as a regional code like "en-US" was silently falling back to Turkish; regional codes are now normalised, so an English site no longer renders a Turkish interface.
- Two sites were running theme copies months behind the product (missing every rollout since the layout engine); all fleet theme copies are now byte-identical with the product and a new sync tool keeps them that way.
SEO: AI visibility audit (llms.txt + AI crawler policy)
Added
- SEO Health Check gained an "AI Visibility" group: it now verifies that llms.txt and llms-full.txt (the site summaries ChatGPT, Claude and Perplexity read) are actually being served, summarises your AI crawler policy (how many of the 13 known AI bots are allowed), and confirms the live robots.txt really reflects that policy — so a stray static robots.txt file can no longer silently override your choice.
Fixed
- Advanced SEO propagation lists were completed: the plugin's activation file joined the fleet sync list and two installations missing from the dedicated sync tool's target list were added, so future panel fixes reach every site instead of silently skipping some.
Audience (CRM): export a segment, faster counters, tighter access
Added
- Each saved segment now has its own "Export CSV" button, so you can download exactly the contacts a segment covers in one click — not just the whole list.
Improved
- The audience summary counters (total plus one per source) are now computed in a single database pass instead of five separate scans, so the Audience screen stays fast on large contact lists.
Fixed
- The admin-only access check on the Audience screen is now unconditional, closing a theoretical gap where the contact list (personal e-mail addresses) could have been reachable by a lower-privileged user if the code were loaded differently.
Social: non-blocking Instagram/Threads publishing + Pinterest image fix
Fixed
- The per-post Pinterest image field in the editor now saves. It was posting to an address that had no route, so the value was silently dropped — the pin image you set was never stored.
- Publishing a photo, story or carousel to Instagram — and a post to Threads — no longer holds a worker busy waiting for the platform to finish processing. Ready posts go out immediately; ones still processing are picked up on the next pass, the same way Reels already worked. Before, a single post could tie up a worker for up to half a minute.
- When a social post succeeds, its remote post id and publish time are now recorded on the queue entry itself (not only in the log), so the published-at time and a link back to the post are available.
Recipe card: servings scaler, card image fix, sturdier rich results
Added
- Recipe cards now have a servings adjuster: readers tap − / + to change the number of servings and the ingredient amounts scale automatically. Whole numbers, decimals and fractions (½, 1½, 1/2) are all handled and shown back as neat fractions; anything that isn't a plain amount ("a pinch", "2–3") is left untouched.
Fixed
- A recipe with only a cover image (no separate step photo) now shows that image on the card. Before, the card's image was computed but never displayed unless a separate process photo was set, so many cards appeared with no picture.
- The recipe's star-rating rich result is now emitted only when the rating is a real number within range and has at least one vote — a stray or out-of-range value could previously invalidate the whole recipe rich result in Google.
- A recipe with an unreadable publish/update date no longer stamps the structured data with a 1970 date; the field is simply left out instead.
- Prep/cook/total times written with a day component (for long-rested recipes) are now counted correctly instead of reading as zero.
Quizzes: fairer scoring, answer explanations, cleaner personality results
Fixed
- A question with more than one correct answer is now scored fairly: picking any of the correct answers counts as right. Before, only one of them was accepted and a reader choosing an equally-correct answer was marked wrong.
- The "Show explanation" option now actually works — when it's on, each question's explanation appears in the results review after finishing. It had no effect before.
- The "Auto-scroll" option now works too: moving to the next question gently scrolls the quiz back into view, which helps on phones. It was also previously inactive.
- Personality quizzes no longer show a "3/10 correct" score or right/wrong marks — those don't apply to result-based quizzes, so now only the result card is shown.
Plugin review, round four: social, forms, CRM, analytics
Improved
- Social & Video: YouTube uploads use a tighter per-chunk timeout so a single slow chunk can no longer tie up a worker; the upload simply resumes where it left off.
- Analytics: the tracking beacon no longer re-checks the database structure on every single page view — it only sets things up if something is actually missing.
- Audience (CRM): segment sizes are now counted directly in the database instead of loading every matching contact into memory, so the Segments screen stays fast on large lists.
- A/B tests: a winner is now declared only once every variant has reached the full sample size, matching what the screen tells you to wait for.
- Forms: spam submissions can no longer grow without bound — only the most recent are kept per form.
Fixed
- Social: the connected app's client secret is now stored encrypted, matching how access tokens are already protected.
- Video Studio: the 90-second limit is now enforced on the server too, so an over-long video can't slip through and be rejected by Instagram — you're asked to shorten the script and re-render instead.
- Contact form: on older installs, clicking "Spam" on a message could silently lose it; the message list now repairs the underlying field first so the message is safely kept.
- Forms: dropdown / radio / checkbox answers are now validated on the server against the defined options, so a made-up value can't be slipped past the form.
Plugin review, round three: push notifications, downloads, AdSense checker
Improved
- AdSense readiness checker: the scan no longer loads every post into memory at once, so it runs reliably on sites with thousands of posts.
Fixed
- Push notifications: the list of trusted push services is now matched strictly, so a look-alike address (a domain merely ending in a trusted name) can no longer register and receive your notifications, and only secure addresses are accepted.
- Push notifications: publishing a post no longer waits for every subscriber to be notified before the save completes — the save finishes at once and notifications are sent right after, within a time budget so a large subscriber list can never stall or crash the publish.
- Downloads: a download link with a set limit can no longer be pushed past its limit by firing several downloads at the exact same moment.
- Editorial calendar & recipes: the admin permission check on these screens is now unconditional, closing a theoretical gap where it could have weakened if the code were loaded differently.
Plugin review, round two: quizzes, Google, recipes, Cloudflare
Improved
- Google: the plugin no longer re-checks its database structure on every admin page load — it does so only once per version.
- Cloudflare: clearing the cache after you publish or edit a post no longer holds up the save while Cloudflare responds — the save finishes immediately and the purge runs right after.
Fixed
- Quizzes: a page containing an embedded quiz could fail to load because the view counter had nowhere to record to. The counter now has its place, is added automatically to older sites, and can never take a page down again.
- Quizzes: a published quiz now has its own shareable page, so the "View" link in the admin opens the quiz instead of a "not found" error.
- Quizzes: the WordPress importer now refuses image and page addresses that point back into the server's own network, and verifies the remote site's certificate.
- Google: the "automatically notify Google when new content is published" checkbox now genuinely turns the feature on — before, it looked enabled but every submission was quietly refused.
- Google: the manual "submit for indexing" action now only accepts addresses on your own site.
- Recipes: a recipe with no usable image no longer publishes structured data that Google would reject — the recipe rich-result is emitted only when it will actually validate.
- Cloudflare: applying the recommended security rules can no longer wipe your own custom firewall rules if reading the current rules momentarily fails — the change is aborted instead.
Plugin review, round one: safer AI images, newsletter and notifications
Improved
- Web notifications: subscriber records are handled more efficiently, without needless database work on every visit.
Fixed
- AI images: a picture returned by the image provider is now downloaded only from a safe public address; an address that points back into the server's own private network is refused.
- AI images: when generation fails, the error message no longer risks showing your API key — the key is now hidden.
- AI images: if the daily image limit can't be read for a moment, the system now stops generating rather than continuing without a limit, so you are never billed past your cap by accident.
- Newsletter: an email template you edited by hand is no longer overwritten by an update — only templates you never touched are refreshed.
- Newsletter: the weekly digest is now sent only once even if two runs happen to start at the same moment.
- Newsletter: the sign-up form no longer reveals whether an address is already on the list — the reply is the same either way.
- Web notifications: the subscribe endpoint is now protected against being flooded with fake entries.
- Stories: reaction counts now change only from a genuine visitor tap, and a reaction sent from another site is ignored.
Video Studio: 90-second cap so videos stay Reels-eligible
Improved
- Studio videos are now capped at 90 seconds. Instagram only places videos of 90 seconds or less in the Reels tab; a longer one would post as an ordinary video instead. The narration is already about a minute, so this only affects manually lengthened scripts — and when it does, both the picture and the sound are trimmed at the same point, so the file really stays within the limit. The script step notes the limit as you type.
Video Studio: sturdier YouTube and Instagram publishing
Fixed
- A Reels or Shorts upload that got stuck while the platform was still processing it could keep polling for up to a day. Such a job now gives up after a reasonable window and is marked failed, so one stuck upload no longer ties up the publishing queue or the daily quota.
- A video scheduled for a future time is no longer mistakenly timed out because of the wait before its scheduled moment — the timeout window now starts from the scheduled time, not from when the job was created.
- The full multi-step publishing flow for both platforms — Instagram's create / wait / publish sequence and YouTube's resumable upload that continues after an interruption — was verified end to end, including recovery when a connection drops or a session expires.
License security hardening
Fixed
- The admin license screen now shows only a masked version of the license key instead of the full value.
- License activation and deactivation now require an admin login on every install, including freshly installed sites that do not yet have an active license.
- Demo-license validation now relies on the site's configured address rather than a value taken from the request, so activation stays tied to the real domain.
- Premium features, plugins and themes now follow the installed edition: a paid package (already purchased to download) keeps everything unlocked even if its token lapses, while the free package is correctly limited.
- The update-download endpoint now rate-limits per address and only responds to expected origins.
New: Video Studio — turn posts into narrated Shorts and Reels
Added
- Video Studio (in the Social plugin): pick a post and the studio writes a ~60-second narration script in your site's language, reads it aloud with a natural AI voice (30 voices, Turkish included — uses your existing Gemini key's free tier, so it costs nothing), and renders a 1080×1920 vertical video with your post's images, animated captions and your site's name — right in your browser. No server video software is needed, so it works on ordinary shared hosting; rendering requires Chrome or Edge.
- One-click publishing to YouTube Shorts and Instagram Reels through the existing social queue, with retries and rate limiting handled for you. Instagram connects with your own Meta app in development mode — publishing to your own account needs no app review. For YouTube, connect your own Google Cloud app; note Google locks videos from unverified API projects to private, so until you complete Google's verification the studio's "Download + open YouTube Studio" button is the recommended path — it saves the video, copies the title and description to your clipboard and opens YouTube Studio, making manual upload a 30-second task.
- Every text the studio produces — narration, YouTube title and description, Instagram caption, hashtags — is fully editable before anything is voiced, rendered or published. A "draft job" can be opened automatically whenever you publish a post, so fresh posts wait for you in the studio.
Comments and the contact form: lost messages found their way back
Fixed
- On the Personal theme the contact form posted to an address that did not exist: every message a visitor sent ended in a 404 and was never stored anywhere. The address now reaches the protected handler, and when JavaScript is off the visitor is brought back to the page with a clear "received" or "failed" notice instead of a raw code screen.
- On the Entertainment theme comments were broken twice over: approved comments were never shown (the list pulled in a file that did not exist), and a signed-in reader's comment was always rejected asking for a name the form never collects. The list renders again and the handler now fills in the reader's name and email from their account.
- On eight of fourteen sites the spam capture log still had an old table layout, so every catch failed silently: blocked bots left no trace, the admin screen showed zero blocks, and the "repeat offender" signal never fired. The table now completes its own missing columns on first use.
- Thirteen themes' comment forms used a spam-trap field literally named "website" (one theme even added "phone"). Browsers recognise those names and auto-fill them — and a real reader whose browser did so had their comment silently thrown away. The trap fields now use a neutral name browsers ignore.
- Every comment and contact submission was counted twice against the flood limits, so the caps the admin configured were effectively halved.
- All three settings on the contact form panel were dead: the recipient address was saved but notifications kept going to the general address, the custom success message was never shown, and the auto-reply was never sent at all. All three now do what the screen says — auto-replies also carry a once-per-hour-per-address brake.
- The site-wide comments feed now includes only comments from published, public posts. It is also reachable now: the feed advertised its own address but the address had no route and bounced to the home page.
- The comment moderation screen and the panel reply endpoint now require full moderation permission, not just any signed-in account.
- A reply written from the panel did not update the post's comment counter, and the person being replied to never got the "someone replied to you" email even when that notification was switched on.
- Comment notification emails were always in Turkish, even on English sites; they now follow the site language. The contact form's success and error notices also had no colour in themes without their own styling.
A/B tests: the numbers are now real visitors' numbers
Fixed
- A/B test results counted search engines and automated crawlers as if they were readers: every crawl added impressions, and a crawler following the conversion link added conversions. A test could crown the wrong winner on traffic no human ever saw. Crawlers still see the page content as before, but they no longer touch the statistics.
- On a site installed in a subfolder, a conversion goal written as a plain path ("/contact") redirected the visitor to the server's root instead of the site's own page — usually a 404. Plain paths now resolve against the site's own address.
- Behind services like Cloudflare, every visitor appeared to arrive from the same address, so which variant a visitor saw depended almost entirely on their browser make — most people got the same variant and the split was badly lopsided. The variant assignment now uses the visitor's real address when a trusted proxy provides it; sites not behind a proxy are unaffected.
- Turning a plugin off left its placement codes ("[ab id=3]", "[form id=5]"…) sitting in the middle of published posts as raw text for every reader. Leftover placement codes from an inactive plugin are now removed from the page.
- Plugin placement codes also leaked as raw text into the RSS, Atom and JSON feeds, because feeds deliberately skip the plugin rendering step. Feeds now clean them out at the source.
Analytics: the settings on the screen now actually do something
Improved
- Every page of every site ran three table-creation statements and nine setting inserts before rendering, on every single request. That check now happens once and remembers the answer; the admin screens still repair themselves on demand.
Fixed
- The analytics master switch did nothing. Turning tracking off left the counting script on every page and the receiving endpoint still wrote every visit to the database, even though the screen said no data would be collected. The endpoint that receives visits now reads the settings before it stores anything, so off means off. The excluded-IP and excluded-path lists were dead in the same way and now work too.
- The free edition collected visitor data with no way to see it and no way to stop it: the analytics screens are not part of that package, but the counting script and the receiving endpoint were. Neither runs now unless the analytics module is installed.
- Any other website could post fake visits to the receiving endpoint from a visitor's browser and skew the reports. Requests that identify themselves as coming from somewhere else are now refused.
- Every comparison figure was biased upward. "7 days" actually measured eight calendar days and compared them against a seven-day span, so the up-and-down badges on the cards flattered the current period on every range. Both windows are now the same length.
- The same page was counted several times over: an address with "?page=2" or a campaign tag on the end became its own row in the most-viewed list. Addresses are now reduced to the page itself, for existing history as well as new visits, and web-encoded characters in Turkish addresses are decoded so they read normally and match the right article.
- Daily totals were being lost for good. The receiving endpoint and the housekeeping task both rotate the daily privacy key, and whichever got there first made the other skip that day's summary — one site had summaries for only 42 of its 83 days. Summarising no longer depends on the key, and missing days are recomputed from the raw records that are still within the retention window.
- Analytics silently collected nothing on installations where the first database file the endpoint found was not the one in use — it gave up instead of trying the next one. It now uses the first connection that actually works.
- The bounce rate loaded every visit session of the selected period into memory to count them; on ninety days of a busy site that is tens of thousands of rows for a single percentage. The database does the counting now.
- A malformed address in the browser bar ("?range[]=x") crashed the analytics screen with a server error.
- Saving the analytics settings and then refreshing the page submitted the form again.
Advanced SEO panel: tools that had quietly disappeared are back
Improved
- Long tool tables no longer scroll inside their own frame. The panel measures the tool it is showing and grows to fit, so the slug repair and content SEO lists — hundreds of rows — scroll with the page instead of trapping a second scrollbar inside it.
Fixed
- The heading hierarchy screen could not be opened from anywhere in the panel. It lists every published article whose headings start at the wrong level and fixes them in one click — on a test site it had findings for two hundred articles — but when the SEO tools were gathered into a single panel, this one screen was left off the menu, and the panel hides each tool's own tabs. It is now a module of its own, under Content.
- On installations where the Advanced SEO plugin is switched off, eight tools became unreachable: the SEO overview, heading fixer, content optimiser, internal linking, featured images, slug repair, orphan content and the year updater. They were removed from the main menu when the panel took over as their single entry point, so switching the panel off left the files installed and invisible. Five sites were in exactly that state. The menu now falls back to an "SEO Tools" entry whenever the panel is unavailable.
- The panel listed every tool it knows about, whether or not that screen exists in the installation at hand. A missing screen produced an empty white frame with no explanation, because a page that is not found says nothing inside a frame. The panel now lists only the tools it can actually open.
- Fixes to the panel screen itself never reached existing sites: the update tool carried the plugin's code but not the page that draws it. It is now on the list.
Critical: the installer failed on its final step
Fixed
- New installations failed at the last step of the wizard. The installer carries its own copy of a small helper for reading PHP size limits, and the core gained a function with the same name on 7 August — so the moment the wizard loaded the core to finish setting up, PHP refused the duplicate and the install stopped with a server error. The installer's copy now has its own name, which also keeps its behaviour independent of the core's version. Anyone who downloaded the package between 7 and 18 August should download it again.
- The end-to-end install test that would have caught this now runs against the packaged installer, and its error detection no longer trips over the words "server error" appearing inside a script comment — a false alarm that masked whether the page was actually broken.
Article pages stop being dead ends, and the ad-readiness panel now sees template repetition
Added
- Shared sidebar modules — categories, topics and recent posts — that any theme can use without carrying its own copy. A theme that ships its own version keeps it; the shared one only fills the gap.
- Three new checks in the ad-readiness panel, covering what it could not see before: how much of the site shares one title pattern or one section skeleton, how many posts run without a single image in the body, and whether a large batch of posts was published on one day. These are the traits that make a site read as machine-produced regardless of how well each article is written.
Fixed
- One theme had its tag list switched off in code. The line dated back to when tag pages returned “gone”, and it was never revisited after those pages started serving again — so a site whose every post carried tags published not a single tag link. The list is back.
- Three themes never printed tags at all, although most of their posts were tagged. An article that ends without a single onward link is a dead end for the reader and for a crawler alike.
- The personal theme shipped its category, tag and recent-post modules switched off, so the sidebar of an article carried three links in total. The same article rendered by the theme that did get ad approval carries thirty-nine. The modules are on by default now.
- The travel theme's article rail held only a table of contents, share buttons and a back-to-top button; the theme's own richer sidebar was never included on article pages. Category, tag and recent-post navigation now sits in the rail.
Image dimensions everywhere, and archives now list their posts in structured data
Added
- Category, tag and author archives now publish the list of posts they show as structured data. The page already declared itself a collection, but never said what was in it; the list is built from the same query the theme uses, so it cannot drift from what a visitor sees.
Fixed
- Resized image variants never received width and height. The lookup stripped the size suffix from the filename but removed the file extension along with it, so the name it searched for could never match a stored one — a comparison that could not succeed by construction. Every related-post card and listing thumbnail was therefore published without dimensions, and those are the most numerous images on a page: each one shifted the layout while it loaded. Sizes now come from the file itself, so the variant reports its own true dimensions.
- Author avatars and site logos were skipped entirely. They are not stored in the media library, so no size was ever known for them, and an avatar can appear half a dozen times on a single article. They are measured now — layout treatment for them stays unchanged, only the dimensions are added.
- The featured image went into the structured data without dimensions on sites whose images predate the media library, even though the in-content images had them. That is the one image search engines look at first.
- The single post page now declares its author and section to social networks as well. Publication and modification times were already sent; the author was only in the structured data, so shared links carried no author attribution.
API settings: quotas now apply to content generation, and usage statistics finally count it
Added
- The API tab now opens with the automation entry points it is named after: a link to the REST API keys used by n8n, Zapier or your own script, and one to the ready-made n8n workflows. Both had moved to other screens with no way back from here.
- Each AI setting now states what it governs — which calls a quota covers, that the token limit applies to analysis rather than article length, and what the cache window actually caches.
Fixed
- The daily and per-account AI quotas were only applied to SEO analysis. Article generation — the path that actually spends most of the tokens — ignored them completely, so a site set to 200 calls a day could make thousands, and on a paid provider that lands straight on the owner's bill. Both quotas now cover every AI call, and the screen shows how much is left.
- The usage statistics counted the same narrow path, so most sites saw zeros no matter how much they generated. Every generation call is now recorded with its provider, model, token count and duration.
- The temperature slider did not reach article generation either: that code carried a fixed value and the setting only affected analysis. The configured value now applies everywhere it is accepted.
- The API key test endpoints now require an administrator account, matching the screen that calls them.
- The model field accepted an empty value and stored it, which left every later request pointing at no model at all — generation failed with nothing on screen to explain why. Empty and malformed values now fall back to the saved model.
- The default provider field accepted any text. An unrecognised value made the site report "no AI key connected" while the key sat there saved.
- Choosing a provider hid the other providers' key fields, and they could not be reached again without reloading — even though keys are stored per provider and several can be filled in. Nothing is hidden now; the default provider is marked instead.
- With a provider other than Gemini selected, the panel claimed the integration was off and asked for a Gemini key although generation was working. The status now follows the provider actually in use.
User management: lockout protection, account status and a single password rule
Added
- Accounts can now be deactivated instead of deleted. The account status was stored and enforced everywhere — an inactive account cannot sign in and is hidden from author pages — but there was no way to set it from the panel, so the only way to stop someone from signing in was to delete their account along with everything attached to it.
- Locked accounts can be released from the user's edit screen. After five failed sign-in attempts an account locks for fifteen minutes, and the counter only cleared on a successful sign-in — so someone who could not remember their password stayed locked out with no way for an administrator to help. The current lock state and the failed-attempt counter are now shown, with a control to clear both.
- The user list now marks inactive, banned and locked accounts, so "why can't I sign in?" has a visible answer.
Fixed
- The last administrator could lock themselves out of their own site. Changing your own role to subscriber, deactivating your own account or deleting the only administrator was accepted without a word — and afterwards nobody could reach user management again, with no way back except editing the database by hand. All three paths are now refused while no other active administrator remains.
- The role field accepted any value that was posted. A value outside the four known roles silently emptied the role — leaving an account that could sign in but had no permissions at all — and on databases in strict mode it broke the save outright. Role and status are now checked against their allowed values.
- Usernames were stored exactly as typed, including spaces and slashes, even though the username is also the author page address. A username can no longer be set to an e-mail address either: the sign-in screen accepts both a username and an e-mail, so the two would collide.
- Changing a username left the old author page as a dead address; it now redirects to the new one, the same way category addresses already did.
- The user screen enforced no password rule at all — "123" was accepted. Both the user screen and My Profile now apply one shared rule: at least eight characters with a letter and a digit, and obvious passwords are refused.
- Changing a password now also ends that account's "remember me" session on both screens, so older browser cookies stop working immediately.
- With a role filter active, the "All" tab showed the filtered number rather than the total, and paging through search results silently dropped the search.
- Deleting a user left their avatar file behind on disk.
Spam Protection screen rebuilt, and its settings now save reliably
Fixed
- The Spam Protection screen was built with a layout system the admin panel does not use, so none of its structure applied: the four summary figures stacked into four full-width bands down the page, the settings sat in a single narrow column, and the icons never appeared. The screen is rebuilt with the panel's own components and now reads as one page: summary cards across the top, settings in the main column, quick actions and blocked addresses alongside.
- A status line at the top now states plainly whether protection is on. Every threshold on the page is meaningless while the master switch is off, and nothing on the old screen said so.
- Turning protection off was never saved: the screen decided the switch's state from the presence of the field rather than its value, so the setting stayed on no matter what was chosen.
- Turning the master switch off also erased the thresholds underneath it — link limit, submit time, flood caps all fell back to factory numbers, because disabled fields are not submitted by the browser and the screen treated a missing field as a request to reset. A missing field now keeps the saved value.
- Out-of-range values were stored as typed; they are now kept within the limits the screen advertises.
- The minimum submit time was an admin setting the guard did not read: the screen could say five seconds while the server decided at three. The configured value is now the one that applies.
- Spam catches were being written to a table that some installs never had. The repair routine existed but was never called from anywhere, so on those sites every caught bot vanished without trace and the screen reported nothing. The table is now created on demand and the write is retried.
- Several English labels on this screen showed placeholder text generated from their internal names; they have been written properly. Two Turkish descriptions described the wrong thing.
Spam protection: one shared surface for every public form
Added
- Public forms now share a single anti-spam surface. Comments, the contact form, the newsletter box and the form builder each had their own hand-built protection, and they had drifted apart. One component now renders the hidden protection fields and one function runs the shared checks, so a new form is protected by construction rather than by remembering to repeat the work.
Improved
- Bot catches are now recorded. Honeypot hits, instant submissions and flood blocks were silently discarded on the comment channel, so there was no way to tell working protection from absent protection; they are logged now.
Fixed
- The timing check that catches instant bot submissions was inactive on five themes and the newsletter box, because the field it reads was never rendered there; one theme's comment form had no honeypot at all. Every public form now carries all three protection fields.
- The newsletter box never sent its hidden fields at all: the script assembled its own payload from just the e-mail address, so the honeypot on that form could never trip. The whole form is submitted now.
- Messages flagged as spam by the contact form were stored with an invalid status, because the column had never been extended with a spam value. They appeared in no folder — including the ones caught by mistake, which is exactly what the spam folder exists to prevent. The column is repaired automatically and previously mis-stored messages are recovered.
- One theme's comment form posted to an address that does not exist, so signed-in readers' comments went nowhere.
- Comment length limits counted bytes rather than characters, so Turkish text was measured incorrectly — a long comment could be refused while a single-letter name passed. Both channels now measure the same way.
- Names and subjects accepted line breaks, which single-line fields should never carry; the value is now cleaned on the way in.
Tags no longer lead nowhere, and images declare their size
Fixed
- Tag links led to a bare “410 Gone” screen. Themes show tags in several places — under the article, in the sidebar cloud, on archive and search pages — but tag pages were only served when tag archives were switched on, which they are not by default. Every tagged article therefore carried several dead internal links, and a reader who clicked one landed on an unstyled error page. Tag pages are now always served with the site's own design; the setting decides only whether search engines may index them. With it off they are shown to readers but marked noindex and left out of the sitemap, exactly as before.
- Images inside articles were rendered without their dimensions, so the page reflowed as they loaded — the layout shift that Core Web Vitals measures. Both the article's main image and images inside the text now declare their size, taken from the media library, across every theme. In-text images also load lazily while the leading image stays eager, which is what browsers need for the largest element to appear quickly.
Legal pages: updated details now apply, duplicate date and mangled e-mail fixed
Fixed
- Correcting your contact e-mail, address or business name and generating the legal pages again left the pages unchanged, still showing the details from installation. The generator kept any page that was long enough, to avoid overwriting text you had written yourself — but that also protected the untouched pages that shipped with the install. The generator now recognises a page you have never edited and refreshes it with your new details, while a page you edited by hand is still kept, and now says so and points to the overwrite option.
- Legal pages showed the last-updated line twice, with two different dates: the generator wrote one into the page text while the theme printed its own. The line now comes from the theme only, and pages that were never edited have the leftover line removed automatically when the Pages screen is opened and during maintenance.
- The last-updated date always showed today, on every theme, even for a page that had not changed in months — a misleading claim on a legal page. It now reflects when the page was actually last saved.
- Turkish spelling correction in the generated text ran across the whole page, including e-mail addresses and links, so an address such as iletisim@example.com could be rewritten into an invalid one. Addresses and links are now left untouched while the surrounding text is still corrected.
Media: half-rendered screen on an empty library, and file types
Fixed
- The media library stopped rendering half-way down the page whenever the library was empty — which is exactly the state of a brand-new site. The file counters are produced with SQL sums, and a sum over zero rows is empty rather than zero; feeding that empty value into the counter text raised an error that ended the response early, so the page arrived without its grid, upload button or closing markup. The counters are now normalised to zero, and the translation layer no longer lets an empty value end a page.
- Every uploaded file was recorded as an image, whatever it was: PDFs, documents, spreadsheets, archives and text files all carried the image type in the library records. The type is now derived from the file itself, and existing records are corrected once during routine maintenance.
- The Video tab listed the entire library instead of videos, because that tab had no filter of its own. Video and audio now filter correctly, the Documents tab no longer mixes media files in, and the item count matches what the tab actually shows.
Built-in pages: stable dates instead of a false freshness signal
Fixed
- Pages served from a theme template rather than a stored record announced the current moment as their publish and modification date, so the structured data changed on every single request — two requests three seconds apart reported two different timestamps. Search engines were told the page had just been edited every time they fetched it. These pages now carry a stable date taken from the template that produces their text, so the date only moves when the text actually changes.
- The same pages were listed in the sitemap with today's date every day, the same "permanently fresh" signal the homepage and category listings were corrected for earlier. Their sitemap entry now uses the same stable date.
Pages: duplicate legal URLs, sitemap gaps and SEO visibility
Security
- The Pages hub now requires the page-editing capability. It previously checked only that someone was signed in, which gave accounts holding lesser roles more reach over published legal text than intended.
Improved
- The legal page status table now shows how each page actually appears to search engines: its canonical address, whether it is indexable, whether it is in the sitemap, and its meta description length — with a plain-language note when something needs attention.
Fixed
- Legal pages served from the theme template — the default state of a fresh site — answered on both their Turkish and English addresses with identical content, and each address declared itself canonical. Measured: /privacy and /gizlilik returned the same page byte for byte as two indexable URLs. Every alias now collapses onto one address per document, chosen by the site language, exactly as it already did once a page existed in the CMS.
- Those same pages were missing from the sitemap: live, indexable, but never submitted, because the sitemap only listed pages stored in the database. Privacy, terms, cookie policy, disclaimer, about and contact are now listed whenever they are served, and a page stored in the CMS replaces the built-in entry instead of being listed twice.
- Legal, about and contact pages served from a theme template carried the site-wide meta description — the same sentence as the homepage — because the route never handed the page's identity to the theme. Each now carries its own description; verified across all 14 themes.
- The legal page editor screen answered with a server error on every install: it queried a table that belongs to the jekcms.com marketing site and does not exist in the CMS. The address now redirects to the page it was meant to open.
- Generated legal pages calculated reading time with a counter that splits Turkish words, inflating the estimate by roughly 40%.
Menus: second menu could not be created, plus icon support
Added
- Menu items can carry an icon (emoji), set next to the title in the menu editor and shown in every theme's navigation.
- Menu items whose parent was removed used to vanish from the navigation; they are now shown at the top level instead of being silently dropped.
Security
- Menu links are now restricted to safe schemes: a `javascript:` or `data:` link saved into a menu is stored and rendered as an inert "#".
Fixed
- Creating a second menu failed with a server error. Menus carry a unique slug, but the create/update code never wrote one: the first new menu was stored with an empty slug and every menu after it collided with it. Menus now get a unique slug derived from their name, and existing rows with an empty slug are repaired automatically. Renaming a menu keeps its slug, so nothing that points at it breaks.
- The Tech theme ignored the menu module completely — its header always printed the first five categories, so nothing configured under Menus ever appeared. It now publishes the assigned menu and falls back to categories only when no menu exists.
- A menu assigned to the "Main" location was invisible on every theme, because themes read the "Header" location. "Main" is now treated as an alias of the header location, so existing menus start working without being touched, and the location list only offers what themes actually render.
- When two menus shared one location, which of them appeared was left to chance. The site now consistently shows the older one, and the Menus screen warns that the others stay hidden.
SERP site name: save defect fixed, end-to-end identity checks
Added
- SERP Identity Check now verifies the whole live chain Google reads for the site name — homepage reachability and indexability, the title, og:site_name, the WebSite schema name/url/alternateName, the canonical, the favicon, and whether the www variant consolidates onto one host — so a broken link in the chain shows up without waiting for a re-crawl.
- Settings → General now flags a site name that is empty, generic, or a literal copy of the domain right next to the field, since Google falls back to showing the domain in those cases, plus a direct link to the identity check.
Improved
- The identity check no longer reports internal state rows (plugin schema markers, heal flags, cached audit payloads) as autoload defects — they are excluded by design, so the check can now actually report a clean install and a real defect stands out.
Fixed
- A setting could fail to save entirely when its stored row lived under a different group label: the settings table keeps `key` globally unique, but the shared save helper looked the row up by group plus key, found nothing, and then tried to insert — hitting a duplicate-key error. The value silently never applied, which for the site name meant search results kept showing the domain. The save path now resolves by key (as the read path already did) and moves the row to the requested group.
- Breadcrumbs on Turkish sites announced the root as "Home" even though the site declared itself Turkish. Google shows breadcrumbs in search results, so the trail now uses the site's own language ("Ana Sayfa").
SEO audit: pagination signals and robots consistency
Improved
- rel=prev/next pagination links are now emitted centrally for every theme — including the four themes whose headers never passed pagination context.
- Page 2+ of the home/blog feed now carries the page number in its title instead of duplicating page 1's title.
Fixed
- Out-of-range pagination URLs (?page=N beyond the last page) returned an empty archive with HTTP 200 and a self-referencing canonical — an infinite, indexable space of thin duplicate pages. Every paginated list (home feeds, category/tag archives, author pages, all 14 themes) now returns a real 404.
- The personal theme stamped paginated archive pages with an extra "noindex, follow" robots tag next to the core's "index, follow" — conflicting directives, and search engines pick the restrictive one, silently dropping page 2+ from the index. Paginated archive pages are all indexable again with a single robots tag.
- A per-post robots value saved as plain "index, follow" wiped the core defaults' max-image-preview:large directive, costing those posts large-thumbnail eligibility in Google Discover. Indexable robots values without max-* directives now get the default set appended.
- URLs of non-paginated pages (a single post, a fixed homepage) with a stray ?page=999 served identical content that declared itself canonical — the canonical now keeps ?page only on genuinely paginated templates and consolidates everything else onto the clean URL.
AdSense readiness: aligned with current approval criteria
Added
- New audit check: the privacy policy is now scanned for Google's "Required content" disclosures — cookie use, the third-party (Google) advertising-cookie statement and the personalized-ads opt-out link. If you rewrote the generated legal pages and dropped these sections, the audit catches it.
- New audit group: ad-click encouragement phrases ("click the ads", "reklamlara tıklayın") are now scanned in titles, slugs and bodies — the clearest program-policy violation there is.
- New sidebar card: applicant requirements (18+ age rule, the 6-month site-ownership rule that applies in some countries, HTML source access).
Improved
- The consent-banner check now explains the certified-CMP rule accurately: since January 2024, serving ads to EEA/UK/Switzerland visitors requires a Google-certified CMP (IAB TCF) — the built-in banner covers the GDPR baseline but does not replace it; enabling Google's own consent message under AdSense → Privacy & messaging after approval satisfies the rule. The application-day checklist gained the same step.
- The policy-scan pass message now states its honest scope: Google's prohibited-content list is broader (hate speech, misleading health/election claims, deceptive practices) than what pattern scanning can detect.
Fixed
- Policy patterns containing the Turkish dotless "ı" (e.g. "şifre kırma", "sızma testi") were silently missed in ALL-CAPS titles because uppercase "I" lowercases to "i", not "ı". The scanner now folds both the text and the patterns to a shared canonical form, so case no longer hides a match.
Settings audit: SVG hardening in the branding preview
Security
- The generated-logo and favicon SVG fields are now sanitized before they are stored and before they are rendered in the branding preview. These are hidden form fields, so a tampered value could previously carry an event handler (e.g. onload) or script into the admin branding screen; the old check only rejected literal
Blog kur, yazını yayınla.
- Publish in minutes — no setup marathon
- Lifetime license, free updates
- Your content stays on your own server
Welcome Back
Sign in to your account
or continue with emailDon't have an account?
Create Account
Purchase a license to get started
or continue with emailAlready have an account?
Be the first to know
New features, release notes & CMS guides — a couple of emails a month, no spam.