Changelog
Release Notes
Every feature, every improvement, every fix since v1.0.0.
Honest Freshness Signals, a Content Quality Gate for Automation, and Full-Document Revision Restore
Added
- Editorial date model: posts now track "last meaningful content change" separately from internal system touches. Schema.org dateModified, article:modified_time and sitemap lastmod are generated from the new signal — so bulk SEO passes, counters and cache refreshes no longer make hundreds of posts look "updated today" to search engines. When editing a published post you can also override the automatic detection: mark a save as a content update or a technical fix.
- Content Quality Gate: every automated publish path — content queue approval and publish (single and bulk), scheduled publishing, REST API and n8n webhooks — runs the same deterministic quality checks before anything goes live: minimum content length, duplicate and near-duplicate titles, and broken local image references block publication with visible reasons; missing featured image, internal links or headings raise warnings. The gate re-runs at the moment of publishing (so post-approval edits are re-checked), and fails closed: if the check itself errors, nothing is published. Thresholds are configurable in Settings.
- Full-document revisions: each revision now stores a complete snapshot — SEO meta, categories, tags, featured image, author, status and dates — and restoring one brings back the content, SEO, taxonomy, featured image and author. Publication status and dates are deliberately not restored, so restoring never unpublishes a live post or rewrites its history. The state before a restore is saved as its own revision, and the revision limit is now configurable (default raised from 10 to 50).
- Author Person schema now includes verifiable sameAs links built from the author's social profiles and website, alongside the job title, bio and photo added in the previous release.
Improved
- The REST API now returns explicit ISO 8601 editorial dates (content_modified_at, reviewed_at) on post endpoints and accepts content_modified_at on writes, so migrations and rewrites can preserve original dates.
Fixed
- Schema dateModified and sitemap lastmod could report a date earlier than the publish date on scheduled posts; both are now clamped so a modification date never precedes publication.
- The sample admin account seeded by a manual database import shipped with a known example password; the seed now ships with an unusable password hash, and the installer sets real credentials as before.
Legal Pages Repaired and Expanded, Author Archives Fixed, Tag Indexing Made Consistent
Improved
- The default Cookie Policy was rewritten to be genuinely comprehensive in both languages: cookie categories with purposes, legal bases and durations in a table, first/third-party and session/persistent distinctions, named third parties with opt-out links, consent management and withdrawal, browser instructions, Do Not Track / Global Privacy Control, and a legal-basis section (KVKK on Turkish sites, GDPR/ePrivacy on English ones).
Fixed
- The built-in legal page templates shipped with corrupted text in all 13 themes — Turkish characters and arrow symbols rendered as garbage ("→", "Çerez") on fresh installs that had not saved their own legal pages. The templates were re-encoded and every character now renders correctly in both languages.
- Opening an author archive on the Personal theme returned a server error: a routing variable leaked into the template and shadowed the real author record. Author pages now render on every theme, and a non-existent author correctly returns 404.
- Tag archives could be indexed by search engines even while tag archives were disabled in SEO settings — the sitemap respected the setting but the page-level robots meta did not. With tag archives off (the default), every tag page is now noindex.
- On the Finance theme, the author box at the end of a post showed the author's name as plain text; it now links to the author's archive page, and the Pets theme's archive pages now emit a proper page title and meta description instead of just the site name.
Personal Theme: Full-Width Brand Logo with Automatic Light/Dark Switching
Added
- The Personal theme now supports a full-width brand logo in the header: upload your logo (and an optional dark variant) under Settings → Branding and it replaces the icon + site-name pair, switching automatically with the visitor's light/dark preference. The site name stays in the markup as a visually-hidden heading, so the Google site-name signal is preserved. Nothing changes for sites without an uploaded logo.
Stories, the Instagram Way: One "Latest Posts" Bubble That Plays Your Recent Content
Improved
- Automatic post stories were redesigned around how Instagram actually works: instead of one bubble per post crowding the strip, there is now a SINGLE "Latest Posts" bubble — tap it and the posts from your chosen window (3, 7, 15, 30 days… up to 90) play as slides, newest first, each with its featured image, title and a "Read Post" button. The bubble is fully virtual: nothing is written to the stories database, new posts appear in it the moment they are published, old ones drop off as they leave the window, and the ring lights up again whenever a new post arrives.
- The bubble's name follows the site language ("Son İçerikler" / "Latest Posts") and can be customized in settings. Bubbles you created by hand are untouched and keep their place next to it; the per-post bubbles generated by the previous version are cleaned up automatically.
Fixed
- Opening the Stories admin page by its direct URL (without a module parameter) returned a server error — a strict-mode array access crashed before the page could render. The page now opens correctly from anywhere.
Stories Strip Becomes a True Latest-Posts Showcase
Improved
- With auto-stories enabled, the strip now carries EVERY post published within the story lifetime window (7 days by default) — not just posts published after the feature was switched on. Older posts are backfilled automatically every hour, each story retires based on its post's publish date, and the newest post always sits first in the strip, Instagram-style.
- The strip now announces itself: when auto-stories are on and no custom heading is set, a heading in the site's language appears above the circles — "Son İçerikler" on Turkish sites, "Latest Posts" on English ones. Set your own heading to override it, or enter "-" to hide it entirely.
Image Captions Done Right: Visible Captions Are Now a First-Class Editor Feature
Added
- New "Caption" field in the image details dialog: add a visible caption under any image, shown identically on every theme via self-contained styling. The dialog now clearly separates the two concepts — alt text is invisible and for search engines and screen readers; the caption is the text readers actually see. Captions render live in the editor and are editable with one click.
Fixed
- Editing a post that contained figure-wrapped images could leak the old caption markup as a visible plain paragraph under the image — the editor did not understand the figure/figcaption structure, so saving unwrapped it and turned caption text into body text. The editor now parses figures natively: real captions survive editing round-trips intact, and legacy captions that merely duplicated the alt text are dropped automatically instead of becoming visible.
- Opening the image details dialog could scroll the page behind it, so you lost sight of which image you were editing. The background now stays exactly where it was while the dialog is open and after saving.
Click, Resize, Align: Full Image Editing Inside the Editor
Added
- Images in the post editor are now fully editable in place, the way WordPress users expect. Click an image and a floating toolbar appears right on it: size presets (Small 300px / Medium 600px / Full width), left-center-right alignment, a details button and remove — plus four corner handles you can drag to resize freely, with a live pixel readout while you drag. Aspect ratio is always preserved.
- New image details dialog (toolbar pencil or double-click the image): see and edit the alt text, title tooltip, exact pixel width and the image URL in one place, with a live preview. Alt text finally gets a proper editing home after insertion — good for accessibility and image SEO.
- Sizing and alignment are written into the content as self-contained inline styles, so they render identically on every theme — no theme CSS support required, and images never overflow on mobile (max-width is built in).
Fixed
- The alt text label in the image insert dialog was hardcoded in Turkish and appeared untranslated on English admin panels.
Posts List: One-Click SEO Score Refresh, Editor and List Finally Agree
Added
- New "Recalculate SEO Scores" button on the posts list: refreshes every post's stored SEO score with the current scoring engine — in batches of 100 with live progress, so a 1,000-post site takes seconds instead of hitting a timeout. Useful after upgrading, since scores saved by older versions used the old scoring rules.
Fixed
- The score in the editor and the score in the posts list could differ: the editor's live analyzer inspects the actual page structure (headings, tables, snippet blocks) while the save-time engine cannot, so recomputing on save produced a different number. The editor now passes its own score along when you save — the list shows exactly what the editor dial showed.
- The "Analyze All" AI button appeared on every installation, including ones with no AI provider configured, where clicking it could only show a setup notice. The button now appears only when AI is actually configured.
SEO Score You Can Trust: Fixed Budgets, No More Reward for Leaving Fields Empty
Improved
- Each check group in the SEO widget now shows its point contribution (e.g. "20/25p" next to Keyword) so you can see exactly where a score comes from and which section is worth fixing first.
Fixed
- A post with NO focus keyword could score 80-90, and the score DROPPED the moment you entered one — the old ratio model removed the keyword checks from the denominator when the field was empty, so withholding information was mathematically rewarded. Scoring now uses fixed category budgets (keyword 25, content 20, structure 15, basics 15, readability 10, visuals 10, schema 5): an empty keyword field burns its whole 25-point budget, and filling in information can only raise your score, never lower it. The same flaw existed in the score saved on every post update (an even stronger version: keyword-less posts were graded out of 50 and could reach 100) — post saves now use the same fixed-budget engine as the SEO Optimizer page, so all scores finally speak the same language.
- Turkish keywords containing İ/I (e.g. "İçerik Pazarlaması") silently failed every match — title, content and density checks all reported "keyword not found" because of a Unicode case-folding quirk. Keyword matching is now Turkish-aware across the editor widget, the save-time score and the SEO Optimizer. Density also counts whole words only (a short keyword inside longer words no longer inflates the percentage) and word counting is UTF-8 correct.
- The title length check said "good" up to 70 characters while the SERP preview's pixel meter showed the same title being cut at ~580px — the two now agree (60-character budget), and a keyword missing from the title is no longer punished twice.
SEO Assistant: Content Structure Checks, Pixel-Accurate SERP Preview, Wider AI Analysis
Added
- New "Content Structure" check group in the editor's SEO assistant — seven checks that mirror how editors actually review a draft: duplicate H1 in the body (your title is already the page H1), skipped heading levels (H2→H4), a too-thin intro before the first heading, a missing conclusion/summary section on long posts, table and list usage, and a featured-snippet readiness check that looks for a question heading followed by a concise 40–60 word answer.
- The SERP preview now measures your title and description in pixels, the way Google actually truncates them (~580px for titles, ~990px for descriptions on desktop). Character counts stay, pixel widths appear next to them and turn red when the limit is exceeded — no more titles that pass the character check but still get cut in results.
- AI deep analysis covers four new dimensions: overall content quality (informativeness, originality, freshness), Google Helpful Content fit, AI-search readiness (would an AI Overview cite this page?), and AdSense policy suitability — including thin-content and clickbait-mismatch warnings before you publish.
Fixed
- The SERP preview showed a broken icon instead of your favicon: it pointed at a file path that only exists on jekcms.com, not on customer installations. The preview now resolves the site's real favicon through the same priority chain the front end uses (uploaded favicon, site-root favicon files, generated icon), with a letter-badge fallback so the slot is never empty.
Google Console: PageSpeed Tab, Fresh Search Data, Stability Fixes
Added
- New PageSpeed tab: measure any page of your site with Google PageSpeed Insights (Lighthouse) right from the panel — mobile and desktop scores for Performance, Accessibility, Best Practices and SEO, lab metrics (FCP, LCP, TBT, CLS, Speed Index) and real-user Core Web Vitals (CrUX) when Google has field data for your site. Works without a Google connection; results are cached for 24 hours. An optional API key setting raises the measurement quota.
Fixed
- Search Console reports were consistently thinner than the GSC interface: the API omits the last ~2 days by default ("final" data), so recent queries and clicks simply never appeared — the exact "my search terms don't show up" complaint. All Search Console reports now request fresh data, matching what the GSC UI shows.
- The Top Queries and Top Pages cards swallowed API errors and displayed a misleading "No data" — a quota or permission problem now shows its actual, actionable message on the card itself (same for the Analytics tables).
- When Google was unreachable, every page load fired the full set of live API calls with 20-second timeouts each, freezing the panel; failed responses are now briefly cached so the page stays responsive, and the Refresh button retries immediately. The response cache table also cleans up its expired rows, which previously accumulated forever.
ZeroTrack Analytics: Data Collection Restored on Production Sites
Fixed
- ZeroTrack silently stopped recording visits on production installations: the standalone beacon endpoint read database credentials only from .env, but production installs keep the real credentials in .env-production (the installer writes them there). The endpoint could never connect, answered every beacon with a polite 204, and the dashboard showed zeros while the site had traffic. The endpoint now uses the same environment-file priority as the rest of the CMS (.env-production first), and a failed database connection is written to the error log instead of disappearing without a trace.
- Page views could be counted twice: both the plugin hook and the core footer injected the tracker script, and the plugin side ignored the once-per-page guard. The guard is now honored on both paths — one tracker, one beacon, one count per view.
SEO Analyzer: Turkish-Correct Matching, Keyword Cannibalization Warning, New Checks
Added
- Keyword cannibalization warning: as you type a focus keyword, the analyzer checks whether another post already targets it and names that post — the classic premium-plugin feature, built in.
- Three new checks: a warning when the meta description merely copies the title, a nudge when no image alt text contains the focus keyword, and a heads-up for slugs containing Turkish/special characters.
Fixed
- Turkish focus keywords were silently failing: JavaScript lowercases dotted İ into a combining character, so a title like "İçerik Rehberi" never matched the focus keyword "içerik" — the analyzer wrongly reported the keyword missing from the title, description, headings, and first paragraph. A Turkish-aware folder now backs every comparison, and the slug check ascii-folds the keyword ("beslenme önerileri" correctly matches "beslenme-onerileri").
- Keyword density counted substrings ("spor" also counted "sporcu"); it now counts whole words. Internal/external link detection resolves the real hostname instead of matching the site name anywhere in the URL. The analyzer also stopped re-rendering every 2.5 seconds, which used to force categories you had collapsed back open.
- On installations without the AI settings table, the editor died mid-page with "Server Error" while rendering the AI tab; the check is now failure-safe and the editor always loads.
- The social preview card showed a broken image for uploads-relative featured paths; description length limits were aligned to 160 everywhere.
Health Theme Speaks Your Site Language on the Frontend
Fixed
- On Turkish sites the Health theme still printed dozens of hardcoded English strings — section titles (Most Popular, Trending Topics, Latest Articles, Recommended), the entire footer navigation (About, Categories, For You, Editorial, Connect and every link inside them), the author card (About Author, View All Articles), the comment form (Leave a comment, Name, Email, Post comment), search, 404, tags, and the fallback header menu (Home, About). All of them now follow the site language setting: Turkish sites read fully Turkish, English sites are unchanged.
Health and Travel Headers No Longer Leak Broken Markup
Fixed
- On the Health and Travel homepages the brand link's H1 was printed inside the aria-label attribute, breaking the attribute and leaking a literal « — home"> » text next to the logo (most visible on fresh installs without a logo). The H1 now renders inside the link body where it belongs; the accessibility label and the SEO site-name signal both work as intended.
Wizard Polish: Come Back Days Later, Nothing Is Lost
Improved
- Take the prompt, close the browser, come back next week with the AI's JSON: the wizard now remembers every choice, greets you with a "Jump to import" shortcut, and the step chips are clickable so you can move to any step directly — no more starting over.
- The Content Studio menu is now one flat list in a clear order (Overview, Content Wizard, AI Content, Automation, Content Queue) — the confusing "Advanced" sub-group is gone — and it stays visible inside the Content Queue and Automation pages too, so sub-pages no longer feel like leaving the studio.
- The Pinterest and external-link option cards were realigned (checkbox beside the title instead of floating above it) and light up when selected.
Fixed
- The sample JSON no longer carries a fixed example date in scheduled_at — some AIs copied that stale date into every article. Scheduling belongs to the wizard's own final step.
- The old JSON generator form inside the import tab was removed (the wizard replaced it); the tab now cleanly hosts the raw import tools (JSON file, Google Sheets, CSV) with a pointer to the wizard.
Content Wizard: Plan, Create, and Schedule in One Guided Flow
Added
- The new Content Wizard (Content Studio → Content Wizard) replaces the old maze of JSON wizard, batch planner, and import tab with one step-by-step experience: how many articles → topic and keywords → richness (word count, images, Pinterest, authority links) → who creates it → schedule. Your theme profile is auto-detected, so recipe, travel, and finance themes automatically request their special fields.
- Two creation paths, same quality contract: use your own ChatGPT/Claude/Gemini account for free (copy one prompt, drop the returned JSON back — the wizard imports and validates it), or let jekcms generate everything through your API key, article by article with a live progress bar. Both land in the same review queue.
- The final step schedules the whole batch on a rhythm (daily, every 2-3 days, weekly) with a randomized time window, and explains the image workflow plainly: every article ships with a ready image plan (per-image generation prompts); generate covers automatically via the AI Images plugin, or create them anywhere, name them by slug, upload to uploads/temp and press Match Images.
Improved
- Content Studio's inner menu was decluttered (Posts and New Post moved back to the main sidebar where they belong) and it now stays visible on every studio sub-page, so you never lose your bearings. The n8n automation planner and raw queue live under a clearly labeled "Advanced" section.
- The single-draft AI tool now shares one AI client with the wizard (Gemini, Groq, and OpenAI — OpenAI upgraded to gpt-4o-mini).
The Finance Footer Shows Your Logo Instead of Plain Text
Fixed
- The Finance theme footer always printed the site name as plain text and never used the logo you uploaded. It now shows the logo, preferring the dark-mode variant because the footer background is dark in both themes. Sites without a logo keep the text heading exactly as before.
A Newly Uploaded Logo Now Appears Immediately
Fixed
- Replacing your logo from Settings → Branding could leave visitors looking at the old one for a long time. Uploads are served with a one-year "immutable" cache header, so once a browser or CDN had the file at that address it never asked again — and a CDN could keep serving a stale copy even after the file on the server changed. Logo URLs now carry the file's modification time, so a new upload is a new address and every visitor sees it on the next page load.
Author Pages Get Photos and an Archive Layout Fix
Improved
- Author archive pages now show the author's photo next to their name in both Finance and Pets — the header no longer reads as an anonymous text block.
Fixed
- Finance archive pages (category, tag, author) stacked the sidebar full-width below the article cards because the layout container had no grid rules; the sidebar is back in its right-hand column. The archive breadcrumb also lost its detached white band, matching single posts.
- Author archive pages claimed every author was a "Financial Analyst" when no credential was set; the fabricated fallback was removed and only real credentials render.
- On the Pets homepage, when the newest post was the only one published, the grid below the featured card rendered as a large blank area; a short "more articles on the way" note now fills it.
Finance Theme: Sans Headings, Breadcrumb Fix, Dark-Mode Readability
Improved
- The default heading font switched from the serif Fraunces to Inter: every heading across the theme now shares one modern sans family. Sites that picked a custom heading font in the Customizer keep their choice.
Fixed
- On single posts the breadcrumb sat in a detached band that ended up unreadable behind the colored post header; it now lives inside the header as light, legible text.
- In dark mode, links inside articles and the table of contents used the light-mode teal and nearly disappeared against the dark background; dark mode now switches them to a bright, readable tone without touching buttons or the hero.
Finance Theme: Sticky Table of Contents, Author Bio, Tidier Cards
Improved
- The "In This Article" table of contents no longer pushes the article down from the top of the content: it moved into the right sidebar, where it stays visible (sticky) while the reader scrolls through long articles.
- Article cards were tidied up: date and reading time sit on one muted line separated from the content, and the author appears as an aligned chip with a round photo instead of a loose letter placeholder. The homepage now also loads author photos for its cards.
- More breathing room between the homepage hero and the "Latest Articles" section.
Fixed
- The author box under articles rendered without the author's biography because the router does not pass it; the template now loads the bio itself, so the full author card (photo, name, bio) appears.
Finance Theme: Design Consistency Pass and Author Byline Fix
Fixed
- Every Finance article showed "Staff Writer" as the byline and skipped the author box entirely, even when the post had a real author. The template expected author data in a nested array while the router provides flat fields; the template now reads both, so the correct name, avatar and author box render on every post.
- The Finance theme received a design consistency pass: the serif display font is now reserved for article headlines while all interface labels use the sans family, the color palette was unified around the theme's navy and gold (the off-brand purple button and blue underlines are gone), the newsletter box no longer blends into the hero, the unused gray band between header and hero was removed, the trending numbers and footer fine print are readable, the author avatar aligns with its name, and archive pages say "1 Article" instead of "1.00 Articles".
- Hardcoded newsletter and footer texts that promised "market analysis and investment tips" were replaced with neutral wording that fits any finance site built on the theme.
Logo Variants: Dark-Mode and Retina Logos, Uploaded from the Panel
Added
- Settings → Branding now accepts three optional logo variants alongside your main logo: a dark-mode logo and 2x (retina) versions of both. When the visitor switches to dark mode the logo swaps instantly — no page reload — and high-density screens automatically receive the sharper file. If you never upload a dark logo, nothing changes: the light logo is used everywhere, exactly as before.
- Themes with permanently dark areas (like the Pets footer) automatically prefer the dark-mode logo there when one is uploaded, so a dark-text logo no longer disappears into a dark background.
Fixed
- The Finance homepage never listed articles on any installation: the home route loaded the template without passing it data, so the "Latest Articles" section always claimed the site was empty. The template now queries published posts itself, with pagination.
- A sweep of rough edges reported on fresh installs: the tagline no longer duplicates next to the logo in the Finance header, raw emoji icons were removed from category chips and lists in both Finance and Pets, a literal "NULL" tag and a "0.00 views" line no longer render in the Finance sidebar, empty tag boxes hide themselves, the featured-post category badge no longer overlaps the title in Pets, and legal pages regained a readable header in all themes.
Theme Honesty: Placeholder Stats Removed, Fresh-Install Language Fixed
Fixed
- The Finance theme homepage shipped with hard-coded placeholder claims — invented reader counts, satisfaction percentages and a fake "expert analysts" figure. All of it is gone: the hero now speaks with your site name and tagline, and the stats strip only appears once it has real numbers from your own database to show.
- Fresh installs now seed the site language from the setup wizard. Previously the language row was never written, so every new site quietly fell back to Turkish in the footer and legal pages — even when everything else was in English.
- Finance and Pets headers printed the logo and the site name side by side, doubling the brand. With a logo set, the text is now kept for screen readers only; without a logo, the text brand still shows.
- The Pets homepage listed every category — including empty ones and the seeded "Uncategorized" — each with a "0" badge. Category lists now show only categories that actually have published posts, without count badges.
Zero-Setup Scheduling: Posts Publish On Time Without a Server Cron
Added
- Scheduled posts and the content queue no longer depend on a server cron job. A built-in scheduler keeps a "next job due" timestamp and, when that moment arrives, runs the publishing engine right after a page response has been delivered to the visitor — so a post scheduled for 14:37 goes live on the first visit at or after 14:37, and the visitor never waits for it. On hosts that cannot detach the response, the work is handed to a lightweight background request instead.
- A real cron job is still first-class: when one is configured it takes over completely and the visitor-triggered scheduler switches itself off, adding zero overhead. It can also be disabled explicitly with the JEK_DISABLE_PSEUDO_CRON constant.
Improved
- The old fallback rolled a dice on every request (a 1% chance), which meant late posts on quiet sites and wasted database work on busy ones. The new scheduler is deterministic: on a normal request it reads one or two tiny files and does nothing else — no database queries, no guesswork.
First-Publish Journey: Redesigned Welcome Guide
Improved
- The dashboard welcome guide was rebuilt as a slim one-line journey rail: a circular progress ring, five connected step dots and a single call-to-action for whatever comes next. It takes a fraction of the space of the old checklist and reads at a glance.
- The five steps now follow the real order of setting up a site: site identity (name and tagline), logo, first category, first published post, and securing your admin password. Every step updates live as you complete it anywhere in the admin, and each links straight to the right screen.
- "Pick a theme" and "connect an AI provider" are no longer setup steps — keeping the theme you chose during installation is a perfectly good choice, and AI is optional.
Featured Image Path Fix in Theme Templates
Fixed
- A handful of theme templates (Recipes cards and pages, Starter posts, Pets error page) printed the featured image path exactly as stored in the database. Relative paths then resolved against the site root and returned 404, so those images never showed. All of these now resolve through the central image helper, which builds the correct uploads URL and serves the best available format.
Logo Aspect Ratio & Accessibility Fixes
Fixed
- Site logos in the Health and Travel themes now declare their real pixel dimensions instead of fixed placeholder values, so uploaded logos of any shape render at the correct aspect ratio without distortion or layout-shift warnings.
Setup Wizard 2.0: WordPress Migration at Scale & Smart Recovery
Added
- Resumable WordPress migration: progress is saved on the server after every batch — if your browser closes or the connection drops mid-migration, reopening the wizard offers to continue exactly where it left off.
- Same-server fast path: when WordPress lives on the same hosting account, images are copied directly from disk instead of downloaded over HTTP — large media libraries migrate in a fraction of the time.
- Smarter server pre-check: disk space, memory limit, upload size and next-gen image support are now verified up front, with plain-language guidance for anything that needs attention — required items block, optional ones just warn.
- Full WordPress fidelity: pending, private and scheduled posts keep their status, comment reply threads are preserved, comment author links are carried over, and your site logo is localized automatically.
Improved
- Wizard actions are protected with a per-session token, and the legacy parameter that allowed re-running installation on an already-installed site has been removed.
Fixed
- In-place migrations (same domain) now migrate images correctly: previously same-domain image URLs were skipped as "already local", and removing the old WordPress files afterwards broke every image in your content.
- Large sites no longer risk server timeouts: imports run in time-budgeted batches with keyset pagination, and comments are imported in batches too — sites with tens of thousands of posts and comments migrate reliably on shared hosting.
- Tag and category names containing commas are no longer split into separate terms, and long tag lists are no longer truncated.
- Your existing .htaccess is backed up before installation replaces it, featured images resolve from WordPress metadata instead of unreliable legacy URLs, and stale responsive image attributes pointing at the old site are cleaned up.
- The setup wizard now speaks your language end to end — every server-side message is available in English and Turkish, and unrecoverable server errors return a readable explanation instead of a blank response.
Managed-Install Indicator Hardening
Fixed
- Centrally-managed installations without the license enforcement stack no longer show a dead-end "Update Available" banner and sidebar badge — the managed-install marker is now honored everywhere the update UI is rendered.
Commerce Core: Updates, License Portability, Plan Upgrades & Support
Added
- License portability from the customer panel: see every site bound to your license, remove one to free the slot, add a new domain, and activate there — moving a license between sites takes a minute and needs no support ticket.
- Theme and plugin updates now flow through the same signed channel as core: RSA-signed manifest covers every package, one-click theme/plugin updates work in the admin panel, and a publish pipeline ships them (package → verified upload → catalog).
- Plan upgrades from the customer panel: pay only the difference, your license key stays the same, and your site limit rises the moment payment completes — no re-activation on your sites.
- Support hardening: ticket confirmation emails to customers, staff notifications on replies, customer file attachments, priority support wired to your plan (Pro+ can open urgent tickets), and contact-form messages now land in the support queue instead of a write-only table.
Improved
- Core update notes in the admin panel now show the real release changelog instead of a generic package label.
- Update access tier is now read from the license record, so plan upgrades take effect on the update channel instantly.
Fixed
- License seat operations no longer depend on the execution context — the customer panel, admin, and API all use the same database seam (previously the panel path could fail fatally).
- Support tables are now guaranteed with self-healing schema (including legacy installs), so the customer portal cannot hit a missing-table error.
Site-Wide SEO Hardening
Added
- Archive pages (category, tag, author, search) now generate their own unique titles, meta descriptions, and Open Graph tags — no more duplicate-title clusters across archives, on every theme, with no theme changes required.
- Optional tag archives: a new SEO setting turns /tag/ pages into real, sitemap-listed archives (thin tags stay auto-noindexed). Off by default, matching modern crawl-budget guidance.
- Feeds now declare a WebSub hub, so feed readers and discovery services get real-time update pushes; uploaded images receive an automatic humanized alt text when none is provided.
Improved
- The first large content image on each page is now promoted to eager loading with high fetch priority — a direct LCP (Core Web Vitals) win on image-led pages.
- Meta descriptions no longer cut words in half: automatic descriptions now end on word boundaries with clean punctuation.
- Retired Google/Bing sitemap-ping calls were removed from the publish path (they only added seconds of dead waiting), and duplicate IndexNow submissions were deduplicated to a single ping per publish.
- Sitemap accuracy: real last-modified dates in the index, paginated post sitemaps are announced above 50k URLs, and video sitemaps join the index when video posts exist.
Fixed
- Structured data is now hardened against content that contains script-closing sequences (JSON_HEX_TAG across all emitters) — schemas can no longer be broken or exploited by post content.
- Open Graph URLs on archive pages pointed to the homepage; they now match the canonical URL. og:locale now always agrees with the html lang attribute.
- On subdirectory installs the og:image check failed silently and social cards shipped without an image; the base path is now resolved correctly.
- Non-existent category and author URLs returned an empty page with HTTP 200 (soft-404); they now return a real 404. Duplicate Recipe/FAQ schema emissions are prevented page-wide.
Stories: Consistent Emoji Art, Reaction Switching & Live Reaction Stream
Improved
- Reactions now use embedded SVG emoji art (Twemoji) instead of OS emojis — the same crisp, modern look on every device and browser, with no external requests.
- You can now change your reaction: tap a different emoji and the previous one is replaced, with counts adjusted correctly behind the scenes.
- Earlier reactions are now visible to every viewer as a subtle ambient stream — tiny emojis float up the story while it plays, proportional to how many reactions the slide collected.
- The Statistics page was redesigned: KPI tiles on top, per-slide view bars, CTR column, emoji-by-emoji reaction breakdowns, inline poll result bars, and a visual completion meter per story.
Instagram-Style Story Reactions
Improved
- Story reactions were redesigned in Instagram's quick-reaction language: six bare emojis (❤️ 😂 😮 😢 🔥 👏) with a springy pop on tap and a shower of emojis floating up the story — no button chrome, no grey chips.
Stories v1.1 — Auto-Stories, Polls, Reactions & Analytics
Added
- Auto-stories: when you publish a post, a story is created automatically from its featured image, title, and link — and retires on its own after a configurable lifetime. Your story strip stays fresh with zero manual work.
- Poll slides: ask a question with 2–4 answers; visitors tap to vote and instantly see live percentage bars. One vote per visitor, no login required.
- Emoji reactions (🔥 ❤️ 👏) on every slide — a single tap, cookie-free, one reaction per slide, with a satisfying burst animation.
- Statistics tab: per-slide views with a 7-day column, link clicks with CTR, reactions, poll result breakdowns, and a completion rate showing how many viewers reach the last slide.
Stories Cache Fix & Cleaner Admin
Improved
- The Stories admin was decluttered: slide editing is now collapsed behind an Edit toggle, add-slide tools are grouped into tidy accordions, and settings use aligned rows with inline inputs.
Fixed
- The Stories viewer script is now served with a server-cache bypass, so viewer fixes reach visitors immediately after an update instead of being pinned to a stale cached copy.
- Closing the viewer is hardened at the style level as well — the close button, Escape, and swipe-down work even if a theme stylesheet interferes.
Stories Viewer Fixes & Inline Links
Fixed
- The story viewer close button (and Escape / swipe-down) now reliably closes the overlay.
- Slide links are now clickable text instead of a separate button: the caption or card text itself opens the link, and inline links can be placed on any word with [visible text](url) syntax.
- The story-age indicator in the viewer header now shows explicit units (e.g. "3 h"), so it can no longer be mistaken for the slide duration.
Stories — Instagram-Style Stories for Your Site
Added
- New Stories plugin: a tappable story strip with a full-screen viewer — image, video (MP4/WebM), and text-card slides with auto-advancing progress bars, swipe/keyboard navigation, and hold-to-pause. Mobile-first, dependency-free, and zero page weight when no story is live.
- Every slide can carry a caption, a custom duration, and a call-to-action link with its own label — turn announcements into traffic.
- Scheduling and auto-expiry: stories go live and retire on their own; permanent "Highlight" stories pin to the end of the strip. View counts are tracked per story, cookie-free.
- Placement is yours: choose the strip position (below header, top of content, top of page, above footer, or a custom CSS selector) and target pages from settings — saved per theme, works on every theme without touching theme files.
- Appearance controls with live preview: circle or vertical-card shape, three sizes, classic gradient / solid / no ring, alignment, optional strip heading, and automatic gray rings for already-watched stories.
License Enforcement Gap-Closing
Improved
- The managed-install marker is now cryptographically signed and domain-bound, so it can no longer be forged to bypass license enforcement. Legitimate managed installs are unaffected.
- Operators now receive automatic alerts (email digest) for suspected redistribution, license clones, and installs that stopped verifying — detection no longer depends on manually opening a dashboard.
License Enforcement & EULA Hardening
Improved
- License verification now reports the copy's distribution origin, so unauthorized redistribution of a licensed copy is detected automatically and surfaced in the operator's installs dashboard. Legitimate installs are unaffected.
- The End User License Agreement (EULA) was strengthened with explicit clauses on embedded copy-tracking, its evidentiary value, liquidated damages, and reverse-engineering/rebranding bans; checkout now records EULA acceptance.
Install Integrity Hardening
Improved
- The install-integrity subsystem was strengthened so unauthorized modification or redistribution of a licensed copy is detected and traceable more reliably. Legitimate installs are unaffected.
Traffic & Distribution: Web Push Repair, Single IndexNow Key and Outreach Pacing
Improved
- The weekly opportunity limit in the backlink workspace is now actually enforced: once the week's quota is used, new additions are paused with a clear message — keeping outreach deliberate, exactly as the screen promises.
- Traffic Health now includes a Web Push row: service-worker reachability, subscriber count and the last send at a glance.
Fixed
- Web Push now works end-to-end. The public endpoints the browser needs (service worker, key, subscribe) were never wired into the router, so enabling push could not deliver a single notification. They are now first-class routes, subscriptions are validated before being stored, and sending respects a time budget so a large subscriber list can never stall publishing.
- One IndexNow key per site. The plugin and the core search pinger each generated their own key, leaving two key files in the site root and duplicate submissions. Both layers now share a single key; changing or regenerating it updates everything and removes the stale key file.
- Saving a setting after a test or an error no longer shows a generic "Saved." — the real result (test outcome, error detail) is now displayed.
- If VAPID keys could not be generated during activation, Web Push stayed permanently broken with no way to recover; the settings screen now regenerates them automatically and reports failures clearly.
Social Auto-Publish: Instagram Stories, Discord, Evergreen Re-sharing and Reliability
Added
- Instagram Stories. Every new post can now also be shared as a 9:16 story a few minutes after the feed post — the image is prepared automatically from the featured image. On by default, one toggle in settings.
- Discord channel publishing. Zero-friction: paste a channel webhook URL and every new post lands in your community as a rich embed (title, description, image, link). No app registration, no OAuth.
- Evergreen re-sharing. Opt-in: older evergreen posts are periodically re-shared to your text channels for steady archive traffic — age threshold and daily cap are configurable, visual channels are excluded, and the same post is never repeated within the window.
- Failed-item recovery. The queue screen now lets you retry or delete failed items (one or all) and shows a 7-day per-platform success-rate table.
Improved
- Adding a new token-based platform no longer requires editing the admin screen: connection forms are generated from the platform registry.
- Facebook Page connections now exchange for a long-lived token and refresh themselves — previously the token silently died within hours and the account broke on first publish.
- The queue is now claimed atomically per item, so overlapping schedulers can never double-publish; stuck items self-recover after 30 minutes, and web-cron runs respect a time budget.
Fixed
- Pinterest "Diagnose" results were never written to the log (a status value the table did not accept was silently dropped).
- Expired connections are now labeled as expired with a clear reconnect signal instead of a generic error.
- The X/Twitter authorization no longer requests a media permission the adapter never uses.
Admin Raw-Key Repair: 249 Missing Translations Restored
Fixed
- Several admin pages showed raw translation keys instead of text (e.g. "admin_blog_posts.th_title") — in both languages. 249 missing dictionary entries were authored in Turkish and English across the blog posts, licenses, email templates, order detail, invoices, backups and login screens; a new linter check now blocks any future use of an undefined key.
- The theme catalog page and the sidebar's First-Install Package label were hardcoded in Turkish; they now follow the admin language.
- The invoices screen crashed on load: its overdue-count query referenced a column that never existed (due_at → due_date).
Customer Portal Fully Bilingual + a Language-Leak Shield
Improved
- A new internal language-leak linter guards every future change: any new user-facing string that is not born as a TR/EN pair is caught before release, so this class of bug cannot silently return.
Fixed
- Turkish text no longer leaks into the English customer portal (and vice versa). Every remaining single-language page was made properly bilingual: security settings, email verification, forgot/reset password, checkout and its success/cancel pages, support tickets, downloads and order details.
- The setup wizard now speaks English. The first screen a new buyer sees was almost entirely Turkish; it is now fully bilingual with a TR/EN switcher, follows the browser language by default, and all of its error messages are translated too.
Site Name Signal Completed Across All 14 Themes
Fixed
- Every theme's homepage now marks the site name as an H1 heading — completing all four signals Google documents for choosing the site name shown in search results, so Google stops falling back to the bare domain. The heading renders with zero visual change; inner pages keep their content H1. (Personal shipped in the previous release; the remaining 13 themes are covered now.)
- The Minimalist theme's header brand was hardcoded to a specific site name; it now follows the Site Name setting like every other theme.
- The Finance theme showed no brand at all when no logo was uploaded, and its homepage detection could mislabel search or paginated pages; both were corrected.
- The Recipes theme rendered its brand as an H1 on every page, giving articles two H1s; the brand is an H1 on the homepage only now.
Personal Theme: Site Name Signal Completed for Google (Homepage H1)
Fixed
- Google could fall back to showing your domain instead of your site name in search results. The Personal theme's homepage had no H1 heading — one of the four signals Google documents for choosing a site name (WebSite structured data, og:site_name, title, and a prominent heading). The header brand now renders as an H1 on the homepage only, with identical visual styling; inner pages keep their content H1.
Buying Goes Live: Pricing-Page Checkout and a Discount Campaign Manager
Added
- The pricing page now sells. Every plan's button opens the secure checkout with that plan preselected; signed-in customers get their email and name prefilled, and the checkout language follows the site language.
- Discount campaign manager. Define campaigns in the admin — percentage or fixed amount, date windows, redemption limits, per-plan restrictions and special-day presets (New Year, Black Friday, and more). Campaigns sync to the payment provider automatically; the pricing page shows a campaign banner and can apply the code at checkout without the customer typing anything.
Fixed
- Plan prices defined in code had drifted from the public pricing page; they are aligned again.
International Payments via Polar, Instant License Delivery, and an Account Security Overhaul
Added
- International card payments via Polar (Merchant of Record). Every paid Polar order automatically creates the customer account, issues the license key, generates the invoice and emails the key — no manual steps. Deliveries are idempotent, webhook signatures are verified, and the checkout thank-you page shows the license key the moment it is ready.
- Email verification for customer accounts. New registrations receive a verification link (sign-in is never blocked); changing your email re-requires verification of the new address and notifies the old one. A new resend-verification page replaces links that previously led nowhere.
- Account deletion (GDPR/KVKK). Customers can permanently anonymize their account from the Security page with password confirmation; order and invoice records are retained as required by law.
- Real login history. The Security page now shows actual sign-in attempts (date, IP, outcome) — the old list was wired to a table nothing ever wrote to.
Improved
- Brute-force protection is now database-backed. The old limiter counted attempts inside the visitor's own session, so clearing cookies reset it; limits are now enforced per email and per IP across sessions, and every attempt is audit-logged.
- Changing your password now confirms it by email and refreshes the session; the non-functional "Remember me" checkbox was removed (sessions already persist for 30 days).
Fixed
- The email verification page queried columns that never existed in production, so verification links could not work; it now uses the real schema.
- Viewing a support ticket linked to an order could fail due to a query against a non-existent table.
- Site-validation bots of payment providers were blocked by an over-broad user-agent filter, which made provider onboarding fail with "could not reach this URL".
Sign-In Flow Streamlined: Session-Aware Header and Google-Only Social Login
Improved
- The site header now recognizes signed-in customers. After signing in or registering, the "Sign In / Get Started" buttons are replaced with "Dashboard" and "Sign Out" — on desktop and in the mobile menu.
- Signing in no longer pulls you away from the page. Logging in or registering from the site keeps you where you were instead of forcing a redirect to the customer dashboard; Google sign-in returns you to the page you started from.
- Your language choice follows you into the customer portal. Browsing the site in English opens the dashboard in English after sign-in; browsing in Turkish opens it in Turkish.
- Social sign-in is now Google only. The rarely used GitHub, Facebook and Microsoft sign-in options were removed from the sign-in modal, the portal pages and the admin settings.
- Signing out now returns you to the homepage instead of the login screen.
Fixed
- Google sign-in errors are now shown. The login page listened for the wrong URL parameter, so OAuth errors (cancelled sign-in, misconfiguration, inactive account) were silently swallowed; all error codes now surface with bilingual messages.
- The registration modal accepted submissions without the Terms of Service checkbox being ticked; acceptance is now enforced.
- Sign-in and registration API calls resolved to the wrong path on subfolder installations; they now respect the site base path.
- Password reset now works on installations missing its table. The password_resets table only existed in a development migration; when absent, the forgot-password form crashed. The table now self-heals on first use, and a mail delivery failure no longer breaks the flow.
- Login error messages mixed English and Turkish regardless of the chosen portal language; they now follow it.
Content Tables Are Now Styled in the Personal Theme
Fixed
- Tables inside articles now have proper borders, a header row and spacing. The Personal theme had no table styling, so tables rendered as plain unbordered columns that were hard to read. They now have cell borders, a shaded header row, comfortable padding, zebra striping and horizontal scrolling on small screens.
Schema Gaps Closed for Voting, AI SEO Analysis and IP Blocking
Fixed
- Article voting now works. The up/down vote feature (used by the crypto theme) wrote to a post_votes table and a posts.votes column that the schema never created — and an old migration even defined the table with mismatched column names. The table and column are now part of the schema, self-heal on existing sites, and the stale migration was corrected.
- AI SEO analysis is now saved. The editor's AI analysis wrote to seo_meta columns (ai_score, ai_analysis, ai_analyzed_at) that did not exist, so results were never persisted. The columns were added to the schema and self-heal on existing sites.
- The IP block list has a proper schema table. Previously it only existed when an admin happened to open the Security Center; it is now part of the core schema and self-heals.
Schema Consistency: Silent Database Errors Fixed + Drift Guard
Improved
- A schema drift guard now runs in the release pipeline. A new tool cross-checks every table/column written by the code against the schema and plugin definitions; any newly introduced mismatch fails the release, preventing this class of fresh-install error from recurring.
Fixed
- Comment replies and API comment creation now save reliably. Both wrote to a column name (ip_address) that did not exist on the comments table (the correct column is author_ip), so these paths failed on every install. They now use the correct column.
- Automatic IP blocking now actually blocks. The security module wrote a non-existent blocked_at column, so blocks were silently dropped; it now uses the correct column.
- Theme switching and settings saves are safe on fresh installs. The settings table gained created_at/updated_at columns (added to the schema and self-healed on existing sites) — code wrote these timestamps but the fresh-install schema lacked them.
- ZeroTrack registers correctly on activation. Its plugin record used the wrong column names (active/core instead of is_active/is_core).
Log and Data Hygiene: A Self-Limiting CMS
Improved
- Automatic maintenance now covers every accumulating store. Raw view records (180 days), auto-link logs, SEO ping logs and expired Google Console cache entries are pruned on the existing maintenance schedule, and oversized log files (including php-errors.log) are rotated centrally with 30-day cleanup of old rotations.
Fixed
- The database error log can no longer grow without bound. It now rotates at 5 MB with a single backup kept, matching the application log. A recurring cron error had been able to grow this file indefinitely.
- Two chronic error sources were silenced at the root. The webhook queue self-heals missing api_tokens columns on older installs (and the webhook feature starts working), and the AI bulk worker skips quietly when its table is not installed — both had been writing an error entry every minute.
ZeroTrack: Interactive Trend Chart and Full Localization
Improved
- The trend chart was redesigned from scratch. The bare line chart is now an interactive bar chart: hovering highlights the bar and its neighbors, shows a tooltip with views and unique visitors, and updates the live value in the header. Days with no data render as zero instead of being skipped, and the "Today" range now shows an hourly breakdown.
- KPI cards now compare against the previous period. Page views, unique visitors and sessions show a rise/fall percentage next to the label.
- The whole plugin follows the admin design system and language. Every label on the dashboard and settings pages is fully localized (Turkish admin shows Turkish everywhere), and hard-coded light-theme colors were replaced with design tokens so dark mode renders correctly. Top pages gained proportional usage bars.
Google Console: Consistent Reports and a Permanent-Connection Guide
Improved
- Search Console and Analytics now report the same date window. GA4 requests previously ended "today" while Search Console ended yesterday, so overview KPIs compared different periods. Both now use the identical range, making trends directly comparable.
- Keyword and page tables show up to 50 rows (previously 20), and indexing-coverage scans now cover up to 2,000 URLs (previously 500) in line with Google's URL Inspection daily quota.
- Reconnect banner now explains the most common cause. When Google drops the connection with invalid_grant — typically because the OAuth app was left in "Testing" mode, which expires grants after 7 days — the panel says so and walks through publishing the app to production for a permanent connection. The setup guide covers this too.
- Search Console site addresses are normalized on save. Entering a bare domain becomes a proper domain property (sc-domain:), and URL-prefix properties get their required trailing slash — malformed values used to fail silently with empty reports.
Newsletter Result Pages Work on Every Theme, in Both Languages
Fixed
- Newsletter subscribe/confirm/unsubscribe pages no longer crash on non-Personal themes. These pages called a Personal-theme helper directly, which caused a server error on any other active theme. They now use a theme-safe helper and render their texts in the site language (Turkish or English) instead of hard-coded Turkish.
Visible Spam Protection, Reliable Newsletter Signup, Consistent Plugin Naming
Improved
- The built-in spam filter is now visible and explainable. The Comments screen links directly to Spam Protection settings, flagged comments show their spam score with the reasons that triggered it, and the spam tab offers a one-click "Not Spam" action. The filter itself (link limits, keyword/IP/e-mail blacklists, submit-speed and repeat-offender checks) was already scoring every comment behind the scenes.
- Plugin names and ordering are consistent everywhere. The sidebar now uses the same localized plugin names as the Plugins screen, and both lists are sorted alphabetically by the displayed name.
- Theme customizer is fully localized. Tab and theme descriptions now appear in Turkish on Turkish admin panels, and the page title follows the admin language.
Fixed
- Newsletter signup now works from every theme. Several themes posted their subscribe forms to endpoints that did not exist (/newsletter, /api/v1/newsletter/subscribe), so signups silently failed. Both endpoints now reach the newsletter plugin, and the API works in sub-directory installs too.
- Fresh installs no longer break on comments or subscribers. The installer schema was missing the spam-score columns on comments and the subscribed_at column on newsletter subscribers; both are now in the schema and self-heal on existing sites.
- New-post notification e-mails render correctly. The notification campaign stored post data as raw JSON that would have been printed into the e-mail; the sender now resolves it into the template placeholders.
- Crypto theme footer now obeys the customizer. The "Brand blurb" field is actually rendered, the social-icons toggle works, the site name is no longer hard-coded, and the footer subscribe form posts to the correct endpoint.
Instant Admin Asset Updates, Dropdown Clipping Fix
Fixed
- Admin CSS/JS updates now reach the browser immediately. Stylesheet and script URLs are versioned by file modification time instead of the CMS version number, so hotfixes no longer require a hard refresh or a version bump to become visible.
- Custom dropdown panels are no longer clipped by their card. When a select panel (such as the Author picker in the post editor) is open, its containing card temporarily allows overflow so the full option list is visible.
Author Picker on the Post Editor, Sentence-Aware Excerpts
Added
- Posts can now be assigned to a different author from the editor. A new Author dropdown in the Publish box lists the site's writers; the change is saved with the post. Autosave and quick-edit paths are unaffected.
Fixed
- Auto-generated excerpts no longer cut off mid-phrase. The generator now prefers the last full sentence within the window, ignores version-number dots (like "GPT-3.5"), is UTF-8 safe for Turkish characters, and inserts spaces where block tags met. Existing truncated excerpts across all sites were regenerated from content.
Pro Theme Customizer: Font Previews, Import/Export, Turkish UI, Deeper Options
Added
- Theme settings can now be exported and imported as JSON — move a finished design to another install in one click, with schema-validated import, cross-theme confirmation and a one-click "Reset to defaults" that preserves footer-builder data.
- Font pickers became real font pickers. A central 38-family library backs every font field (empty dropdowns are gone), the current font sits selected at the top, every option renders in its own typeface, and a live preview line updates as you browse.
- Deeper per-theme options, all wired to real output: the Personal theme gained homepage controls (hero slide count, popular section and count, categories toggle, posts-per-page for the latest grid) and a Post Page tab (sidebar, author card, related posts and count, comments) — every switch verified to change the rendered page.
Improved
- The customizer speaks Turkish now. Over a hundred remaining English field and tab labels across all theme schemas were translated for Turkish admin sessions.
Fresh-Install Audit: Theme Switching, Customizer and Setup Hardened End-to-End
Fixed
- A full customer-journey audit (installer → theme switching → customizer → import) fixed nine fresh-install bugs. Subdirectory installs no longer hit an infinite redirect on About/legal pages; single-post pages now receive author data, so the News theme no longer crashes; the Tech theme's missing helper, the Finance theme's missing comments partial, and Health theme null-image crashes are all resolved.
- Search works on every host now. Reusing one SQL placeholder twice broke search with an SQL error on servers where PDO prepares are not emulated — fixed in the core query builder, the Health theme and the quiz plugin.
- Saving the Theme Customizer no longer wipes other settings. It used to replace the theme's whole customization record, silently deleting footer-builder data; it now updates only its own fields. The footer builder likewise activates only on themes that render it, instead of corrupting other themes' footer settings.
- Setup polish: application logging now creates its log directory on first use (it was silently dead on fresh installs), broken absolute-path ErrorDocument rules were removed, and session ini warnings on first requests are gone.
Media Library: Click-to-Edit Restored, Smarter Alt Text Editing
Improved
- Alt text editing got a live character counter and guidance (ideal ≤125 characters) so image SEO fields are filled properly, not just filled.
Fixed
- Clicking an image in the media library opens its detail/edit screen again. The lightbox was capturing every click on image cards, so the screen where alt text, caption and description are edited had become unreachable. Zooming now has its own magnifier button on the card (and clicking the preview on the detail page).
Ad Placements Standardised Across All Themes, Honest Slot Panel
Improved
- Every theme now renders the standard ad placement set. An audit found the personal and trends themes rendered no ad slots at all, health and recipes only one or two — ad code pasted in the admin simply never appeared. All themes now support: below navigation, above/inside/below the article, between archive cards and above the footer.
- The ad manager now tells the truth per slot. Each slot card shows whether the active theme actually renders it ("In theme" / "Not in theme" badge), and the four legacy slots that no current theme uses are hidden unless they hold saved code.
Hotfix: Footer Customizer Save No Longer Rejected
Fixed
- The real root cause of the footer customizer's "CSRF token mismatch" was a field-name mismatch, now fixed at the core. The form emits its token as
_tokenwhile the handler readcsrf_tokenand passed an empty string, which blocked the fallback lookup — so every save was rejected even in a fresh session. The validator now treats an empty token as "not provided" and falls back to all accepted field names; invalid tokens are still rejected.
Footer Customizer Redesign, Newsletter Styling, Session-Lifetime CSRF
Improved
- The footer customizer got a visual overhaul. Templates are now picked from illustrated layout thumbnails instead of a text list, sections follow a consistent card design, and a sticky save bar keeps the action always in reach.
- The footer newsletter block is now fully configurable. Besides the title and intro, you can set the input placeholder, the button text and a display style — plain, boxed card or accent-tinted card — with matching styles for dark footers and mobile.
Fixed
- "CSRF token mismatch" on save is gone. Security tokens used to hard-expire after one hour, so any admin form left open longer — the footer customizer, a long post edit — died on submit. Tokens are now valid for the whole login session, per the standard per-session pattern.
One-Click Edit for Every Legal Page
Improved
- Every row in the legal page status table now has an Edit button. For pages still served from the theme's built-in template, clicking Edit creates the page from the ready-made text using your site settings and opens the editor immediately — no detour through the generator form. The explanatory text on the screen was also rewritten in plain language.
Pages Hub With Inner Navigation, Legal Pages Finally Editable at a Glance
Improved
- The Pages screen is now a proper hub with an inner sidebar — the same pattern as Settings. Modules are grouped under headings: Pages (all pages, new page) and Legal Pages (status & edit, generator). The old single-scroll screen that mixed the generator, a status table and a legacy record list into one confusing page is gone.
- Every legal page now has a clear path to editing. Pages backed by a CMS record show an Edit button; pages currently served from the theme's built-in template are labelled "theme default" and offer a one-click Create action that jumps to the generator with that page preselected.
Fixed
- Hover row actions (Edit | View | Trash) in content lists are left-aligned under the title again. A shared action-cell style had pushed them to the right edge of the title column in posts, categories, tags and quiz lists.
- The legacy legal-records block was removed from the CMS admin. It edited a marketing-site table that has no effect on a CMS site's public pages, which made the screen genuinely misleading.
Category Slug Renames Get Automatic 301s, 404 Logging Heals Itself
Added
- Renaming a category slug now creates a 301 redirect automatically — in both the admin panel and the REST API. Combined with v2.18.8's post-slug redirects, no rename anywhere in jekcms can silently orphan an indexed URL anymore.
Fixed
- 404 logging works on every install now. The not-found log table was only created when an admin first opened the Redirects page; on sites where that never happened, every 404 was silently discarded and the "suggest redirect" list stayed empty forever. The logger now creates its own table on first use.
Automatic 301 on Slug Change, Legacy URL Guard, Cleaner Crawl Budget
Added
- Renaming a published post now creates a 301 redirect automatically. Previously every slug change silently left the old URL as a 404 in Google until someone noticed and added a manual redirect — a fleet-wide Search Console audit found exactly this pattern in the wild. The redirect is created on save, existing chains pointing at the old slug are re-pointed at the new one, and duplicate sources are never inserted.
- Built-in guard for legacy WordPress URL families. Retired Turkish tag archives (/etiket/…) now return 410 instead of soft-404 redirects, taxonomy AMP leftovers (/author/…/amp, bare /amp, /amp/page/N) redirect in a single hop, so migrated sites stop accumulating Search Console errors.
Improved
- Crawlers no longer waste budget on write-only endpoints. robots.txt now disallows the analytics beacon (/zt-track) and webhook paths, which previously showed up as "other 4xx" noise in Search Console.
Search Console Cleanup: Retired Tag URLs Are Now Crawlable (410)
Fixed
- Retired /tag/ URLs can now leave Google's index. robots.txt disallowed /tag/ while the pages correctly returned 410 Gone — but a crawler that is blocked can never see the 410, so hundreds of dead tag URLs stayed frozen in Search Console error reports indefinitely. The disallow is removed; Google can now crawl the 410 responses and drop the URLs for good.
Comprehensive Legal Pages, Unified Footer Credit, Author Card Fix
Improved
- Legal pages are now comprehensive and professional out of the box. The default Privacy Policy, Terms of Service, Cookie Policy and Disclaimer texts were rewritten editorially in both languages: data categories, legal bases, retention periods, Google AdSense/analytics disclosures with opt-out links, a cookie category table, permitted-use and liability sections. Sites that publish their own legal pages are unaffected — defaults apply only when no custom page exists.
- One footer credit everywhere. The footer bottom bar now reads "Powered by jekcms" in every language — the former Turkish translation of the credit was dropped in favor of a single brand-standard phrase.
Fixed
- Legal pages are readable on dark-bodied themes. The universal legal template had no background of its own, so themes with a dark page body rendered near-invisible headings on a dark surface. The template now pins an explicit light panel with fixed text colors, plus proper list and table styling.
- Author card uses its full width. The author bio in the crypto theme was capped at 480px, wrapping sentences into a cramped column next to the avatar; the cap is removed.
Crypto Theme: Legacy TOC Cleaner No Longer Swallows Article Bodies
Fixed
- Articles no longer render truncated. A legacy WordPress-import cleaner in the single template removed inline tables of contents with overly broad patterns: any H2 merely containing the word "içerik" — e.g. "AI content production" — triggered deletion of everything up to the next list, silently cutting up to 90% of an article at render time (the database content was intact). The cleaner now only scans the first 3000 characters, matches exact TOC phrases, and caps the removal window.
Crypto Theme: Full-Width Layout and Styled Content Tables
Improved
- Homepage post grid and single articles now align with the header width. The "All Posts" section and the article layout previously used a narrower container, and the article body was additionally capped at 736px — both now follow the site's full 1400px line, so wide screens are actually used.
Fixed
- Content tables render properly in articles. Table styling was scoped only to static pages, so tables inside posts appeared bare (no borders, no header background). Article bodies now get the same professional table look, with zebra rows and horizontal scrolling on mobile.
Winning Content: Traffic Trends on Your Dashboard
Added
- Winning Content card on the dashboard. Your top 5 posts of the last 30 days with rise/fall indicators, powered by the built-in privacy-first ZeroTrack analytics — no external service, no cookies. Appears automatically once traffic data exists.
- Content Trend report in ZeroTrack. A rising/falling comparison (last 30 days vs the previous 30) at post level; falling posts are labelled as refresh candidates, so you know exactly which articles need attention before rankings slip further.
Uniform Row Actions Across All SEO Lists
Improved
- List action buttons follow one clean standard. In Heading Fixer, Content SEO, Content Optimization and Orphan Content, row actions (Preview / Fix / Save / Edit) no longer wrap onto multiple lines or mix button styles — they sit in a single compact row with a consistent look; secondary validator shortcuts (Rich Results, Schema) are now subtle links instead of heavy buttons.
- Less noise in the Content SEO list. The redundant content-type label before each slug was removed; pages are marked with a small badge only when relevant.
Advanced SEO Panel v2: One Navigation, Auto-Linked Orphans, Brand-Safe Headings
Added
- Orphan content fixes itself. The Orphan Content module gained an Auto-Link action: for every post with no inbound internal links, related posts (same category first) are scanned and a natural internal link pointing at the orphan is injected automatically — no manual editing, with the full markup-safety net and at most one new link per source post.
- SEO Health Check is now tabbed. Identity, AdSense, content, files and HTTP checks each get their own tab with issue-count badges — no more scrolling through long card columns.
Improved
- One navigation, zero duplication. The Advanced SEO panel sidebar is now grouped (Overview, Content, Images, Links, Site) and each optimizer tab is its own module; inside the panel the old duplicate top tab bar is gone, and confusingly-named entries were renamed (Image SEO vs. Featured Images).
- Redirects & 404 opens clean. The module previously rendered the whole Settings page — including its own settings menu — inside the panel; it now opens as a standalone tool.
- Year Updater and Content Optimization follow the design line. Cards, tables and buttons match the rest of the admin; action buttons no longer wrap into circle-shaped blobs, and the Edit button got its missing style.
Fixed
- Technical terms are no longer "fixed" into broken casing. Heading checks flagged titles like "cPanel Guide" or "iptables and ufw" as lowercase errors, and title-case would mangle them (cPanel → Cpanel). Brand-like words — mixed-case names, terms with digits or dots, and a broad list of lowercase tool names — are now left untouched in both detection and repair; Turkish conjunctions (ve, ile, için…) also stay lowercase in title case, in both languages.
Advanced SEO Overhaul: Internal Linking Repaired, Turkish-Aware Matching, New Modules
Added
- Turkish-aware internal linking. On Turkish sites the linker now recognizes inflected forms ("e-posta pazarlamasında" matches "E-posta Pazarlama"), and posts' multi-word tags become anchor candidates — noticeably more natural internal links, with the same markup-safety net that reverts anything suspicious.
- Orphan Content module. Lists published posts with no inbound internal links and uncategorized posts, with linking-candidate suggestions from the same category.
- Bulk meta editor. Edit meta title/description inline in the post list with live character counters; scores recompute on save. CSV export is one click away.
- The panel now surfaces SEO Health Check, Redirects & 404 log and the SERP Identity test — previously hidden in Settings.
Fixed
- Posts that matched no links are no longer excluded from future scans. A "processed, no links" marker made such posts invisible to the incremental scan forever and miscounted the panel statistics; they are now retried as your library grows, and the stats distinguish processed, linked and awaiting posts.
- Internal-linker silence is over. Every skipped, failed or successful on-publish linking attempt is now recorded to a dedicated log, so "why did this post publish without links?" is answerable — a read-only diagnostic page shows settings truth, log distribution and a live dry-run.
- The SEO panel no longer breaks inside its frame. Saving a form could render a second admin shell inside the panel, and edit links trapped you inside the frame; both fixed.
- Turkish content scores are measured correctly. Word counting was not UTF-8 aware, so Turkish posts scored artificially low; generated meta titles also respect your title separator and site name now.
- All SEO tools require administrator rights and use a single heading-hierarchy engine, ending inconsistent results between modules.
No More Style Flash on Inner Pages, Analytics Beacon Restored
Fixed
- Pages no longer flash unstyled for a split second. The Personal theme async-loaded its full stylesheet while the inline critical CSS did not fully cover any page type; navigation briefly rendered bare. The stylesheet now loads normally — it is same-origin, versioned and immutable-cached, so the change costs nothing after the first visit.
- ZeroTrack page views are recorded again. The tracker posted to a plugin route that 404'd in production; it now uses the standalone /zt-track endpoint that works independently of plugin bootstrap.
- Cloudflare Insights no longer triggers console CSP errors. Its beacon origin was missing from the Content-Security-Policy script allowlist.
Zero Validator Errors: noscript Guard & Footer Style Leftovers
Fixed
- The font-defer optimizer no longer touches noscript fallbacks. It could wrap the fallback link inside an existing noscript block, producing nested noscript markup and a dead stylesheet for no-JS visitors.
- Personal footer layouts dropped their duplicate legal bar. All eight variants carried a leftover legal-links block and an in-body stylesheet from before the standard bottom bar; links were doubled and the markup failed validation.
Three Gaps Caught by the New Live Signal Checks
Fixed
- Health theme now emits the WebSite/Organization schema. Its header never called the central schema emitter, so sites on this theme published no structured data — invisible to Google's site-name and rich-result systems.
- Personal theme search pages are noindexed again. The header skipped the robots-meta helper entirely, leaving search results indexable.
- News-theme language attribute reads the correct setting. A legacy key left Turkish sites reporting lang="en".
Theme Integrity: Every Theme File Now Ships From One Source
Fixed
- Recipe featured images resolve to the correct URL everywhere. A media-path fix that lived on a single install (cards/hero images could 404 when stored without the uploads prefix) is now part of the core Recipes theme.
- Theme copies can no longer silently drift. Previously only ~30 hand-picked theme files were integrity-checked; now every theme template and stylesheet is verified against the canonical source, and deliberately customized installs are tracked explicitly instead of being overwritten.
- Hardened against a class of update crashes. Syncing a theme's function file onto a customized install could remove helpers its templates still call, cutting pages off mid-render. Sync tooling now knows about customized theme sets and never overwrites them.
Valid Markup, Correct Language Tags & Faster Font Loading
Improved
- Fonts no longer block first paint. Google Fonts and icon stylesheets across all themes now load with the non-blocking preload pattern, improving Core Web Vitals.
Fixed
- Turkish search pages are no longer indexable. The /arama route escaped the noindex rule that /search already had, leaving thin search results crawlable — a "low value content" risk for ad-network review.
- Removed the hidden duplicate H1 from homepages. An old experiment injected an invisible site-name heading on every homepage, producing two H1 elements on themes that render their own. Each page now has a single, visible heading.
- Article pages no longer break on customized Entertainment installs. A sidebar helper call could crash mid-page on sites with a customized theme copy, cutting the page off before the footer. The sidebar now degrades gracefully.
- Markup validates cleanly. Headings inside inline wrappers, a mis-scoped ARIA label and the footer bar's in-body stylesheet (now emitted in the head) were the last W3C validator errors.
- Language attribute now follows your site language. Five themes hard-coded lang="en"; Turkish sites reported the wrong language to browsers and crawlers.
Your Site Name Now Reaches Google Exactly As You Typed It
Fixed
- Google could show your domain instead of your site name in search results. The system auto-generated a spaceless copy of your site name as a schema alternate name, and a Turkish-character comparison bug let this domain-lookalike value slip into the page. Google's site-name algorithm could then fold your brand into the bare domain. The auto-generated alternate name is gone, the comparison now transliterates Turkish characters correctly, and existing installs clean up the stray value automatically — the Site Name setting is now the single source of truth, emitted verbatim.
- Removed weaker duplicate schema emitters from five themes. Personal, Trends, Recipes, News and Lifestyle carried their own WebSite/OpenGraph generators missing fields Google uses for site-name selection; all themes now use the central, complete emitter.
- Admin SEO preview now matches the real page output. The preview showed a different homepage title pattern than what the site actually emitted.
Content Rendering, Performance & AdSense-Ready Theme Pass
Improved
- Faster pages with responsive images. Article cards and thumbnails now load an appropriately sized image variant instead of the full-resolution original, cutting page weight significantly.
- Navigation and footers are data-driven. Menus, category bars and footer links now come from your real categories, so a fresh site never shows dead example links — better for visitors and for ad-network review.
- Dark mode stays correct with custom colors. Setting brand colors no longer overrides the dark theme; dark mode renders reliably regardless of customization.
- Cleaner article intros. The first paragraph is auto-capitalized at publish, so content never starts lowercase.
Fixed
- Markdown headings no longer leak as raw “###” text. Content that mixed HTML with Markdown could print literal “### Heading” or merge a heading and its first paragraph into one oversized block. Headings are now correctly separated and rendered, both at publish time and on render — across every theme.
- Queued articles that silently failed to publish now go out reliably. A session-cookie error during manual publishing could leave items stuck as “failed”. The underlying call is now guarded, so publishing completes instead of aborting mid-way.
- Removed placeholder/demo content from themes. Sample authors, demo article bodies, fabricated statistics and dead example links could appear on real pages; these are gone, so only your real content is shown.
- Legal links now appear in the Personal theme footer. The standard bottom bar (copyright · legal links · credit) was missing from all Personal footer layouts, so privacy/terms pages existed but were unreachable from the footer. Every footer variant now renders the shared bottom bar.
- Theme stylesheets update reliably after an upgrade. Tech, Entertainment and Pets linked their CSS without a version stamp, so browsers could keep serving a cached stylesheet indefinitely; the link is now stamped per file change.
No More Dead-End Update Banner on Centrally Managed Sites
Fixed
- The “Update available / Update Now” banner no longer appears on centrally managed sites. On these installations self-update is disabled and new versions are delivered by operator deployment, so the banner, the header update icon and the sidebar update badge were a dead end — clicking “Update Now” did nothing. They are now hidden whenever the install is centrally managed, matching the System Updates page which already showed “Central deployment ready”.
Professional Single-Bar Footer & Permanent CSS Cache Fix
Improved
- The footer bottom is now a single clean bar — copyright, legal links and the credit line share one row instead of a separate, duplicated legal strip below the copyright. Legal links used to render twice (in the footer columns and again in an injected bar); the redundant strip is removed across all themes.
Fixed
- Theme CSS no longer serves a stale cached copy after an update — the stylesheet is cache-busted by its file modification time, so visitors get the current styles without a hard refresh.
Canonical Cleanup: /page Redirects, Alias Consolidation & AdSense Readiness
Improved
- robots.txt is now AdSense- and Google-safe — the Googlebot group mirrors the base disallow rules (a crawler obeys only its most-specific group, so admin/api paths were previously left crawlable), and the AdSense crawler
Mediapartners-Googleis now explicitly allowed. - The site now serves a valid
ads.txtdeclaring the authorised AdSense publisher, resolving the “authorised sellers” warning that appears when the ad code is present but ads.txt is missing.
Fixed
- The duplicate
/page/{slug}URL now 301-redirects to the clean/{slug}and is no longer emitted in the sitemap — previously every static page was reachable at two URLs (a soft-duplicate that dilutes ranking signals and trips content-quality audits). The clean slug is now the single canonical address. - Legal, about and contact aliases consolidate onto one canonical URL with a 301 — language and spelling variants (e.g.
/privacy,/privacy-policy,/gizlilik) used to each return 200 with their own canonical, signalling duplicate pages. They now redirect to the page’s real address and the canonical tag matches the redirect target. - About/Contact pages that have no content now return 404 instead of an empty soft-200 — an alias with no template and no published page no longer renders a blank page whose canonical pointed at the homepage.
Image SEO: In-Content Images in Schema & Sitemap
Improved
- Article structured data now lists every image, not just the featured one — the Article/BlogPosting
imageproperty is now an array of ImageObjects covering the featured image plus the images embedded in the article body, each resolved with width, height and caption from the media library. This gives the in-content images a real shot at ranking in Google Images. - The image sitemap now includes in-content images — previously only the featured (and gallery) image of each post was submitted; the images inside the article body are now listed too, so Google can discover and index them.
- Fixed a silent bug where the featured image carried no dimensions in structured data — the media lookup queried a non-existent column, so width/height/caption were always dropped. Image objects now include their real dimensions.
SEO: Archive Canonicals, Unique Titles & Schema Fixes
Improved
- The homepage FAQ is now eligible for rich results — FAQPage structured data is emitted from the marketing site’s FAQ section.
Fixed
- Category, tag and author pages now point their canonical to themselves — in the travel theme these archive pages were inheriting the homepage’s canonical, title and description, which told search engines they were duplicates of the home page and effectively dropped them from the index. They now emit their own canonical URL, a unique title and description, and correct rel=prev/next for pagination.
- Every page now has a unique title and meta description — the recipes and finance themes were falling back to the site name on all pages (and recipes single posts had no meta description at all). Titles and descriptions now come from the page’s own content.
- The finance theme showed a hard-coded “FinancePro” heading regardless of the site’s real name, and rendered a second H1 on article pages — both fixed (real site name, single H1 per page). The news theme’s duplicate H1 was also resolved.
- News article structured data is now generated by the central engine — replacing an older version that referenced a missing logo file and could emit an invalid date, so news articles now carry correct Article/NewsArticle schema with the configured logo.
PageSpeed: Responsive Images, Accessibility & Security Headers
Security
- Content-Security-Policy now declares
script-srcand a Cross-Origin-Opener-Policy header is sent — script sources are restricted to the site itself plus the required Google advertising, analytics and font origins, closing the “missing script-src / COOP” findings without affecting ads.
Improved
- Images now download at the size they are displayed — the responsive image engine was emitting wrong width descriptors, so browsers fetched the 1600px version into ~800px slots. Descriptors now match the real variants (800/1600) and the size hint reflects the actual layout, cutting roughly 500 KiB from a typical page. Tip-card and recipe-card covers, which shipped a single full-size source, now serve responsive variants; continent illustrations were resized to their display size and the footer logo serves AVIF/WebP.
- Accessibility fixes across the travel theme and marketing site — section labels, hero chips and the newsletter button use an accent that meets WCAG AA contrast; decorative continent images no longer repeat adjacent link text; tip “Read” links carry the article title for screen readers; footer headings follow proper heading order.
- Smoother homepage animation — the step progress bar animates with a compositor-friendly transform instead of width, and the FAQ accordion no longer triggers a forced reflow on open.
Security Hardening from a Full Code Audit
Security
- Closed a SQL injection in the content scheduler — the status filter on the scheduler screen now uses a strict allow-list and a parameterized query, so a crafted filter value can no longer reach the database.
- The post listing helper now enforces a column allow-list — sort field, direction and limits are validated and type-cast before they touch the query, removing a latent injection path for themes and plugins.
- The automation webhook secret falls back to an installation-unique key — when no webhook secret is configured it is now derived from the per-install security key instead of a guessable time-based value.
Publisher Catalog & Backlink Opportunities, Verified for 2026
Improved
- The Backlink Opportunities module now lists real, verified programs — every niche grew from a couple of search shortcuts to 10-19 named opportunities checked live in 2026: Source of Sources and the relaunched free HARO, unlinked-mention reclamation, Lonely Planet Correspondents, BoardingArea, Matador Creators, foodgawker, mindbodygreen, the Plutus Awards, CryptoPanic, BlogPaws, Google/Bing/Apple business listings and more — each with priority, effort, and a concrete first step.
- The News Publishers catalog was re-verified for 2026 — Apple News (ANF, four countries), Flipboard (program closed; magazine + bookmarklet path documented), SmartNews and NewsBreak requirements updated; Bundle and SQUID added as open application channels; Pocket and Yandex Dzen removed.
Brand Consistency, robots.txt Compliance & Full Turkish Admin
Improved
- The Turkish admin is now fully Turkish — dozens of hardcoded English labels were localized across the post editor (Recipe/LocalBusiness schema fields), backups schedule, comment replies, duplicate finder, media upload, banner manager, theme customizer, user profiles and the traffic plugin menu (now "Hızlı İndeksleme", "Anında Bildirim", "RSS Beslemesi", "Backlink Fırsatları", "Tarayıcı Bildirimi"). The English admin remains fully English.
Fixed
- robots.txt now passes Bing validation — the non-standard
Host:directive (a legacy Yandex extension that Bing flags as an error) was removed from the generated robots.txt on every site. - The brand reads "jekcms" everywhere — a repo-wide sweep replaced every wrong-case variant across emails, feeds, installer screens, API docs, theme metadata, user-agent strings and comments. License-key format and code identifiers are untouched, so nothing breaks.
Proper-Noun Anchors in Internal Linking
Improved
- Auto internal linking now recognises single-word proper nouns — place, brand and topic names such as a city or a dish (capitalised, 5+ letters) can now become link anchors, not just multi-word phrases. Lowercase generic words stay excluded, so the links remain relevant. This noticeably improves internal linking on niche sites (travel, food, local guides) where titles are often a single proper noun.
Fixed
- Fixed the content-import wizard showing the "External authority links" label in English on a Turkish admin (it now follows the admin UI language).
Smarter Internal Linking & E-E-A-T Outbound Links
Added
- External authority links in the content generator — the content-queue import wizard can now request a set number (0–5) of in-content outbound links to high-authority, non-competitor sources. When enabled, the AI prompt weaves them naturally into the body on descriptive anchors (never a "Sources" list), strengthening E-E-A-T.
Improved
- Auto internal linking now waits for a real library — on a brand-new site there is nothing useful to link to, so auto-linking stays dormant until a configurable minimum number of published posts exists. The Auto Linker screen explains the threshold and shows current progress. As before, only published posts are link targets — queued/scheduled content is never linked.
Pinterest Production Setup Instructions
Improved
- Clearer Pinterest go-live instructions — after Pinterest grants Standard access, the setup guide now tells you to remove the existing connection and connect again in Production mode, instead of using plain Reconnect (which can silently stay in Sandbox).
Admin Customer Detail Fix
Fixed
- The customer detail screen in the admin panel opens reliably again — orders, licenses, invoices, support tickets and internal notes loaded with queries that did not match the production database, so the page returned a server error. Every section now reads the live schema correctly, and the customer create/edit forms save address details to the right fields.
Clearer Product Positioning Copy
Improved
- jekcms is now described the same way everywhere — a next-gen smart CMS that installs on any PHP + MySQL hosting. The vague "self-hosted" label (which could read as if hosting were included) and the inaccurate "plugin-free" label were removed from the homepage, the WordPress-alternative page, site metadata and structured data.
Category Archive Filter Fix
Fixed
- Category pages now show only their own posts — on themes that query archives by category ID, the post list ignored the category filter and showed every published post. The core query layer now accepts both category ID and slug, so every category archive lists exactly the posts that belong to it.
Invoicing, Customer Portal Language & Support System
Added
- Real PDF invoices — admins can now generate an invoice for any order and email it to the customer, and customers can download a proper PDF from their portal. Invoices render with full Turkish characters and work on any shared host (no server extensions required).
- Turkish-law VAT handling — domestic sales carry 20% VAT (KDV); sales to customers outside Turkey are treated as a VAT-exempt service export and the exemption note is printed on the invoice automatically.
- Company billing settings — a new admin screen for your seller details (company title, tax office, tax number, address, IBAN) that appear on every generated invoice.
- Billing profile for customers — buyers can now enter their tax number, address and country so their invoices are complete and the correct VAT rule is applied.
Improved
- Customer portal fully bilingual — every page of the customer portal (orders, licenses, invoices, support, profile, sign-in/up) now follows the selected language, so Turkish users no longer see stray English labels.
Fixed
- Support tickets hardened — fixed an issue where a second ticket from a customer could fail, added missing attachment storage, corrected priority handling, and customers now get an email when staff reply (and staff get one on new tickets).
- Portal pages that referenced old data fields now load correctly — order detail, new-ticket and invoice pages were updated to the live data model.
- Two admin tools gained CSRF protection and several blog/theme pages had social-share image and metadata issues corrected for better SEO.
Automatic Internal Links on Publish
Added
- New posts get internal links automatically when published — the moment a post goes live (manual publish, scheduled date, or content queue), 3-5 contextual links to your existing published posts are added inside it, so you no longer have to run the linker site by site. Only published posts are used as link targets; queued or scheduled items are never linked.
Security Hardening Pass: Payment, CSRF, Uploads, SSRF, API
Fixed
- Marketing homepage hardening guard aligned — the direct-access guard in the constants file only accepted one context flag, while the marketing site and update-server bootstrap use different ones; the guard now matches the loader so the public site renders normally
- Payment webhook is now fail-closed — the iyzico webhook accepted an event when no signature header was present; it now rejects any unsigned or invalid-signature webhook (matching the Stripe gateway), closing an unauthenticated path to marking orders paid
- One-click (GET) CSRF on admin actions closed — central CSRF enforcement now also covers authenticated GET action handlers (delete/toggle/activate), so a forged link or image tag can no longer trigger destructive admin actions
- API input is column-whitelisted — the categories/tags update endpoints now accept only known fields, removing an identifier-injection vector from attacker-controlled JSON keys
- SVG uploads disabled — SVG is no longer an allowed upload type (it can carry scripts and was served inline), eliminating a stored-XSS vector; standard image formats are unaffected
- SSRF guards added to server-side fetchers — bulk-import and remote content-image fetching now validate the URL against private/loopback/metadata ranges and no longer follow redirects
- Customer portal forms fixed — the CSRF token field referenced a non-existent method (so it rendered empty); corrected to the proper token, and a reflected status parameter in pagination links is now URL-encoded
- Removed a temporary password-reset utility from the web root that was reachable without authentication
In-Article Images Now Match on Items That Already Have a Pinterest Slot
Fixed
- Image matching no longer skips the in-article photos when an item only had a Pinterest slot — after a re-import added a Pinterest slot to an item that had no content image plan, the matcher mistook that lone Pinterest slot for a full plan and never built one from the article's headings, so the cover and pin matched but the in-article images (img02, img03…) stayed in temp. The matcher now ignores the Pinterest slot when deciding whether a content plan exists, builds the heading-based plan when needed, and preserves the existing Pinterest slot
Re-Importing JSON Now Updates Existing Queue Items (Pinterest + Prompts)
Improved
- Re-importing a JSON now enriches items already in the queue instead of skipping them — previously a duplicate (same source id) was skipped entirely, so content imported before a feature existed could never gain it. Now a re-import fills in any empty image prompts from the new file and adds the Pinterest brief (hook, title, description, tags, image prompt) and pin slot — while preserving already-matched image URLs, the schedule, and any manual edits. The import result reports how many items were updated
Content Queue Image Column Now Counts the Matched Cover
Fixed
- The image-status column no longer shows “—” when the cover is actually matched — items imported without a full image plan store their cover in the
featured_imagecolumn rather than the plan, so the queue list read “no images” even though the cover thumbnail was clearly set (and the image dialog said “1/1 matched”). The column now counts a column-matched cover too, so the list and the dialog agree
End-to-End Pinterest Pins: Custom Copy, Per-Category Boards, and Baked Designs
Added
- Per-article Pinterest copy now publishes — a pin's title and description come from the imported brief (
_pinterest_title/_pinterest_description) instead of the generic post title and template, so each pin reads the way it was written - Pins route to the matching board automatically — a pin is posted to the board whose name matches the article's category (with the connected account's default board as fallback), so a multi-topic site keeps its Pinterest boards organized with no manual selection
- Designed-in-full pins are supported — when the image already bakes in its own headline and domain bar, the CMS skips its own stamp (
stamp:false), so there is never a double bar
Improved
- The AI content wizard now writes premium pin briefs — when Pinterest is enabled, it produces an editorial brief (short hook, ≤100-char title, ≤500-char keyword-rich caption, tags, the
<slug>-pinterestfilename, and a full split-layout image prompt with the site domain baked in) ready for image generation
Hands-Off Pinterest Pins and Bulk Image Matching in the Content Queue
Added
- Pinterest pins now match automatically — drop a
<slug>-pinterest.jpginto the uploadstempfolder alongside your article images and the queue picks it up on the next “Match Images” run, stamps your site’s domain bar onto it, and attaches it to the post. No more uploading pins one at a time - Pinterest captions travel with the content — the import schema now carries a pin hook (the headline on the image), a meta description (the caption shown under the pin) and tags, and writes them to the published post so a Pinterest publisher can fill those fields without guesswork
- An image-status column in the queue list — every row shows how many article images are matched (e.g. 2/3) and whether a Pinterest pin is present and matched, at a glance
Improved
- The content queue list was redesigned — the action buttons (view, images, publish, delete) are now a compact, single-row icon group instead of a stack that overflowed the column, and the new image-status chips are monochrome and uncluttered
- Image matching now shows a real progress bar — a clean progress window reports matched count, percentage and a live log as it processes the temp folder in batches, instead of a number ticking in a button
- Content Studio is now the calm starting point for publishing — the dashboard gathers the publishing calendar, queue health, next action and entry points for AI draft, planned batches and content packs into one compact two-language screen
- Imports are more forgiving — image entries that use
role/promptinstead ofslot/image_promptare now understood, so content generated by different tools imports correctly without hand-editing the JSON
Admin Sessions No Longer Drop After a Few Hours Idle
Fixed
- You stay signed in until you actually sign out — even with the session cookie and garbage-collection lifetimes already raised to 30 days, an inactivity check was still destroying the session after ~2 hours of no activity (its threshold constant was undefined, so it fell back to a 2-hour default). The idle limit now matches the 30-day session lifetime, so leaving the dashboard open and coming back hours later keeps you logged in
Changed files (2)
native/includes/Session.php
—
checkRegenerate idle-timeout fallback 7200s → SESSION_LIFETIME (30 gün); 15 site + marketing'e deploy
includes/Session.php (marketing)
—
headers-sent fatal throw → graceful (fail-closed) — tutarlılık
Admin Language Consistency — Plugin Text Now Follows TR/EN
Fixed
- The newer plugins no longer leak the wrong language in the admin — Google Console, Traffic & Distribution, and parts of Social Publishing hardcoded their interface text in a single language (mostly Turkish), so it showed Turkish in the English admin (and vice-versa). All of these are now bilingual and follow the admin language setting
- Google Console’s plugin-list description is now bilingual — it was missing from the localized description map and fell back to the Turkish manifest text
- The Two-Factor Authentication card in Settings → Security is now bilingual — its labels, steps, badges and buttons were Turkish-only
- Social Publishing platform help/how-to, cost and warning texts are now bilingual for all platforms — these registry strings rendered in a single language regardless of admin locale
Changed files (4)
native/includes/helpers.php
—
global jek_t($tr,$en) yardımcısı (her zaman yüklü; eklenti admin sayfaları için)
native/admin/plugins/jek-google/index.php + jek-traffic/index.php
—
~100 sabit metin jek_t ile iki dilli
native/plugins/jek-social/* (connections + platforms.php + 15 adapter)
—
js_t kullanmayan sızıntılar + 21 platform howto_en
native/admin/plugins.php + settings.php
—
jek-google açıklama haritası; 2FA kartı jek_t
Performance (N+1) and Security/SEO/Plugin Hardening
Improved
- List pages issue far fewer database queries — loading a post list with relations ran 6 queries per post (author, categories, tags, meta, SEO, comments); a 12-post page hit ~72 queries. It now batches all of them into 6 total via IN() lookups
- Image dimension lookups no longer scan the media table on every render — the per-image width/height query used a leading-wildcard LIKE (full-table scan per image); it now uses exact-path matching plus a per-request cache
- Saving a post no longer wipes the entire object cache — cache invalidation is now targeted to the affected namespaces instead of a global flush
- Faster LCP on article pages — the hero/featured image on travel and health single-post templates now carries fetchpriority="high"
Fixed
- Client IP detection can no longer be spoofed to evade blocks — forwarded headers are now accepted only when they carry a public IP, so an attacker cannot inject an internal/loopback address to bypass IP blocking or frame another IP
- Redirect Manager blocks dangerous redirect schemes — javascript:/data:/vbscript: targets are refused at emit time
- Admin error messages no longer leak internals — Security Center and Redirect Manager now show a generic message and log the detail
- Cross-domain Sitemap line removed from the shipped robots.txt fallback — robots is served dynamically with the site’s own domain; the static fallback no longer carries a hardcoded foreign domain
- Google Console snippets can no longer double-inject — the head injector is guarded against firing on both head hooks
- Removed the misleading dead Pinterest-template dropdown in Social Publishing settings (it was never read)
Changed files (6)
native/classes/Post.php
—
loadRelationsForList() batch (N+1); clearCaches hedefli purge
native/includes/helpers.php
—
jek_img_optimize exact-path + request-cache
native/includes/Security.php
—
getClientIp forwarded header → yalnız public IP
native/classes/RedirectManager.php
—
emit şema güvenliği
native/admin/{security-center,redirects}.php
—
generic hata mesajı + error_log
native/robots.txt + themes/{travel,health}/.../single.php + jek-google + jek-social
—
robots domain; LCP fetchpriority; çift-inject guard; ölü dropdown
Deep Audit Fixes — CSRF Enforcement, Cache, SEO & Systems
Fixed
- CSRF protection is now actually enforced across the admin — the validation helper returned a boolean that nearly every admin/AJAX endpoint discarded, so forged cross-site requests were silently accepted. Validation now blocks state-changing authenticated requests centrally (clean 419, JSON for AJAX) without affecting public forms or page rendering
- "Clear Cache" buttons work again — they called a method that did not exist and fataled (purging nothing). Added the missing prefix-delete method and hardened the handler
- Sitemap index no longer miscounts pages as posts — the posts-sitemap presence/lastmod now filter on post type, fixing false "empty posts sitemap" and wrong freshness signals
- Update manifest hash guard is no longer a no-op — the signed update manifest now exposes the core package hash under the field the client checks
- Social Publishing "Hold for approval" no longer silently stops publishing — held items now appear in the queue with one-click Approve / Approve-All / Cancel actions
- Traffic & Distribution now verifies TLS — IndexNow/WebSub/Web-Push calls had certificate verification disabled; enabled to prevent MITM
Changed files (5)
native/includes/Security.php
—
validateCsrfToken: başarısızlıkta authed+POST bağlamında merkezî 419 enforce (no-op çağıran deseni topluca kapanır)
native/includes/Cache.php + admin/ajax/clear-cache.php
—
deleteByPrefix() eklendi; catch \Throwable
native/classes/Sitemap.php
—
posts index sayım/lastmod AND type='post'
native/plugins/jek-traffic/* + jek-social/queue.php
—
TLS verify açıldı; hold→approve/cancel UI
api/v1/updates/manifest.php
—
core entry hash = file_hash normalize
Security Center Now Matches the Admin Design System
Fixed
- The Security Center looked disconnected from the rest of the admin — it shipped its own stylesheet with hardcoded light-mode colors (white cards, grey borders) instead of the admin’s shared design tokens, so it ignored dark mode and its tabs/cards/tables didn’t match the other panels. Every color now uses the admin theme variables, so it adapts to dark/light and looks like one consistent product. Status indicators keep a subtle tinted badge instead of solid blocks, and the brand wordmark was corrected to lowercase
Changed files (1)
native/admin/security-center.php
—
tüm hardcoded renkler → admin CSS değişkenleri (--bg-secondary/--border-color/--text-* /--radius-*); status pill soft-tint; mavi rol etiketi nötrlendi; "jekcms" → "jekcms"
Strip Byte-Order Marks From Core Files — Fixes Admin Layout & AJAX
Fixed
- Admin pages no longer render with broken styling — several core PHP files (bootstrap, constants, helpers, theme functions) carried an invisible UTF-8 byte-order mark (BOM) before their opening tag. That BOM was emitted before the document’s doctype, which forced browsers into "quirks mode" and broke list/table layouts across the admin. The BOM has been stripped from every PHP file fleet-wide
- AJAX actions no longer fail with a JSON parse error — the same BOM was prepended to JSON responses (e.g. "Match Images"), so the browser threw
Unexpected token … is not valid JSON. With the BOM removed, responses are clean JSON again
Changed files (1)
140 .php (native + 15 site)
—
açılış etiketinden önceki UTF-8 BOM (EF BB BF) kaldırıldı; en kritik: includes/bootstrap.php, config/constants.php, includes/helpers.php (her istekte yüklenir)
Match Images — Build Article Image Plans From Your Generated Files
Fixed
- Bulk image matching now actually imports your files — the media importer used PHP’s upload-only move function, which always fails for files already on the server (e.g. images you place in the uploads/temp folder). A server-side "sideload" path now imports those files correctly, and a valid uploader id is always supplied so the database insert no longer fails outside a browser session
- "Match Images" understands multi-image articles — drop files named
{slug}-img01..04in the temp folder and the matcher attaches them as the article’s image plan: image 01 becomes the featured image and the rest are placed in the body after the article’s headings. When the article already has a plan, empty slots are filled in order - Admin thumbnails resolve relative image paths — queue list and calendar previews now prefix the uploads URL for plan images stored as relative paths, so the thumbnail shows instead of a broken image
Changed files (2)
native/classes/Media.php
—
upload(): options.sideload → move_uploaded_file yerine rename/copy (sunucu-içi dosya import)
native/classes/ContentQueue.php
—
matchFeaturedImages: {slug}-imgNN → görsel planı kur (img01 featured, imgK in-content H2[K-1]); sideload+explicit user_id; resolveThumb göreli url UPLOADS_URL öneki; parça limiti
Match Images — In-Memory Matching, Seconds Instead of Minutes
Fixed
- "Match Images" now finishes in seconds on large queues — the previous version ran two full-table
LIKE '%slug%'scans per item and re-normalized every media filename for every item, which on a queue of hundreds against thousands of media files took minutes and hit a server gateway timeout (the generic "server error"). The media library is now normalized once and all items are matched in memory — no per-item database queries, no repeated work
Changed files (1)
native/classes/ContentQueue.php
—
matchFeaturedImages ADIM 2: öğe-başına SQL LIKE + medya yeniden-normalize kaldırıldı → medya bir kez normalize, hepsi bellekte eşleşir (O(medya+öğe))
Match Images No Longer Times Out on Large Queues
Fixed
- "Match Images" no longer fails with a generic server error on large queues — with hundreds of queued items and thousands of media files, the slug-to-media scan could exceed PHP’s execution limit and return a raw 500. It now skips items that already have an image attached through the image-matching flow (so nothing is re-scanned needlessly), and the time limit is raised for the bulk pass
- Queue actions now always return a readable error — any failure in a content-queue action is converted to a proper JSON message instead of a raw 500 page, so the browser shows the real reason rather than a generic "server error"
Changed files (2)
native/classes/ContentQueue.php
—
matchFeaturedImages: set_time_limit(180) + extra_json image-plan’ında görseli olan öğeleri atla (compass büyük kuyruk timeout’u)
native/admin/ajax/queue-action.php
—
catch Exception→\Throwable: fatal/timeout ham 500 yerine JSON hata; error_log
Reliable Manual Publishing — No More "Spinning then Failed"
Fixed
- Publishing no longer crashes when a session cannot start — if output had already begun (e.g. a slow image URL emitting a warning), the session layer threw a fatal "headers already sent" error that aborted the publish even though the post itself was fine. The session now degrades gracefully (logs and continues, fail-closed) instead of crashing background work
- A dead or slow featured-image URL can’t freeze the publish anymore — image download now has an 8-second connect and 25-second total cap (was 60s with no connect timeout), the single biggest cause of the publish button spinning for up to a minute. A failed download simply falls back to publishing without that image
- Already-published posts are no longer mislabeled "failed" — if a post was created but a later side-step (cache, session, search-engine ping) errored, the queue now finds the post by slug as well as title and correctly marks it completed
- The optional in-content image localization can no longer abort a publish — the whole step is now isolated; any error there is skipped and the post still goes live
Changed files (3)
native/includes/Session.php
—
start(): headers_sent → fatal throw yerine error_log + return false (fail-closed); byte-güvenli hedefli replace ile 15 siteye (compassdraft divergent dosyası korundu)
native/classes/ContentQueue.php
—
downloadFeaturedImage CONNECTTIMEOUT 8s + TIMEOUT 60→25s; publishItem catch post’u slug ile de bulur; 4b görsel-yerelleştirme tümüyle try/catch izole
native/admin/content-queue.php
—
publish butonu net "işleniyor" + başarısızlıkta/timeout’ta otomatik refresh (donuk buton + eski satır kalmaz)
Content Queue — Recover Stuck Posts & Fix Missing Thumbnails
Fixed
- Scheduled posts can no longer vanish silently — if publishing was interrupted by a fatal error mid-run, the item used to stay frozen in a "processing" state that appeared in no queue tab and was never retried. Publishing now catches every failure type and the auto-publisher reclaims any item stuck longer than 15 minutes, so the backlog clears on the next visit
- Failed and stuck items are now visible and recoverable — a new "Failed" tab surfaces every problem item (failed or processing) with a one-click retry, instead of leaving them invisible while still showing on the calendar
- Featured thumbnails show in the admin again — completed posts whose image was attached through the image-matching flow stored the picture in the rich payload, not the legacy column, so the queue list and calendar showed an empty box even though the live post had the image. The admin now reads the matched image as a fallback
- Calendar hover preview image fixed — the tooltip was building the image path the wrong way around (a local path treated as an external URL and vice-versa), so the preview was always broken. It now uses the same single image resolver as the rest of the queue
Changed files (2)
native/classes/ContentQueue.php
—
resolveThumb() tek-kaynak küçük-resim çözücü (extra_json featured slot fallback); publishItem catch Exception→\Throwable; publishDueItems 15 dk takılı processing kurtarma; getItems status_in filtresi
native/admin/content-queue.php
—
takvim+liste resolveThumb kullanır (ters görsel mantığı düzeltildi); "Başarısız" sekmesi (failed+processing) tek-tık yeniden dene; 15 siteye yayıldı (md5+grep-assert)
Security Hardening — Per-Install Unique Keys
Improved
- Every installation now generates its own unique security keys — authentication, session and JWT secrets are created with cryptographic randomness on first run and stored outside the distributed package. No two installs share secrets, so a token issued on one site is meaningless on another
- Install-time integrity manifest — the wizard now signs the tamper-detection manifest with the install’s own key at the end of setup, so a fresh installation never shows a false "integrity" warning
Changed files (3)
native/config/environment.php
—
sabit anahtarlar kaldırıldı; config/keys.php (gitignore) ilk yüklemede random_bytes ile üretilir + son-çare host-özgü fallback
native/jekcms-install.php
—
kurulum sonunda IntegrityGuard::generateManifest() — kurulumun kendi anahtarıyla imzalı manifest
native/classes/IntegrityGuard.php
—
protectedFiles() tek-kaynak liste (installer + script ortak); .gitignore: **/config/keys.php
Migration Polish — Author Links Show Everywhere, Bulletproof .htaccess
Improved
- The installer now guarantees jekcms’ own .htaccess is used — on most WordPress sites the .htaccess is stuffed with SEO/sitemap-plugin rewrite rules that can break clean URLs. The installer detects whether jekcms’ signature is present; if not, it backs the old file up to
.htaccess.wp-backupand writes the canonical jekcms .htaccess (read straight from the package, so no drift). Routing is correct even if the host locked the file or the archive lacked it
Fixed
- Migrated author social links now actually appear — several themes (Personal, Trends, Lifestyle, Pets, Finance) were reading the old column names and silently showed nothing. They now read the real
social_x / social_facebook / social_instagram / social_linkedin / websitefields, so the profiles imported in 2.16.0 are visible on author and article pages
Changed files (2)
native/themes/{personal,trends,lifestyle,pets,finance}/...
—
yazar sosyal/website okuma gerçek kolon adlarına çekildi (8 dosya); 14 siteye + _template’e yayıldı (md5+grep-assert)
native/jekcms-install.php
—
jek_enforce_htaccess(): imza kontrolü + WP .htaccess yedekle + kanonik jekcms .htaccess zorla yaz
WordPress Migration — Richer, Safer, Cleaner Imports
Added
- Author profiles now come over in full — biography, website, social links (X, Facebook, Instagram, YouTube, Pinterest, LinkedIn) and a Gravatar-based avatar, instead of just the name. Existing authors are enriched only where fields are empty (never overwritten)
Improved
- Re-running a migration no longer creates duplicates — posts already imported (matched by their original slug) are skipped, so an interrupted migration can be safely resumed
- Empty categories are cleaned up — WordPress’ default "Uncategorized" and any category with no posts are removed after import, so your category list stays meaningful
- A clear warning before deleting old files — if you migrated without downloading images (so your content still points at the old site), the cleanup step now warns that deleting the old files would break those images
Changed files (3)
native/database/schema.sql + migrations/005_user_social_website.sql
—
users: website + social_* kolonları (kanonik şema + idempotent migration)
native/admin/includes/import-core.php
—
tam yazar profili + jek_normalize_social + skipExisting + uncategorized atlama; 15 siteye yayıldı
native/jekcms-install.php
—
WP usermeta (bio/sosyal) + user_url + Gravatar SQL; boş kategori temizleme; görsel uyarısı (i18n)
Installer Renamed to jekcms-install.php (avoids WordPress clash)
Improved
- The setup file is now
jekcms-install.phpinstead of the genericinstall.php. A leftover WordPressinstall.phpon the server can no longer be confused with — or shadow — the jekcms installer. All "not installed yet" redirects and robots rules were updated to match
Setup Wizard — Clean WordPress Switchover (Safe Cleanup + Logo)
Added
- The wizard now finishes a WordPress migration cleanly — after importing your content, a Cleanup step lists exactly which old WordPress files will be removed and asks you to confirm (with a clear "this cannot be undone" warning). It then deletes them with a live progress bar, and optionally drops the old WordPress database too
- Safe by design — only genuine WordPress files are removed (a strict allow-list:
wp-admin,wp-includes,wp-content,wp-*.php,xmlrpc.php…). jekcms’ own files are never touched — even where names overlap (e.g. license/readme). The wizard also refuses to drop jekcms’ own database - Logo support — your site logo is pulled automatically from WordPress when migrating, or you can upload one (PNG/SVG/JPG/WebP). For a fresh install, just upload your logo. It’s saved to your site settings
Setup Wizard — English & Turkish, English by Default
Added
- The setup wizard now speaks English and Turkish, defaulting to English. A language toggle (EN/TR) sits next to the theme switch in the top bar, and your choice is remembered. Every label, hint, button, alert and progress message is fully translated
Setup Wizard — A Polished, Modern First Impression
Improved
- The setup wizard was redesigned from the ground up — a glassy, animated interface with a numbered progress tracker, the jekcms wordmark logo, soft animated background auras, smooth card transitions and a live progress bar. It now supports both dark and light themes with a one-tap toggle (your choice is remembered)
- The database step is much clearer — it now explicitly states that this is a new, empty database for jekcms, with a prominent note for WordPress users that it is not their existing WordPress database (that comes in the next step). No more mixing them up
Setup Wizard — WordPress Migration Verified End-to-End
Fixed
- The WordPress import step now connects to the correct database. Three real-world bugs found during a live migration test (a 114-post WordPress site) were fixed: the framework is loaded in global scope so the site's configuration is read correctly, database seeding no longer collides with open result cursors, and AJAX responses are now always clean JSON (no stray warnings)
New Setup Wizard — Install Fresh or Migrate From WordPress in Minutes
Added
- A modern, guided installer (install.php) — drop it next to the jekcms archive in your site root, open it in a browser, and it walks you through everything: a system requirements check, database connection (with step-by-step phpMyAdmin guidance and auto-create if the database is missing), site details, theme choice and admin account. It then unpacks the files, builds the database, applies your settings automatically, and cleans itself up afterwards
- WordPress migration built into the wizard — choose "Migrate from WordPress", enter your WordPress database details, and the installer previews how many posts, pages, categories and comments it found, pre-fills your site name and tagline from WordPress, then imports content, downloads & converts images to AVIF, and brings over approved comments. At the end it checks for leftover WordPress files and warns you to remove them to avoid conflicts
- Finishes with clear next steps — two cards to open the Admin Panel or view your site, with your details already filled in
Account & License Security Hardening
Fixed
- License site-limit race condition closed — registering domains for a license is now serialized (row-locked), so two simultaneous requests can no longer slip past your plan's site limit
- Logout now fully ends the session — the session is destroyed and its cookie cleared (previously only the user id was removed), removing a session-fixation surface
Reliability Audit — Newsletter Cron, Scheduled-Posts Link & Contact Inbox Fixed
Improved
- Trimmed remaining developer-oriented notes across the admin (technical jargon, internal details) down to plain, end-user labels
Fixed
- Newsletter sending cron was broken across all sites (a comment line accidentally ended early and broke the file). Scheduled campaigns now send again
- Scheduled-posts link in the top bar led nowhere — it now opens the scheduled posts list correctly
- Contact-form inbox could load the wrong site's configuration (a hard-coded path) — now resolved per-site
Google Console — One Clear "Scan" Button
Improved
- Index Coverage now has a single Scan button (auto-completes the whole site; becomes Re-scan when done) instead of three overlapping controls. Each card carries one short line explaining what it does
Google Console — Cleaner, Less Cluttered Copy
Improved
- Trimmed long explanatory notes in the Google Console panel down to short, action-focused labels — less clutter, faster to scan
Google Console — Cleaner Search Console Flow + Responsible Bulk Indexing
Added
- Bulk "Submit to Index" — notify Google about your not-indexed pages in one click. Built responsibly: a daily cap (well under quota), the same URL is never re-sent within 14 days, and only genuinely not-indexed pages qualify (404 / noindex / redirects are skipped). A clear notice explains that Google officially supports the Indexing API only for job-posting / livestream pages
Improved
- Search Console tab decluttered — the redundant single-URL inspector was removed (Index Coverage already shows every URL's status). One clear flow: coverage summary → problem list → indexing actions
- Auto-scan reliability fixed — coverage now scans in short, fast batches with automatic retry, so it no longer trips the "connection error" on stricter hosts
Changed files (1)
native/admin/plugins/jek-google/index.php
—
Tek-URL denetleyici kaldırıldı; coverage_scan_ajax kısa parti+retry; idx_submit (günlük cap + 14g de-dup + jg_idx_eligible) + politika uyarısı; 15 siteye yayıldı
Google Console — One-Click Auto Scan for Index Coverage
Improved
- Index Coverage now scans automatically — one "Auto scan" click runs the whole site in the background, batch by batch, with a live X/Y checked… progress counter, instead of clicking "Next batch" a dozen times. Google's URL Inspection API is rate-limited and ~one URL takes a few seconds, so the panel paces itself and resumes until every URL is checked
- Resilient & cached — each batch is time-guarded so it never hangs the page, results are cached 24h, and a single-batch manual button plus Reset remain for fine control
Changed files (1)
native/admin/plugins/jek-google/index.php
—
coverage_scan_ajax (JSON) + JS otomatik döngü + ilerleme; 15 siteye yayıldı
Google Console — Pick Your Analytics Property From a List (No More ID Typing)
Improved
- GA4 is now a dropdown, not a number to copy — Settings → Auto-discovery lists the Analytics accounts and properties your Google account can access, so you just pick yours instead of hunting for the numeric Property ID. Matches the existing one-click selection for Search Console site and AdSense account. Manual entry stays as a fallback
- Index Coverage is clearer before scanning — instead of a confusing row of zeros, the card now shows a clear "ready to scan" prompt, and explains that its totals won't exactly match Search Console's "Page indexing" numbers (Google also counts category/tag/system and old URLs; the panel checks your published content)
Changed files (2)
native/plugins/jek-google/GoogleClient.php
—
ga4AccountSummaries() — Analytics Admin API ile hesap/property keşfi
native/admin/plugins/jek-google/index.php
—
GA4 property dropdown + pick_ga4; kapsam kartı tarama-öncesi durumu + GSC-fark notu; 15 siteye yayıldı
Google Console — See Which Pages Google Isn't Indexing
Added
- Index Coverage in the Search Console tab — a new card scans your site's URLs and groups them by Google's indexing status: Indexed, Not indexed (crawled/discovered but not added, unknown to Google) and Error (404, server error, blocked by robots). You finally see your indexing problems in one list instead of checking URLs one by one
- Quota-friendly, incremental scan — built on Google's URL Inspection API (the only API that exposes per-URL index status). Each click inspects ~10 URLs, results are cached 24h, and a wall-clock guard keeps it responsive — large sites finish in a few clicks. Problem URLs link straight to Submit to Index
Changed files (1)
native/admin/plugins/jek-google/index.php
—
Dizine Ekleme Kapsamı kartı + coverage_scan/coverage_reset + jg_site_urls/jg_cov_classify; 15 siteye yayıldı
Google Console UI — Now Fully Native to Your Admin Theme
Improved
- The Google Console panel was rebuilt on the admin design system — it now follows your dark/light theme, uses the same cards, pill buttons, segmented date controls and typography as the rest of the admin instead of a separate light-only look. A more professional, cohesive dashboard
- Cleaner data presentation — connection status shown as a clear pill badge, neutral monochrome trend charts (no decorative color noise), refined KPI cards, tables and diagnostics that read at a glance
Changed files (1)
native/admin/plugins/jek-google/index.php
—
CSS değişkenleri (--bg-card/--text-*/--radius-*) ile yeniden yazıldı; hardcoded Google-mavisi/beyaz tema kaldırıldı; 15 siteye yayıldı
Google Console Now Ships With Every Theme
Added
- The Google Console plugin is now bundled with every jekcms theme — Search Console performance, GA4 traffic, AdSense earnings and frontend GA4/GTM/AdSense snippet injection in one panel, behind a single Google sign-in. Previously available on one theme, now on all of them
- One-click connect, encrypted tokens — OAuth refresh/access tokens are stored encrypted; the connection survives even if your admin session drops mid-flow (server-side one-time state, 10-min window)
Changed files (2)
native/plugins/jek-google + native/admin/plugins/jek-google
—
compassdraft'tan native kanonik kaynağa terfi (tek kaynak)
tools/jek-google-sync.php
—
Yeni: native → 14 site + _template idempotent yayılım (md5 doğrulamalı, route yaması yok — OAuth callback fiziksel dosya)
One Universal Key, Multiple Sites — Manage Domains From Your Dashboard
Added
- Site management in your account — one license = one key + N site slots. Register each site's domain (e.g.
siteadi.com) under My Licenses, up to your plan's limit. Adding a site beyond the limit is blocked - Strict activation — a site only activates if its domain is pre-registered for that license; an unregistered domain is rejected with a clear message. You control exactly which sites use your license
- Upgrade path — move to a higher plan for more sites; your key stays the same
Changed files (2)
customer/licenses.php
—
Yeniden yazıldı: customer_email + license_domains; domain ekle/çıkar + limit + format
classes/LicenseManager.php
—
registerDomain/unregisterDomain/isValidDomain + strict activate() + ensureLicensesSchema()
Simpler Pricing — Same Everything, Only Site Count Differs
Improved
- Every plan now includes the exact same features and support — all 14+ themes, all SEO & automation tools, priority support, lifetime updates. The only difference between plans is how many sites you can run
- Clear tiers: Personal $29 / 1 site · Standard $79 / 3 · Professional $149 / 10 · Unlimited $349 / ∞. The confusing dual "Agency $299 / Enterprise $599" tiers were replaced by one Unlimited plan
Fixed
- Pricing data was inconsistent across the site, checkout and license server (Agency was 50 domains in one place, unlimited in another, $299 vs $599). Now a single consistent model end-to-end
Changed files (3)
pricing.php
—
Tek-fark-site-sayısı modeli + karşılaştırma matrisi sadeleştirildi
classes/Payment/PaymentManager.php + classes/LicenseManager.php
—
Sınırsız $349 / sınırsız domain / ömür boyu — hizalandı
api/license/{activate,deactivate,info}.php
—
Rate-limit eklendi (bağlantı sertleştirme)
New Plugin: Google Console (Analytics + Search Console + AdSense)
Added
- Google Console plugin — Search Console (clicks/impressions/queries, URL Inspection, one-click index submit), Analytics GA4 (traffic, channels) and AdSense (earnings) in one dashboard, via a single Google OAuth connection
- Snippet injection — GA4, Tag Manager and AdSense tags injected on the frontend, managed from the admin (no code editing)
- Robust by design — encrypted tokens, response caching for quotas, per-API diagnostics, and clear "reconnect" handling
Changed files (1)
plugins/jek-google + admin/plugins/jek-google
—
Yeni eklenti (manifest, OAuth client, dashboard hub, snippet hook)
Infrastructure Hardening — Security, Performance & SEO
Security
- Payment webhooks now fail closed (Stripe + iyzico): an unsigned/forged webhook can no longer mark an order paid, and the paid amount is verified against the order total
- Admin payment/customer/order pages now require admin role; unauthenticated maintenance scripts locked to CLI; session cookie set to
SameSite=Lax(fixes being logged out when returning from external links)
Improved
- Faster page loads — plugin scan cached per request, composite DB indexes, and N+1 query batching on list pages. SEO: correct archive titles, paginated-page noindex, dynamic html lang
Fixed
- Analytics plugin (ZeroTrack) and Smart Backup now create their database tables on first use, fixing a 404/500 on fresh installs
Hero Trimmed to a Hook + Features Grid Expanded
Improved
- Hero copy trimmed to a hook — the 8-vendor laundry list ("Analytics (Plausible). SEO schema (Rank Math)...") was too long. Replaced with a sharp hook: "Not plugins. Core." + a single subtitle quantifying the savings (20+ features, ~$624/yr). Same message, half the words, double the impact
- Features grid expanded from 14 to 20 cards — added 6 cards for built-in capabilities that were previously hidden: Social Publisher (Buffer/Hootsuite — 18+ networks auto-publish), Instant Indexer (IndexMeNow — IndexNow + WebSub + Web Push), Newsletter (Mailchimp — campaigns + subscribers + digest), AI Image Generator (Canva — Gemini-driven post covers), AI Bulk Publisher (ContentBot — n8n + bulk queue), and they collectively replace another ~$390/yr in subscriptions
Changed files (2)
marketing-includes/header.php
—
hero_title (EN+TR) "Not plugins. Core." / "Eklenti değil. Çekirdek." + subtitle 20+ features hook
features.php
—
+6 grid kartı (EN+TR): Social Publisher, Instant Indexer, Newsletter, AI Image Generator, AI Bulk Publisher
Hero Copy Forced from Code — DB Override Bypass
Fixed
- Hero subtitle was empty on production — load_marketing_translations() pulls hero_subtitle from the marketing_translations table when present, which still held a stale pre-v2.8.1 entry on production (the 8-vendor copy never displayed). Fix: after merging defaults+DB layers, header.php now force-overrides hero_title and hero_subtitle from the code defaults. Marketing-investment copy is a release-time concern, not a CMS admin concern
Changed files (1)
marketing-includes/header.php
—
Force-override hero_title + hero_subtitle from defaults after load_marketing_translations()
Homepage Hero — The $624+/yr Built-In Story
Improved
- Hero subtitle rewritten — instead of the abstract "built-in SEO, internal linking, AVIF media" laundry list, the hero now names the 8 specific WordPress plugins jekcms replaces (Plausible, Rank Math, UpdraftPlus, Wordfence, WP 2FA, Redirection, Smush, WP Rocket) and quantifies the savings (~$624/yr in subscriptions). Concrete vendor-named replacements convert better than generic feature lists
- EN + TR copy aligned — both languages use the same 8 vendor names + dollar figure for consistent messaging across markets
Changed files (1)
marketing-includes/header.php
—
hero_subtitle (EN+TR) — named-vendor replacement story + savings figure
Performance Suite — Redirect Manager + Image Studio + Critical CSS, Built-In
Added
- Redirect Manager (NEW) — admin/redirects.php with full CRUD UI for 301/302/307/308/410 redirects. Bootstrap-level lookup runs BEFORE the router so redirects are zero-latency. Hit counter + last-hit timestamp expose which URLs people actually follow. Replaces Yoast Premium Redirect ($99/yr)
- 404 logger + Orphan 404s tab — every 404 hit is logged with referrer + UA. The admin sees URLs with 3+ hits in the last 30 days and can create a 301 with one click + a target URL field. Solving SEO recovery becomes a feed scroll
- RedirectManager class — lookup(), logNotFound(), stats(). Self-heals not_found_log table on first use. Admin/api/zt-track paths bypass (no false-positives on dev requests)
- Image Studio branding — existing admin/media-optimize.php now positioned as a Smush Pro alternative. Bulk batch convert (Media::batchConvert), responsive srcset auto-gen (320-1920px), Pinterest tall-image generator, domain-watermark stamper — all existing in Media.php
- Critical CSS Studio branding — existing Performance class (Performance::inlineCriticalCss, addCriticalCss, deferJavaScript, addPreloadHints, getCoreWebVitalsHints) positioned as a WP Rocket alternative. No new code, just visibility
- features.php +3 cards (Redirect Manager / Image Studio / Critical CSS Studio) — total grid now 14 cards covering ~$406+/yr in WP plugin subscriptions
Changed files (9)
native/classes/RedirectManager.php
—
YENI class: lookup, logNotFound, stats, ensureSchema
native/admin/redirects.php
—
YENI admin: CRUD UI + 404 log + suggest-redirect
native/admin/includes/sidebar.php
—
Redirect Manager link eklendi (Security Center altina)
native/includes/bootstrap.php
—
RedirectManager::lookup() hook (router'dan once)
native/classes/FrontendController.php
—
notFound() icinde RedirectManager::logNotFound()
features.php
—
Marketing grid: 3 yeni kart (Redirect/Image/Critical CSS)
sites/*/admin/redirects.php
—
15 site propagated
sites/*/classes/RedirectManager.php
—
15 site propagated
sites/*/includes/bootstrap.php
—
15 site propagated
TOTP 2FA — Surfaced + Coverage Tracker in Security Center
Added
- Security Center → 2FA Status tab — lists all admin/editor/author users, their 2FA enabled state (ENABLED / NOT ENABLED pill), role, last-login timestamp. "Enable Now" button for the current user (jumps to Settings). For other users: instruction that they must enable from their own profile (TOTP is a personal credential)
- 5th KPI card: 2FA Coverage — percentage of admin/editor/author users with TOTP enabled. Color codes: green ≥80%, neutral 40-80%, red <40%. Sub-label shows raw count (e.g. "3 / 5 users")
- About TOTP card — documents the setup flow (Settings → Two-Factor Authentication → Initialize → scan QR → confirm), login flow, recovery path (DB-level unlock if authenticator is lost). Explicitly positions jekcms's TOTP as a replacement for WP 2FA + Wordfence Login Security (~$50/yr combined)
- features.php 11th card: TOTP 2FA — RFC 6238, Google Authenticator/Authy/1Password compatible
Changed files (3)
native/admin/security-center.php
—
2FA tab + 5th KPI card + admin user query
features.php
—
Marketing grid: 11. kart — WP 2FA + Wordfence Login Security ~$50/yr alternative
sites/*/admin/security-center.php
—
15 site propagated
Security Center — WAF Dashboard + File Integrity Monitor, Built-In
Added
- Security Center admin page — a single tabbed dashboard for WAF/login attempts, security events, and file integrity. Surfaces what was already running silently (Security::detectAttacks, login_attempts log, IntegrityGuard::maybeVerify) so you can actually see attacks happen. Replaces Wordfence Premium ($119/yr)
- WAF tab — recent login attempts (last 30), top attackers by failed-login count (last 7d), blocked IPs table with manual block/unblock, one-click "Block this attacker" from the top-attackers list. KPIs at the top: failed logins (24h), unique IPs (7d), blocked count, FIM status
- Security Events tab — parses
logs/security.log(where Security::detectAttacks writes SQLi / XSS / path-traversal hits), displays timeline with IP, message and context. Up to 30 most recent events - File Integrity tab — install fingerprint display, VERIFIED/DRIFT status pill, last tamper report (formatted JSON), one-click "Scan Now" button that triggers IntegrityGuard::verifyManifest(). Includes a response-playbook card for what to do if drift is detected
- Self-healing blocked_ips table — created automatically on first visit to the page. Idempotent: ON DUPLICATE KEY UPDATE preserves existing blocks. CSRF-protected admin operations throughout
- Sidebar link — new "Security Center" entry directly below Backups in the admin nav. Shield icon. Standard active-state highlighting
Changed files (5)
native/admin/security-center.php
—
Yeni admin sayfasi (~500 satir): WAF tab + Events tab + FIM tab
native/admin/includes/sidebar.php
—
Security Center baglantisi eklendi (Backups'in altinda)
features.php
—
Marketing grid: 10. kart — Wordfence Premium $119/yr alternative
sites/*/admin/security-center.php
—
15 site propagated
sites/*/admin/includes/sidebar.php
—
15 site propagated
Smart Backup — Scheduled Daily Backups, Built-In
Added
- Smart Backup scheduled cron — turn on daily auto-backups in the admin (Backups → Smart Backup Schedule card). Pick the hour (default 03:00, low-traffic window). Cron runs
BackupManager::scheduledRun()which is idempotent (one backup per day, even if cron fires multiple times). Replaces UpdraftPlus Premium ($70/yr) - Retention policy — configurable 7-365 days. Auto-backups older than the cutoff are deleted automatically after the daily run. Manual backups are never auto-deleted. Storage stays bounded
- Pure-PHP backups — no
mysqldumpdependency (Hostinger and shared hosts often disable it). Streaming row-by-row dump handles large post tables without exhausting memory. Output is a single ZIP withdb.sql+uploads/+manifest.json - External sync hint — the schedule card documents the recommended
rclonepattern for syncing thebackups/folder to S3, Google Drive, or Dropbox. Native cloud SDK support is on the v2.6.x roadmap
Changed files (4)
native/classes/BackupManager.php
—
scheduledRun() method eklendi — hour + day guard, retention prune
native/cron.php
—
BackupManager::scheduledRun() cron tick'inde tetikleyici (silent no-op default)
native/admin/backups.php
—
Smart Backup Schedule card: enable + hour + retention slider + CSRF-protected save
features.php
—
Marketing grid: Smart Backup karti — UpdraftPlus Premium $70/yr alternative
Schema Studio — 13 Schema.org Types, Built-In
Added
- Schema Studio plugin family — 13 Schema.org types, all driven from the post editor with form-based UI. The full set: Article, BlogPosting, NewsArticle, TechArticle, ScholarlyArticle, Report, FAQPage, HowTo, Product, Event, Review, Course, Recipe (new), and LocalBusiness (new). Replaces Rank Math Pro's schema-builder module ($59/yr) — no subscription, no add-ons
- Recipe schema — food bloggers can now ship Google Rich Recipe cards: prep/cook/total time (ISO 8601), yield, category, cuisine, calories, ingredient list, step-by-step instructions, aggregate rating. Drives 30-40% CTR uplift on recipe-intent queries
- LocalBusiness schema — drives Google Maps + local-pack ranking. 18 business subtypes (Restaurant, Store, MedicalBusiness, Dentist, BeautySalon, TravelAgency, …). Full PostalAddress + GeoCoordinates + opening hours + price range + aggregate rating
- CSV-style data entry — ingredients, instructions and opening-hours all accept one item per line in a textarea. No fragile JavaScript arrays, no clicking +/- buttons; copy-paste works directly from your notes
- Schema preview + Google Rich Results Test link — the editor shows the live JSON-LD payload AND a one-click handoff to Google's validator. Zero guesswork
Changed files (5)
native/includes/helpers.php
—
output_schema() — Recipe + LocalBusiness case bloklari eklendi (~120 satir)
native/admin/post-edit.php
—
Recipe + LocalBusiness POST handler + UI form fields (CSV textarea pattern)
features.php
—
Marketing grid: Schema Studio karti — Rank Math Pro $59/yr alternative
sites/*/includes/helpers.php
—
15 site propagate
sites/*/admin/post-edit.php
—
15 site propagate
ZeroTrack Analytics — Privacy-First, Cookie-Free, Built-In
Added
- ZeroTrack Analytics plugin — a built-in, privacy-first replacement for Google Analytics, Plausible and Matomo. Zero cookies. Visitor data never leaves your server. KVKK/GDPR-compliant by design: IP addresses are SHA-256 hashed with a daily-rotated salt, making cross-day correlation mathematically impossible. Auto-activated on install
- Privacy dashboard in admin → ZeroTrack: page views, unique visitors, sessions, bounce rate, daily trend chart, top pages, referrers, countries, devices, UTM sources. Date range selector (today / 7d / 30d / 90d)
- Smart filtering out of the box — respects browsers' Do-Not-Track header; excludes logged-in admins; filters Googlebot, GPTBot, ClaudeBot, headless Chrome and 20+ other automation user-agents; configurable IP and path exclusions
- Reverse-proxy aware — picks up the real visitor IP behind Cloudflare and LiteSpeed (no double-counting your CDN). Country detection via Cloudflare CF-IPCountry header — no third-party GeoIP database needed
- Self-cleaning — raw pageview rows are deleted after a configurable retention window (default 90 days). Daily aggregates are kept forever for long-term trend analysis with tiny storage footprint
Changed files (7)
native/plugins/zerotrack/plugin.php
—
Plugin manifest + bootstrap
native/plugins/zerotrack/ZeroTrackPlugin.php
—
Tracker beacon endpoint, UA parser, salt rotation, daily aggregator, retention cleanup
native/plugins/zerotrack/activate.php
—
DB schema: zt_pageviews, zt_aggregates_daily, zt_settings
native/plugins/zerotrack/admin/index.php
—
Privacy dashboard — KPIs, trend chart, top tables
native/plugins/zerotrack/admin/settings.php
—
Settings UI: master switch, DNT, exclusions, retention
features.php
—
Marketing grid — ZeroTrack vs Plausible $9/mo
sites/*/plugins/zerotrack/
—
Propagated to all 15 sites + _template
Sharper Homepage Hero — A Concrete Hook
Improved
- The hero now says what jekcms actually is — the vague "Smart Next-Gen CMS" line was replaced with a concrete, provable hook: everything you would normally add to WordPress (SEO, internal linking, AVIF media, bulk import, AI publishing) is already in the core, self-hosted, with no plugin stack to buy or maintain. One clear message instead of a buzzword
Changed files (1)
marketing-includes/header.php
—
hero_title + hero_subtitle (EN/TR) somut hook
Newsletter Email: Branded Dark Header
Improved
- Email design now has a real branded identity — the previous version rendered too plain in clients that strip CSS backgrounds. The header is now a solid dark band with the brand wordmark and an accent eyebrow, plus a thin accent rule under it, a card frame, and a tinted footer band. Backgrounds use both inline CSS and
bgcolorattributes so the design survives in Gmail/Outlook. Auto-applied to system templates via a schema bump
Changed files (2)
plugins/newsletter/data/default-templates.php
—
koyu markalı header bandı + bgcolor sağlamlaştırma (native+kök+15 site)
plugins/newsletter/NewsletterPlugin.php
—
SCHEMA_VERSION 2.5.0 → 2.6.0
Redesigned Newsletter Email Templates
Improved
- Professional, brand-consistent email templates — the newsletter emails (confirmation, welcome, campaign, unsubscribe, new-post) were replaced with a polished, English, email-safe design: a clean white card on a soft background, branded header with an accent eyebrow, strong typographic hierarchy, a proper rounded brand CTA button, and a complete footer (unsubscribe, website, copyright). Table-based + inline CSS for reliable rendering across email clients; all placeholders preserved
- Auto-applied across all installs via a plugin schema-version bump — system templates refresh automatically on the next load, while any template you customized is left untouched
Changed files (2)
plugins/newsletter/data/default-templates.php
—
yeni profesyonel İngilizce e-posta tasarımı (native+kök+15 site)
plugins/newsletter/NewsletterPlugin.php
—
SCHEMA_VERSION 2.4.0 → 2.5.0 (otomatik re-seed tetik)
Blog Editor: Featured Post & Empty-Content Fix
Fixed
- Blog post editor opened empty for the featured post — the editor treated
?id=0(the featured post, which carries id 0) as "new post" because of aid > 0check, so it never loaded it. It now loads any post when an id is present (0 included); a truly new post is one with no id parameter. Additionally, if a row's body is empty (legacy posts whose content lived only in the static blog data file), the editor pre-fills the form from that source by slug/id for review — saving persists it into the database (display-only, non-destructive, never overwrites existing edits)
Changed files (1)
admin/blog-post-edit.php
—
id=0 düzenleme + blog-data.php boş-içerik ön-doldurma (jekcms.com kök)
Plugin System Restored on the Main Install (Newsletter Now Lists)
Fixed
- Newsletter (and all plugins) now appear in the plugin manager — the main install's bootstrap (cloned long ago from an older codebase) was entirely missing the plugin-loader block, so the plugin registrar never ran and no plugin could register itself. The block was restored, identical to the canonical source; the registrar now runs (with the self-healing plugin-table schema), so Newsletter registers automatically and is listed/activatable
Changed files (1)
includes/bootstrap.php
—
eksik plugin-loader bloğu native ile birebir geri eklendi (jekcms.com kök)
Marketing Blog Editor Now Reachable in Admin
Fixed
- Blog posts are editable again — the bilingual marketing blog (the EN/TR posts shown on jekcms.com/blog) has its own admin editor that reads the same table the public blog uses, but it had no link in the admin menu, so it looked like the posts weren't manageable (the CMS Posts page only lists the separate site-content table). A "Blog Posts (jekcms.com)" entry was added to the admin sidebar — the existing posts are now listed and editable
Changed files (2)
admin/includes/sidebar.php
—
Marketing Blog (blog-posts.php) nav linki — jekcms.com kök admin
config/translations/{tr,en}.php
—
admin_nav_marketing_blog anahtarı (ham-anahtar regresyonu önlendi)
Wizard Network Error, Profiles & Plugin Registration Fixed
Fixed
- "Network error" on Generate fixed — the JSON wizard endpoint (
admin/ajax/assistant-json.php) existed only on two installs; it now exists on every site, so Generate works everywhere, not just compass - Plugins now register on cloned installs — on installs cloned from an older database the
pluginstable could be missing newer columns, which made plugin registration fail silently — so the Newsletter plugin never appeared in the plugin manager. The scanner now self-heals the table schema, so Newsletter (and any new plugin) registers and is visible/activatable
Changed files (3)
includes/plugin_hooks.php
—
plugins tablosu şema self-heal (native+kök+15 site)
classes/ImportSchema.php
—
profiles() + themeProfile() genişletildi
admin/ajax/assistant-json.php
—
kök + tüm sitelere yayıldı
Root Admin Fixes — Content Fixer, Newsletter Link, Wizard Keys
Fixed
- Content Fixer 404 fixed — the SEO Optimizer's Content/Heading Fixer page existed in the canonical source but was missing from the main install's admin, returning 404. It is now present
- Newsletter admin link corrected — the Newsletter plugin manifest pointed its admin page to a non-existent path; corrected fleet-wide so the dashboard opens from the plugin manager (the sidebar entry still requires the plugin to be activated)
- Wizard keys fixed on the main site too — the previous translation-key parity fix covered demo sites but missed the main install;
cq_assistant_*keys are now mirrored there as well, so the JSON Generation Wizard no longer shows raw keys
Changed files (3)
admin/content-fixer.php
—
kök kuruluma eklendi (native'den)
plugins/newsletter/plugin.php
—
Admin Page yolu düzeltildi — native+kök+15 site
config/translations/{tr,en}.php + lang/{tr,en}/general.php (kök)
—
cq_assistant_* native paritesi
Content Queue Wizard — Raw Keys Fixed on All Sites
Fixed
- JSON Generation Wizard now reads properly on every site — the content-queue assistant translation keys (
cq_assistant_*) existed only on a couple of sites, so other sites showed raw keys like "cq_assistant_title" instead of labels. All sites now carry the full key set, mirrored byte-for-byte from the canonical source
Changed files (1)
sites/*/config/translations/{tr,en}.php + lang/{tr,en}/general.php
—
cq_assistant_* native paritesi (15 site × 4 dosya), grep-assert ile sayı eşitliği doğrulandı
Newsletter Signup Live on the Marketing Site
Fixed
- Newsletter subscription now works on jekcms.com — the footer "Subscribe" form was built but silently failed when the subscriber table did not exist. The handler now self-creates the table (idempotent, identical schema to the Newsletter plugin, so the plugin admin reads the same subscribers). Homepage stat figures also unified site-wide
Changed files (2)
marketing-includes/ajax/newsletter-handler.php
—
idempotent self-bootstrap (newsletter_subscribers, eklenti şemasıyla birebir)
index.php / about.php / functions.php
—
stat 500+ → 100+ tutarlı, 14→14+, 24/7 lang-aware
Sub-Page SEO Audit — Documentation Title Fixed
Improved
- Documentation title is now descriptive & branded — the docs
was a bare "Documentation"; it is now "jekcms Documentation | Setup, Admin Guide, REST API & Automation" (and category/page docs titles now carry the brand). Stronger, unique titles for search - Full sub-page meta/SEO audit: every marketing sub-page verified to have a unique, bilingual (EN/TR) meta title and description, valid canonical + hreflang (en/tr/x-default) + Open Graph; no missing, empty or duplicate meta found
Changed files (1)
docs.php
—
SEO başlığı markalı + anahtar-kelimeli (görünür UI etkilenmez)
Accurate WordPress-Alternative Page (Verified Features Only)
Improved
- Stronger, honest "why jekcms vs WordPress" page — now built strictly from verified features: it maps the paid WordPress plugins jekcms replaces in its core (SEO/Yoast, internal linking/LinkWhisper, broken-link detection, AVIF media/ShortPixel, security/Wordfence, payments/WooCommerce), plus jekcms-only JSON bulk import and n8n+Gemini AI automation. Modern, readable, theme-consistent table; long-tail keyword focused; FAQ with FAQPage structured data
Fixed
- Removed an inaccurate capability claim — a "multi-site / fleet management" line was wrongly added to the comparison page, structured data and llms.txt. jekcms has no such product feature; it has been removed everywhere and replaced with verified, real capabilities only
Changed files (2)
wordpress-alternative.php
—
doğrulanmış özelliklerle yeniden yazıldı (multi-site kaldırıldı)
header.php + llms.txt
—
uydurma özellik kaldırıldı, gerçek yeteneklerle değiştirildi
No Orphan Pages — Full Internal Linking
Fixed
- No orphan pages — every public marketing page is now reachable via the footer + sitemap + clean URL with EN/TR variants. The "Report Piracy" page was orphaned (no link anywhere) and is now footer-linked and crawlable; the WordPress-alternative page was already footer-linked (verified)
Changed files (2)
marketing-includes/footer.php
—
report-piracy Legal bölümüne eklendi
functions.php + .htaccess + sitemap.php
—
report-piracy slug map + TR slug + temiz-URL allowlist + sitemap
AI-Search Visibility & WordPress-Alternative Positioning
Added
- WordPress Alternative comparison page — a new, honest
/wordpress-alternative(TR:/tr/wordpress-alternatifi) page with a factual jekcms-vs-WordPress table and FAQ (FAQPage structured data), sitemap + hreflang + footer-linked - llms.txt — a machine-readable summary at
/llms.txtso AI assistants can accurately describe jekcms as a self-hosted CMS / WordPress alternative
Improved
- Discoverable in AI search — AI answer/search engines (ChatGPT, Perplexity, Gemini, Claude, Copilot) are now explicitly allowed (server-level block removed for them; named robots groups added). Low-value SEO-scraper bots stay blocked
- Clearer entity for search & AI — structured data now classifies jekcms as a Content Management System with a precise CMS / WordPress-alternative description and feature list; site meta sharpened to say "self-hosted CMS / WordPress alternative" (factual, no keyword stuffing)
Changed files (3)
.htaccess
—
AI bot 403 kaldırıldı (SEO-scraper engelli kalır); wordpress-alternative temiz-URL + TR slug
robots-txt.php
—
GPTBot/OAI/Claude/Perplexity/Google-Extended… açık Allow grupları + llms.txt referansı
llms.txt + wordpress-alternative.php
—
YENİ; header.php SoftwareApplication=CMS + meta; sitemap + footer + slug map
Marketing-Site SEO Hardening
Improved
- No duplicate page URLs — direct
.phphits (e.g./features.php) now 301-redirect to the clean URL (/features), so each page has a single indexable address and a single canonical - Single redirect hop —
http://wwwnow goes straight tohttps://non-www in one 301 instead of two chained redirects (faster, stronger SEO signal) - Audited & confirmed correct: error pages return real 404 (no soft-404, noindex), dynamic robots.txt with environment-aware sitemap, bilingual sitemap with hreflang, self-referencing canonical + en/tr/x-default hreflang,
?lang=tr→/tr/…301
Changed files (1)
.htaccess
—
www→non-www+https tek hop; .php→temiz URL 301 (allowlist, THE_REQUEST guard, static-serve öncesi)
Article Rendering & Internal-Link Integrity Fixes
Fixed
- Broken internal links repaired at the source — The auto internal linker could run over raw Markdown and inject a link inside a Markdown link, which the renderer then turned into corrupted, half-visible anchor markup. Markdown links/images are now protected, so internal linking can never mangle content again. The link cleaner was also hardened to fully remove any pre-existing corrupted/leaked link debris — re-running the internal-link scan on an affected site now self-heals old content
- Checklists render properly — Markdown task lists (
- [ ]/- [x]) now show real checkbox glyphs instead of literal "[ ]" text - Tables are styled — Markdown tables in articles now render with borders, padding and header styling instead of columns running together
- No more double bullets — list items showed both a default bullet and a custom marker; the duplicate is gone
- Related posts fixed — the related section rendered twice, once as full-width stacked images; the broken duplicate was removed, leaving the clean card grid
- Featured image aspect ratio — single-post cover images now use a proper 16:9 frame instead of a cropped near-square
- Table of contents shows accented characters correctly — the on-page contents list double-escaped HTML entities, showing things like "Güncel" instead of "Güncel"; titles are now decoded before display (anchors stay in sync)
- Front-end fixes now go live immediately — deploys purge the page cache, so a fix is no longer masked by up-to-5-minutes of stale cached HTML
Changed files (4)
includes/auto-linker.php
—
markdown link/görsel placeholder koruması (iç içe anchor kök nedeni)
includes/helpers.php
—
parse_markdown GFM task-list ([ ]/[x] → onay kutusu glyph)
themes/travel (subpages.css, single.php)
—
tablo CSS + çift-madde list-style:none + bozuk dublikat related blok kaldırıldı
themes/health (single-v2.css)
—
.h-single__cover 4/3 → 16/9 (native + ilgili siteler)
JSON Wizard Rename & Calendar Visibility Fix
Improved
- "Content Assistant" renamed to "JSON Generation Wizard" — name now reflects what it actually does: builds a ready-to-import JSON + prompt
- "Continue below" marker is now built-in — typing
{devam}in a post renders a centred "content continues below" button that smooth-scrolls to the next section. It now lives in the core renderer (theme-independent), so theme resets can no longer wipe it - Checklist fix also covers articles already stored as HTML, not just Markdown
Fixed
- Content calendar fixed — schedule is visible again — On some installs the whole calendar silently came back empty: the underlying query referenced a column that older content-queue tables never had, so it failed and showed nothing. The query is now schema-independent and self-healing, and the month view also shows every scheduled item regardless of its state (draft / approved / in-progress / done), colour-coded by status
- Calendar hover preview used the wrong image field in one branch — corrected
Changed files (2)
admin/content-queue.php
—
takvim status filtresi genişletildi (scheduled_date olan tüm öğeler) + görsel-alan dal hatası
lang/*/general.php, config/translations/*
—
cq_assistant_title → JSON Oluşturma Sihirbazı / JSON Generation Wizard
Cleaner Content Queue Import Screen
Improved
- Content Queue → Import — Clearer visual separation between the AI Content Assistant and the import options (JSON / Google Sheets / CSV), so the two no longer run together on the page
- Removed the redundant static JSON and Google Sheets format reference blocks — the Assistant already generates a ready-to-use example, so the extra boilerplate only added clutter. Applied fleet-wide
Changed files (1)
admin/content-queue.php
—
import sekmesi: bölüm ayrımı (gap) + statik format kutuları kaldırıldı — native + _template + 14 site senkron
Reliability, Security & Always-On Delivery
Added
- Two-Factor Authentication (TOTP) — Modern QR setup card in every site's Security settings. Scan with Google Authenticator / Authy / 1Password; self-hosted QR (no third party), with a manual key fallback. Login enforcement is fail-open by design — a 2FA glitch can never lock you out
- Zero-downtime auto-deploy — Updates now ship to the whole fleet automatically within minutes of a change, over HTTPS, with a post-deploy health check. No manual uploads, no SSH, no lockouts
Improved
- Faster pages — documentation/screenshot assets ~73% lighter, zero-layout-shift images
- Cleaner SEO — bilingual default meta description & footer fields, consistent schema name source
Fixed
- Site name in Google results — A long-standing settings storage issue made search engines fall back to the bare domain. Now every site shows its real configured name in titles, social cards and structured data — fleet-verified
- Stay signed in — Admin sessions no longer drop unexpectedly; they persist until you explicitly sign out (root cause: server session garbage-collection wasn't aligned with the configured lifetime)
- Footer & branding — Footer renders reliably and is driven from a single source in General Settings (slogan / footer text), bilingual (TR/EN) where applicable; placeholder/demo remnants removed
Changed files (5)
includes/Totp.php / QrSvg.php
—
NEW — self-hosted TOTP + QR (SVG)
deploy/deploy-all.sh
—
NEW — sunucu-tarafı ban-proof auto-deploy + smoke-test
includes/Session.php
—
gc_maxlifetime fix (oturum kalıcılığı)
admin/settings.php
—
modern 2FA kartı + settings persistence (SERP) fix
marketing-includes/footer.php
—
bulletproof footer
Two-Factor Auth, Smart Newsletter & Customer Update Channel
Added
- Admin two-factor authentication (TOTP) — Optional time-based 2FA with QR enrollment, enabled/disabled per account from Security settings; compatible with any authenticator app
- Smart newsletter digests — The subscription plugin can now send an automated weekly or monthly roundup of new posts (frequency off/weekly/monthly + day-of-month), reliably driven server-side via cron with per-period de-duplication
- Customer self-update channel — End-to-end signed update delivery: the update manifest is verified with an embedded public key so verification works on every install, SHA-256 is mandatory, and a one-command release packager builds a clean core package with a key-pair safety gate that refuses a mis-signed release
Fixed
- Critical SEO: archive pages no longer soft-404 — On the Tech & Minimalist themes every category/author archive returned a hard 404 (the template read a routing key that was never set); these pages now resolve correctly and author archives are fully supported
- API write authorization — An authenticated low-privilege token can no longer create/modify/delete content or touch another author's posts; role + ownership are enforced from the product's own capability model
- Sitemap/robots resilience — Security user-agent heuristics could return 403 to Googlebot/Search Console for
sitemap*.xml/robots.txt; these endpoints now bypass every blocking rule so indexing is never accidentally lost - Footer social links — The marketing footer now renders only the accounts configured in General Settings → Social Media (placeholder/demo links removed)
Changed files (9)
native/includes/Totp.php
—
NEW — RFC6238 TOTP
native/admin/login.php
—
2FA 2-adım akışı
native/plugins/newsletter/classes/WeeklyDigest.php
—
haftalık+aylık dispatch
native/themes/{tech,minimalist}/templates/archive.php
—
archive_slug + author dalı
native/api/v1/index.php
—
authorizeWrite() rol/sahiplik
native/.htaccess
—
sitemap/robots güvenlik-bypass
native/classes/Updater.php
—
gömülü public key + managed guard
tools/release.php
—
NEW — release paketleyici + anahtar self-doğrulama
marketing-includes/header.php
—
şema adı i18n
Security Hardening & Update Integrity
Fixed
- Critical: SSRF blocked — Server-side image fetch (media-from-URL) now allows only http/https public hosts; private/loopback/link-local and cloud-metadata addresses are rejected, redirects disabled, size-capped
- High: Markdown XSS blocked — Link/image URLs in content are scheme-allowlisted;
javascript:,data:,vbscript:and protocol-relative URLs can no longer reachhref/src - High: Cross-site request hardening — State-changing requests now also enforce same-origin (Origin/Referer) on top of the CSRF token, covering all admin action pages at once
- SVG upload XSS blocked — Uploaded SVGs containing scripts, event handlers, foreignObject, external refs or XML entities (XXE) are rejected; static SVGs still allowed
- Update integrity mandatory — Updates without a verified SHA-256 are refused; manual ZIP apply is off by default unless the official hash is provided; developer-license localhost detection now requires a real loopback connection (Host-header spoof closed)
Changed files (8)
api/v1/index.php
—
validateRemoteUrl() SSRF guard
includes/helpers.php
—
parse_markdown URL şema allowlist
includes/Security.php
—
CSRF same-origin + SVG denylist
classes/Updater.php
—
zorunlu sha256 (hash_equals)
admin/updates.php
—
manuel ZIP default-kapalı + sha256 gate
classes/License.php
—
isLocalhost loopback-peer zorunlu
tools/check-drift.php
—
NEW — standardizasyon drift denetimi
STANDARDIZATION.md
—
NEW — propagasyon/governance modeli
Core Web Vitals: Responsive Images, LCP & Caching
Improved
- Site-wide Image Optimization — Every front-end image now ships with intrinsic
width/height(zero layout shift / CLS),decoding="async"and lazy-loading, applied through a single global output filter that covers all themes. The hero/LCP image keepsfetchpriority="high"and is never lazy-loaded - Automatic Responsive Variants — Existing images are progressively back-filled with optimized AVIF/WebP size variants (thumbnail/medium/…), so cards and thumbnails download a small image instead of the full-resolution original — done gently in the background with no extra server load
- Faster First Paint — Instant-search CSS no longer blocks rendering (async with no-JS fallback); themes can ship a
critical.cssfor inlined above-the-fold styles - Browser Caching Restored — Front-end pages are cacheable again (back/forward cache works); only admin and API stay no-store
Changed files (5)
includes/helpers.php
—
jek_img_optimize() global filtre + instant-search async
index.php
—
ob_start('jek_img_optimize') (yalnız frontend)
classes/Media.php
—
regenerateVariants() — eksik boyut varyantı backfill
cron.php
—
görsel varyant backfill (nazik, cursor, idempotent)
themes/travel/*
—
picture()/LCP + koşullu critical-CSS
Clean Content Rendering: Markdown, Code Blocks & Encoding
Improved
- Newsletter Band Restyled — The pre-footer subscribe band dropped its generic blue gradient and now uses the site's own monochrome design tokens with pill controls — consistent in both light and dark themes
Fixed
- Critical: Raw Markdown Headings — When a post mixed HTML with Markdown (the normal output of AI/automation),
##/###headings, fenced code blocks and lists were printed literally instead of being rendered. The Markdown engine was rewritten so block elements are converted even alongside HTML - Critical: Shell Commands Became Headings — Code (fenced ``` / ~~~, inline, and existing
<pre>) is now protected before any heading parsing, so#shell comments and#!/bin/bashlines are never mistaken for titles - Legacy Linux Articles Repaired — WordPress-imported command blocks that had broken apart (
<pre>…</p><p>…</pre>) were rejoined into clean multi-line code blocks - Critical: Turkish Text Corruption (Mojibake) — Some automated content arrived double-encoded (Turkish letters shown as CJK glyphs, e.g. "Çikolata" → "脟ikolata"). The API now repairs every inbound write path automatically (self-validating, no false positives), and a fleet tool cleans existing content across all sites
Changed files (5)
includes/helpers.php
—
parse_markdown() v2 — kod-koru-önce, başlıklar HTML içerikte de
api/v1/index.php
—
fixMojibake() güçlendirildi + demojibakeDeep() (tüm write yolları)
marketing-assets/css/main.css
—
.nl-band site token'ları + pill
tools/fix-mojibake-all.php
—
NEW — 15 site fleet mojibake onarımı
tools/fix-celil-pre.php
—
NEW — celil <pre> komut bloğu onarımı
Reliable Theme Switching, 17 Auto-Publish Networks & Full-Width Admin
Added
- Regional & Fediverse Auto-Publish — Eight new networks join the social automation engine: Pixelfed, Misskey/Sharkey, WriteFreely, Micro.blog and Lemmy (token/instance), VK (OAuth2), plus Hatena Bookmark and Plurk (OAuth1). Every connected account receives new posts automatically with per-platform pacing and back-off
- Honest Capability Notes — Networks without a safe, official publishing API (Xing, Naver, Nostr) are now clearly labelled with the reason instead of silently failing — no fake connectors
Improved
- Full-Width Connections Page — The social connections grid no longer caps at a narrow column; cards now use the full screen width on large displays instead of leaving the right third blank
Fixed
- Critical: Theme Switching Failed — Because
settings.keyis uniquely indexed, the old "UPDATE then INSERT-if-zero-rows" path threw a duplicate-key error whenever the value was unchanged (re-activating a theme, or the automatic previous-theme snapshot on every switch). The activation aborted with a database error and the theme never changed. Theme writes are now a single-row upsert (delete + insert) that also self-heals any pre-existing duplicate/stray rows. Active-theme reads are deterministic (canonical group, newest row) so the front-end always reflects the chosen theme
Changed files (4)
admin/themes.php
—
setThemeSettingRow() singleton upsert; tüm yazım noktaları
includes/helpers.php
—
get_active_theme() deterministik sorgu
plugins/jek-social/classes/adapters/*
—
Pixelfed/Misskey/WriteFreely/Microblog/Lemmy/Vk/Hatena/Plurk
admin/plugins/jek-social/connections.php
—
.js-wrap tam genişlik + yeni platform formları
Smart Next-Gen CMS — Admin UI Overhaul, Bulletproof Slugs & Autosave
Added
- New Admin Design Language — Unified badge system (5 pill variants: success/danger/warning/info/neutral), stat-card-v2 with colored backgrounds + decorative SVG, quick-action outline buttons, state-block for empty/error states
- Language Toggle — TR/EN switcher in admin header with session-based override (
$_SESSION[admin_lang_override]), persists across navigation - Draft Autosave — Post editor saves every 30s + localStorage offline fallback. Status pill bottom-right: "Saving…" / "Saved · 15:42" / "Offline". Restore prompt on reopen if unsaved changes found
- Anonymous Preview —
preview.php?token=XXXwith 48-hex-char secret tokens stored inpost_meta. Click "Preview Link" button, URL auto-copied to clipboard. Orange banner indicates preview mode - Revision Diff — Click any revision → modal with word-level diff (jsdiff via CDN). Green additions / red strike-through deletions. "Restore this revision" with automatic snapshot
- Word Count Distribution — Dashboard shows stacked bar of post word counts (0-500, 500-1K, 1K-1.5K, 1.5K+) with hover tooltip
- Date Range Filter — Post listing has native date pickers for
date_from/date_to - Media Grid/List Toggle — Library view switches between grid and vertical list, preference saved to localStorage
- Slug Rebuild Tool —
admin/tools/rebuild-slugs.php— dry-run preview + conflict handling + CLI mode for batch operations
Fixed
- Critical: Turkish Slug Bug —
mb_strtolower()was convertingİ(U+0130) into composite sequences, breaking the transliteration map and leaving orphan bytes as hyphens. Newslugify()runsstrtrBEFORE lowercasing with comprehensive map (Turkish + Latin extended). Fixed 866 bad slugs across all sites - Sidebar Border Bug —
.sidebar-brandwas 56px but--header-height: 60px, creating a 4px misalignment visible as a horizontal line. Now usesvar(--header-height) - profile.php 90s Button —
.avatar-actions .btn-smhadborder-radius: 50%rendering buttons as blobs. Plus "Active" was hardcoded English in Turkish admin. Both fixed - Settings Thumbnail Inputs — Pixel inputs had no styling (native browser default — 90s). Now proper padding, focus ring, contained background
- Logo Regression —
logo-yatay.svgwas an obsolete test logo. Replaced withlogo-dikey.svg+ inline SVG in sidebar (matches admin login) - License Page Branding — Fake blue
[J]SVG monogram replaced with reallogo-dikey.svg. Hardcoded#28a745colors migrated to CSS variables - Updates Page UX — License inactive / update failed / up-to-date states use unified pill-badge format. Raw English errors removed from Turkish UI
Changed files (32)
includes/helpers.php
—
slugify() — bulletproof Turkish + Latin extended
api/v1/index.php
—
generateSlug() wrapper → slugify()
config/functions.php
—
Session-based admin_lang_override
admin/ajax/autosave.php
—
Existing — no change (frontend added)
admin/ajax/preview-token.php
—
NEW — generates 48-hex preview tokens
admin/ajax/revision-get.php
—
NEW — fetches revision JSON for diff
admin/ajax/revision-restore.php
—
NEW — restores post from revision
admin/tools/rebuild-slugs.php
—
NEW — slug rebuild UI
admin/tools/rebuild-slugs-cli.php
—
NEW — CLI version
admin/post-edit.php
—
Autosave JS, preview link, revision diff modal
admin/posts.php
—
Date range filter
admin/media.php
—
Grid/list toggle
admin/profile.php
—
90s button fix + TR translate
admin/settings.php
—
Thumbnail input styling
admin/fix-images.php
—
Pill-badge + icon buttons
admin/content-fixer.php
—
Unified badge system
admin/license.php
—
logo-dikey.svg + CSS vars
admin/updates.php
—
Pill-badge state blocks
admin/login.php
—
Tagline added
admin/assets/css/admin.css
—
Pill-badge, qa-btn, stat-card-v2, lang-toggle
admin/includes/sidebar.php
—
Border fix + slug tool link + inline SVG logo
admin/includes/header.php
—
Language toggle button
admin/includes/init.php
—
set_admin_lang handler
preview.php
—
NEW — anonymous token-based draft viewer
config/constants.php
—
CMS_VERSION = 2.0.1
version.json
—
v2.0.1, db_version 6
marketing-includes/header.php
—
Hero title → "Smart Next-Gen CMS" / "Akıllı Yeni Nesil CMS"
marketing-includes/footer.php
—
logo-dikey.svg + site_tagline
marketing-assets/css/main.css
—
.ss-frame (screenshot component) + .footer-tagline
marketing-includes/ss-helper.php
—
NEW — ss_frame() / ss_step() helpers
tools/sync-from-celil.sh
—
NEW — deployment script (21 verbatim files)
tools/patch-from-celil.php
—
NEW — surgical patch script (6 targeted edits)
Auto-Seed Settings, Core Web Vitals, Update System & SEO Hardening
Added
- Settings Auto-Seed —
ensure_default_settings()automatically seedssite_nameandsite_alternate_nameinto the database on first page load. Cache-file based, zero performance impact after initial run. No more manual SQL for new sites - Migration System —
migrations/5_seo_settings_seed.phpcreated across all sites. Update system can now distribute database changes automatically - LCP Eager Loading — First post card image on page 1 gets
loading="eager" fetchpriority="high"across all theme architectures. Expected ~200-500ms LCP improvement - CLS Prevention —
widthandheightattributes added to all post card images. Eliminates layout shift completely - CSS Cache Busting —
?v=THEME_VERSIONparameter added to stylesheet links in starter theme headers - Update Server Connected —
api/updates/check.phpnow uses realUpdateManagerwith database queries instead of static stub response. Graceful fallback on connection errors - jekcms Backlinks — All footer files across active sites, admin panels, and bundled themes now link to
jekcms.comwith "jekcms" anchor text andrel="noopener noreferrer" - Marketing SEO — Real favicon URL (SVG),
application-namemeta tag,theme-color, WebSite schemaalternateNameadded. Decorative text moved to CSS to prevent Google sitelink pollution
Fixed
- Sitemap pagination URLs removed —
?page=2,?page=3etc. no longer appear in homepage, category, tag, and author sitemaps. These thin pages wasted crawl budget - Thin tag pages now
noindex— Tag pages with fewer than 3 posts getnoindex, followviaoutput_robots_meta()to prevent thin content indexing - Markdown
# Headingnow renders as<h2>instead of<h1>— prevents double H1 on post pages where title is already H1 - SQL migration file
sql/v1.5.1-seo-site-names.sqldeleted — replaced by automaticensure_default_settings()mechanism - Marketing site favicon was data URI — Google requires real URL for SERP favicon display. Replaced with proper
/favicon.svg - Marketing site showed "Dashboard Posts Media Settings" as Google sitelinks — decorative text moved from HTML to CSS
content: attr(data-label)
Changed files (18)
includes/helpers.php
—
ensure_default_settings() + thin tag noindex + markdown H1→H2
includes/bootstrap.php
—
ensure_default_settings() call added
classes/Sitemap.php
—
Pagination URLs removed
migrations/5_seo_settings_seed.php
—
NEW — DB seed migration
version.json
—
v1.5.3, db_version 5
themes/*/partials/post-card.php
—
LCP eager + CLS dimensions
themes/*/templates/index.php
—
Featured image eager loading
themes/*/templates/archive.php
—
Card index parameter
themes/*/templates/header.php
—
CSS cache busting
themes/*/functions.php
—
render_post_card index param
themes/*/templates/footer.php
—
jekcms backlink
admin/includes/footer.php
—
jekcms backlink noreferrer
api/updates/check.php
—
Real UpdateManager connection
favicon.svg
—
NEW — Root favicon for Google SERP (marketing)
index.php
—
Mockup text → CSS data-label (marketing)
marketing-includes/header.php
—
Favicon + application-name + schema (marketing)
marketing-assets/css/main.css
—
Mockup nav CSS content rule (marketing)
changelog.php
—
v1.5.3 release entry (marketing)
Deep SEO Audit — Schema, OG Image, Core Web Vitals & Accessibility
Fixed
- BlogPosting
authorschema missingurlproperty — Google requires author URL since 2023. Addedauthor.urlpointing to/author/{slug}across all sites - BreadcrumbList last item missing
item(URL) property — Google Rich Results test was reporting errors. Fixed both category and non-category code paths across all sites og:image:widthandog:image:heightmeta tags missing in bundled theme functions.php files — Facebook/LinkedIn image previews could render incorrectly. Added 1200×630 dimensions- Featured/hero image missing
fetchpriority="high"in active theme single.php files — LCP (Largest Contentful Paint) performance impact. Also addedwidth/heightwhere missing - Author avatar
<img>tags had emptyalt=""in active theme files — accessibility and image SEO issue. Replaced with author name - Hardcoded
<html lang="tr">in affected themes — replaced with dynamicget_setting()for correct language declaration
Changed files (4)
includes/helpers.php
—
Author URL + BreadcrumbList item fix
themes/*/functions.php
—
og:image:width/height added
themes/*/templates/single.php
—
fetchpriority + avatar alt text
themes/*/templates/header.php
—
Dynamic html lang attribute
SEO Audit — Pagination, Sitemap Language, Tag Cleanup & OG Locale
Fixed
- Pagination URL double query string bug —
?page=3?page=4caused byget_canonical_url()returning?page=N. Now strips page param from baseUrl before rebuilding - Schema
$currentUrlmissing?page=Non paginated pages — canonical and schema URLs now consistent ?page=1duplicate content — 301 redirect to clean URL added in all site .htaccess files- News sitemap hardcoded
<news:language>en</news:language>— now usesget_setting('general', 'site_language')dynamically across all sites - Tag URLs returning 301 to homepage — changed to proper 410 Gone response with minimal HTML page across all sites
- BlogPosting schema missing
inLanguageproperty — added dynamic language detection across all sites og:localehardcoded toen_USon Turkish sites — now dynamically set totr_TRoren_USbased on site language setting- AVIF → WebP schema image fallback missing
file_exists()check — WebP URL was emitted even when file didn't exist
Changed files (6)
includes/helpers.php
—
Pagination fix, schema URL, inLanguage, AVIF fallback
.htaccess
—
?page=1 redirect rule
classes/Sitemap.php
—
News language dynamic detection
config/routes.php
—
Tag 410 Gone response
themes/*/header.php
—
og:locale dynamic setting
themes/*/functions.php
—
og:locale dynamic setting
Duplicate Prevention, Smart Thumbnails & Admin Tools
Added
Post::checkDuplicate()method — detects duplicate posts by title or slug before creation- Duplicate check integrated into all API webhooks:
webhookPublish,webhookSchedule,webhookDraft,webhookBulkPublish,webhookContentGenerate - HTTP 409 response with full existing post details (id, title, slug, status, url) when duplicate detected
force_duplicate: truerequest parameter to bypass duplicate check when intentional duplicates are needed- Bulk publish silently skips duplicates with
skippedcounter instead of blocking - Admin "Duplicates" button on Posts page — opens modal with full duplicate analysis
- Slug pattern detection engine: finds posts ending with
-N(N=1-10) where the base slug also exists as another post - Single-click and bulk "Trash All Duplicates" actions with real-time UI updates
- Image proxy fallback in
get_featured_image()— when pre-generated thumbnail files are missing, dynamically resizes viaimage-proxy.php - Size dimension map: thumbnail (400×400), card (480×300), medium (800×500), large (1600×1000)
- AVIF → WebP → original format cascade when looking up sized variants
- Content Queue sidebar badge now counts
queuedstatus alongsidedraftandready
Changed files (6)
classes/Post.php
—
checkDuplicate() method added
api/v1/index.php
—
checkDuplicatePost() + webhook integrations
admin/posts.php
—
Duplicates button, modal, JavaScript
admin/ajax/find-duplicates.php
—
NEW — AJAX duplicate finder endpoint
includes/helpers.php
—
get_featured_image() image-proxy fallback
admin/includes/init.php
—
Content Queue badge query updated
Production Hardening — SEO Fixes, License Enforcement & Session Security
Added
output_robots_meta()function — per-page robot directives (noindex for 404, search pages; post-level override)- License enforcement in
init.phpandlogin.php— redirects tolicense.phpwhen no active license key is configured - Cross-site session hijacking prevention: cookie path scoped to site-specific URL path via
parse_url(SITE_URL, PHP_URL_PATH) - Session
_site_hashverification inAuth::loadUser()— prevents authenticated sessions from bleeding across co-hosted sites - Site-specific
remember_tokencookie path — remember-me tokens no longer shared between sites on same domain - Footer branding standardized across all installations
Fixed
- API upload path double
uploads/uploads/prefix —uploadFromUrl()anduploadFromBase64()now strip redundant prefix before saving to database - Duplicate
<link rel="canonical">tags removed from affected site headers where both inline andoutput_seo_head()emitted canonicals - FAQ schema output: enforced minimum 3 items with 50+ character answers, maximum 10 items, deduplicated across helpers
- Sidebar category post counts removed per design rules — "(5)" count display no longer appears in category listings
- Author name links converted from non-clickable
<span>to proper<a href>anchor tags in single.php files - SITE_NAME config spacing corrected — compound names like "FinanceSubject" updated to properly spaced "Finance Subject"
- Schema.org URLs stripped of tracking parameters (
utm_source,fbclid, etc.) viaparse_url() - Post card images missing
width/heightattributes — CLS prevention applied across affected sites
Changed files (7)
api/v1/index.php
—
Upload path fix
includes/helpers.php
—
robots_meta, FAQ schema, schema URL cleanup
classes/Auth.php
—
_site_hash verification, cookie path
classes/Session.php
—
Site-specific cookie path
admin/includes/init.php
—
License enforcement redirect
admin/login.php
—
License check before auth
sql/v1.4.5-migration.sql
—
Fix corrupt featured_image paths
SEO Overhaul, Content Optimizer, Breadcrumbs & Table of Contents
Added
- Complete SEO overhaul across all active sites — meta tags, Open Graph, Twitter Cards, Schema.org structured data reviewed and standardized
- Breadcrumb navigation with Schema.org
BreadcrumbListmarkup added to every site - Table of Contents (TOC) — automatically generated from
<h2>/<h3>headings, renders as sidebar widget or inline block depending on theme - Content Optimizer with dictionary-based synonym refresh — replaces removed AI API (Gemini/Groq) approach that broke Turkish morphology
- Turkish synonym dictionary (~200 modern word pairs) and English synonym dictionary (~180 pairs) with archaic terms removed
- Auto language detection via
get_setting('general', 'ai_content_language')for optimizer dictionary selection - Google SERP site name fix:
??operator replaced with?:to catch empty strings inog:site_nameand WebSite schema <meta name="application-name">tag added to all theme headers for Google site name signal- Pinterest Compose API endpoint for Livecub — Gemini generates photo, PHP GD adds text overlay, 5 layout templates, 1000×1500 output
- SosyalMedya cover image engine replaced: PHP GD gradients → Gemini Image API professional photographs (1080×1920, AVIF, 5 styles)
- Turkish slug generation fix:
generateSlug()now properly transliterates ç, ğ, ı, ö, ş, ü across all sites fix-slugs.phputility script for repairing existing corrupted Turkish slugs in production databases
Fixed
- robots.txt files had unresolved
{{SITE_DOMAIN}}placeholders in affected sites - hobirehber schema function was named
output_hobbyrig_schema()instead ofoutput_hobirehber_schema() - CSP header in production was blocking Google Analytics, AdSense, and Facebook Pixel domains
- MinimalistRig posts had full URLs in
featured_imagecolumn instead of relative paths - Livecub favicon was showing jekcms [J] icon instead of Livecub L+Heart brand icon
Changed files (7)
includes/helpers.php
—
SEO functions, breadcrumbs, TOC, schema fixes
includes/ContentOptimizer.php
—
Dictionary-based synonym refresh engine
admin/content-optimizer.php
—
Optimizer admin interface
themes/*/header.php
—
Breadcrumbs, meta tags, application-name
themes/*/single.php
—
TOC integration
themes/*/style.css
—
Breadcrumb and TOC styling
api/v1/pinterest-compose.php
—
NEW — Pinterest image composer (Livecub)
Critical SEO Fix, Multi-Site Template & Documentation
Added
_template/directory established as the canonical base for creating new jekcms sites — includes all required files, folder structure, and placeholder variables- Dual-environment configuration:
.env(local development) and.env-production(live server) with automatic detection based on hostname - Placeholder system for rapid site cloning:
{{SITE_NAME}},{{SITE_SLUG}},{{SITE_DOMAIN}} - Standard error pages: 400, 401, 403, 404, 500, 502, 503 with consistent branding
- Maintenance mode page (
maintenance.php) with countdown timer - Standardized
.htaccesswith GZIP compression, browser caching (1 year for static assets), security headers, and URL rewriting - Complete deployment documentation: architecture guide, SEO checklist, responsive images reference, upgrade instructions
Fixed
- Critical: Removed
X-Robots-Tag: noindexHTTP header that was accidentally blocking all Google indexing across production sites - Admin content queue retry:
attemptscounter now resets to 0 when a failed task is re-queued - Removed obsolete Pinterest sharing code from post editor panel
- Removed e-commerce menus (Sales, Customers) from blog-only site admin panels — these belong to the main marketing site only
- Synchronized missing AJAX endpoints (comment, newsletter, comment-like) across all sites
- Added missing
SpamFilter.phpclass to kriptogetiri
Changed files (6)
sites/_template/
—
NEW — Complete site template directory
.env.example
—
Environment configuration template
maintenance.php
—
NEW — Maintenance mode page
error.php
—
NEW — Unified error handler (400-503)
.htaccess
—
Standardized security + performance rules
skills/*.md
—
Architecture, deployment, SEO, image documentation
E-Commerce, Customer Portal, License System & Multi-Language Engine
Added
- Complete e-commerce system with iyzico payment gateway integration — credit card processing, 3D Secure, installment support
- Order management lifecycle: create → payment → confirmation → processing → completed, with cancellation and refund flows
- PDF invoice generation with automatic numbering, tax calculation, and downloadable customer receipts
- Customer portal at
/customer/— dashboard with order history, active licenses, downloadable invoices, and profile management - Support ticket system with threaded messages, priority levels, and admin response tracking
- Multi-language engine with database-driven translations — Turkish and English supported out of the box, extensible to any language
Translatorclass with lazy-loading approach: strings parsed on demand, not upfront — significant memory reduction on multi-locale installations- jekcms license system with 6 tiers: DEV (free), PER (personal), STD (standard), PRO (professional), AGC (agency), ENT (enterprise)
- License activation, validation, and deactivation API at
/api/license/ - Update server with check, download, and report endpoints at
/api/updates/ - Image proxy with SSRF protection — blocks private IP ranges (10.x, 172.16-31.x, 192.168.x, 127.x) and automatic garbage collection (7-day TTL)
- Cache management system: page cache, query cache, object cache, sitemap cache, feed cache, image cache with admin AJAX clear controls
- Rate limiting with IP-based tracking and configurable thresholds
- IP blocking list for persistent abusers
- SEO pagination:
rel="next"/rel="prev"tags, canonical URL query string exclusion, robots.txtAllow: /*?page= - Responsive image
srcsetgeneration with automaticwidth/heightattributes for CLS prevention - Gravatar 2x rendering for HiDPI/Retina displays
Breaking
- Sites relocated to
sites/directory structure — existing installations require path migration
Changed files (14)
classes/Order.php
—
Order management
classes/Customer.php
—
Customer accounts
classes/Invoice.php
—
PDF invoice generation
classes/SupportTicket.php
—
Support ticket system
classes/Translator.php
—
Multi-language engine
classes/Payment/IyzicoGateway.php
—
iyzico payment integration
classes/Security.php
—
Rate limiting, CSRF, XSS protection
classes/License.php
—
License client
classes/Updater.php
—
Update client
includes/image-proxy.php
—
SSRF-protected image proxy with GC
includes/cache-cleanup.php
—
Cache garbage collection
customer/
—
NEW — Customer portal directory
api/license/
—
NEW — License API endpoints
api/updates/
—
NEW — Update server API endpoints
Admin Panel English Translation & UI Polish
Added
- Complete English translation of all admin panel interface elements — menus, labels, buttons, tooltips, error messages, and success notifications
- Unified terminology across admin: consistent use of "Posts", "Pages", "Media", "Settings" throughout all modules
- Post voting system activated — thumbs up/down with per-IP deduplication
- Post view counter with bot-filtered tracking
- Newsletter module wired into admin sidebar under PLUGINS section
- AI content queue foundation — infrastructure for automated content generation pipeline
Fixed
- Admin sidebar spacing reduced for cleaner navigation appearance
- CSS improvements across admin panel — consistent padding, border alignment, and responsive behavior on smaller screens
Plugin Architecture, Newsletter System & Advertising Module
Added
- Plugin enable/disable system with database-driven management — plugins can be activated, deactivated, and configured without code changes
- Newsletter module with subscriber management, campaign creation, and delivery tracking — moved from core to PLUGINS menu for optional activation
- Advertising system for banner and inline ad placements with impression and click tracking
- Contact form with spam protection, email notifications, and admin message management
- Email delivery logging with status tracking (sent, failed, bounced)
- Spam protection logging for audit and pattern analysis
- Admin sidebar reorganized: PLUGINS section separated from core navigation
- API endpoint enhancements for external integrations
Changed files (6)
classes/Plugin.php
—
Plugin management engine
classes/Newsletter.php
—
Newsletter subscriber + campaign system
classes/Advertising.php
—
Ad placement and tracking
classes/SpamFilter.php
—
Spam detection and logging
admin/plugins.php
—
NEW — Plugin management interface
admin/newsletter.php
—
NEW — Newsletter administration
Environment System, SEO Tools & Performance Foundation
Added
- Environment configuration system — automatic local/production detection based on hostname with separate database credentials and URL settings
- SEO Optimizer admin tool with on-page analysis, keyword density checker, and readability scoring
- Extended sitemap system:
sitemap.xmlindex with separatesitemap-posts.xml,sitemap-pages.xml, andsitemap-categories.xml - Schema.org auto-detection:
Article,BlogPosting,WebPage, andWebSitestructured data injected per page type - Post view tracking with
post_viewstable — bot-filtered, deduplicated by IP, used for "Popular Posts" widgets - Post voting system infrastructure with
post_votestable — per-IP rate limiting, thumbs up/down - Performance baseline: output buffering, query logging in development mode, execution time tracking
- Advanced
robotsmeta controls: per-pagenoindex/nofollowsettings in post editor
Changed files (4)
config/environment.php
—
NEW — Environment auto-detection
admin/seo-optimizer.php
—
NEW — SEO analysis tool
includes/sitemap.php
—
Extended sitemap generation
includes/schema.php
—
Schema.org structured data
Initial Release — Blog CMS Foundation
Added
- Core blog CMS with post and page management — WYSIWYG editor, draft/published/scheduled status workflow, revision history
- User authentication with role-based access control: admin, editor, author, subscriber — each role has granular permission boundaries
- Hierarchical category system with unlimited nesting depth and SEO-friendly URL slugs
- Tag management with auto-suggest, bulk operations, and tag cloud generation
- Media library with drag-and-drop upload, AVIF/WebP automatic conversion, and gallery management
- Theme system supporting 14+ premium themes — each theme is a self-contained directory with templates, partials, assets, and configuration
- Responsive design with mobile-first approach — all themes pass Google Mobile-Friendly test out of the box
- Comment system with nested replies, Gravatar integration, and admin moderation queue
- Basic SEO:
<title>tags,<meta description>, canonical URLs, and XML sitemap generation - RSS feed at
/feed.xmlwith full-content and excerpt modes - Search functionality with relevance scoring across titles, content, and excerpts
- Admin dashboard with post statistics, recent activity feed, and quick-action buttons
- API token system for external integrations — key generation, revocation, and usage logging
- Clean URL routing via
.htaccessrewrite rules —/post-slug,/category/name,/tag/name,/author/name
Changed files (10)
classes/Post.php
—
Post/page CRUD + revision system
classes/User.php
—
Authentication + role management
classes/Category.php
—
Hierarchical categories
classes/Tag.php
—
Tag management
classes/Media.php
—
Media library + AVIF/WebP conversion
classes/Comment.php
—
Threaded comments
classes/Database.php
—
PDO wrapper with prepared statements
admin/
—
Complete admin panel (dashboard, posts, pages, media, settings)
themes/
—
14+ responsive themes
api/v1/index.php
—
RESTful API with token authentication
Go live today
Setup, content management, SEO and automation — all in one platform. Get started in 30 minutes.
View Pricing- Setup and live in 30 minutes
- 14+ professional themes
- n8n automation integration
- Automatic SEO — Sitemap, Schema.org
- iyzico payment support