Skip to content

Changelog ​

All notable changes to FalconCMS are documented here.
Format follows Keep a Changelog β€” versions are sorted newest first.


v2.7.3 Latest ​

Released: 2026-09-20

Fixed ​

  • Updating from the dashboard could refuse to start, and staying that way was the CMS's own doing. Running falcon:update from a shell β€” on a Docker host, usually as root β€” left vendor/falconcms/falconcms owned by root. The site kept serving, because reading is all it needs, and the damage only showed at the next update, whose pre-flight check correctly stopped rather than let Composer half-replace the package. It told you to chown the files, you did, and the next update from the command line undid it again. The command now hands ownership back to the user the site runs as β€” worked out from the owner of public/index.php, not a guessed name β€” and only when it is actually running as root.

  • A page a plugin's menu points at could not be opened by anyone but an administrator. The middleware works out which menu owns the path being requested and checks that menu's permission, but it looked in the menus table alone β€” and a menu registered with falcon_add_menu_page() is not in it. So the menu appeared in the sidebar, its permission could be ticked in Roles, and opening it still answered 403. Registered menus and their submenus are matched now, and one declared 'public' => true opens for any signed-in user.

  • Clicking Shop went to Orders instead of Overview. A migration corrected that route in June and the seeder put it back on the next update, because it truncates the menus table and rebuilds it every time β€” so the fix was undone by every falcon:update for three months.

  • Two columns were written and silently dropped. Eloquent discards a value for a column outside $fillable without a word. menus.params carries the type=product that is the only thing telling Products β†’ All Products apart from Posts; seeding kept it by accident, so sites looked right while any other code path lost it. cms_forms.lang_code was passed on every form create and saved as nothing.

Changed ​

  • Nothing in the public API. This release is corrections to 2.7.2.

v2.7.2 ​

Released: 2026-09-20

For theme and plugin developers

The helper functions and hook tags that still said lazy_ are now falcon_, and the stored settings keyed under the old name have moved with them. Nothing you have written stops working: every old helper name remains as a forward, every renamed hook fires for callbacks registered under either name, and a value saved under an old key is still read. Old [lazy_*] builder shortcodes still render. The new names are what the documentation teaches from here; the old ones are kept for code already in the wild.

Added ​

  • A mega menu the theme header builds itself. Customizer β†’ Menu β†’ Mega Menu turns on a per-item checkbox under Appearance β†’ Menus: a top-level item with sub-items can show them as a multi-column panel instead of a dropdown, with a column count up to six and a panel width of full, site, or one you name. Eight item-border styles β€” a rule under each item, a dashed one, a rule under each column heading, vertical rules between columns, a full table grid, and two that reveal on hover β€” each with its own colour at rest and on hover. Desktop only, and only for the theme's own header; the Layout builder is unaffected, and with the switch off nothing changes at all.

  • A custom post type can choose where it sits in the sidebar. ACPT β†’ Post Types β†’ Advanced Configuration β†’ Menu Position lists every menu in the dashboard; the type appears directly below the one you pick and the choice is remembered.

  • The icon picker offers every icon the dashboard can draw β€” all 4,237 in the bundled icon font, read out of the font itself so nothing renders as an empty box, with a search box over the whole set.

  • Forms can be renamed. The builder's heading is the field: click it and type. The shortcode's slug deliberately does not follow, so pages the form is already on keep working.

  • A child theme inherits its parent's templates. make:theme --child said it did and it did not β€” a child holding no copy of a template fell through to the default theme rather than to the parent it was made from.

  • The taxonomy archive bases are settings. /category/… and /tag/… were written into the route file; they are on SEO Settings β†’ Permalinks now, so a site can serve /topics/food without editing the package and losing it on the next update.

  • The loop can order by published_at, and its paginator keeps the rest of the query string β€” a reader who searched and then turned the page no longer lands on the unfiltered list.

  • Renaming a term leaves a redirect behind, the way renaming a page always has. A category slug is an address; editing it used to 404 every link to the old one.

  • Menus registered by a plugin or theme appear in Users β†’ Roles. falcon_add_menu_page() could put an entry in the sidebar that no administrator could grant to anybody, because the capability existed only in the package's source. They are listed now, under the same groups the sidebar uses. Two keys opt out: 'public' => true for something every signed-in user should reach, and 'show_in_roles' => false for a capability granted elsewhere. A menu registered without a capability gets one of its own rather than borrowing the dashboard's.

Changed ​

  • Shop and Products have a sidebar section of their own, headed eCommerce, the way ACPT heads Advanced.

  • A subscriber holds the Dashboard and its Overview, and nothing else. The role was seeded with manage_users, which drew a Users entry in the sidebar of everyone who had just registered β€” and every page behind it answered 403. The customer role is narrowed the same way. A role an administrator has edited is left exactly as they set it.

  • The Post Types and Taxonomies lists use the full width, like Field Groups beside them.

Fixed ​

  • One unguarded mega-menu property took the whole header down. Every property but mega_columns was read defensively; a menu row saved before that column existed threw, and the header is on every page, so the site 500'd rather than one menu rendering plainly.

  • Static page caching could serve one visitor's basket to another. The cache keys a finished page on its URL alone, /cart and /checkout sat inside that route group, and every page's header carries a basket count. Silent, because every response was a valid 200.

  • Products sits under Shop again, and this time it stays there. A post type's menu position was computed from its database id β€” 40 + id on three code paths and 60 + id on three others β€” so a type with the wrong id collided with Shop and the sidebar drew the tie in whichever order the database felt like. Nothing derives a position from an id any more.

  • Analytics drew an empty chart on Today, its default range: a single day is a single data point, and a line through one point with no markers is nothing at all. Today is plotted by the hour now, in the site's own timezone.

  • An options page, its menu and its guard now name the same permission.falcon_add_options_page() gave its menu manage_settings while the middleware guarded the page with manage_options_<slug> and the Roles screen listed neither β€” so a role holding Settings saw the menu and got a 403 from clicking it.

  • Role grants made under the old permission spelling are carried across. Two rules derived a menu's slug and disagreed about every child menu, so a permission could be granted that nothing ever checked. The migration only ever adds, never removes, and declines the handful of old names that two menus shared rather than guessing which was meant.

  • A term link follows the configured archive base, instead of the one written into the helper β€” which, on a site that had changed a base, sent every link the long way round through a redirect.

  • A menu item pointing at a category points at where that category lives now. The address was stored the day it was added; renaming the category left the menu on the old one.

  • Two menus may share a name. The slug was built straight from the name, so naming a second menu after an existing one put a duplicate-key stack trace on the screen.

  • Two forms with the same name no longer share a shortcode. The slug was made from the title without checking for a collision.

  • Product page scripts survive an out-of-stock product. The inline script bound a handler to an add-to-cart form that is not rendered when a product cannot be bought, and the throw took the description tabs down with it.

  • Two admin screens misdescribed a custom post type β€” the field-group location rule listed Post and Pages twice, once hard-coded and once from the table.


v2.7.1 ​

Released: 2026-09-15

Added ​

  • A custom post type can choose where it sits in the sidebar. ACPT β†’ Post Types β†’ Advanced Configuration β†’ Menu Position lists every menu in the dashboard; the type appears directly below the one you pick, joining that menu's section. The choice is remembered, so re-saving the type does not quietly send it back to the bottom.

  • The icon picker offers every icon the dashboard can draw. The Icons tab had 36 hard-coded pictures. It now has all 4,237 icons the bundled icon font can actually render β€” read out of the font itself, so nothing in the grid can come out as an empty box β€” with a search box over the whole set. A post type saved with a custom SVG keeps it until someone picks something else.

  • Forms can be renamed. The name was set once, on the create screen, and there was no way back to it, so a form called "test" stayed that way. The builder's heading is the field now: click it and type, and it saves with the rest of the form. The shortcode's slug deliberately does not follow the name β€” it is what every [falcon_form slug="…"] already on a page points at, so a rename leaves those pages working.

Changed ​

  • Shop and Products have a sidebar section of their own, headed eCommerce, the way ACPT heads Advanced. Selling is a job of its own: a site that sells nothing reads the heading and skips both items.

Fixed ​

  • Products sits under Shop again, and this time it stays there. A custom post type kept wedging itself between the two. The position of a post type's menu was computed from its database id β€” 40 + id on three code paths, 60 + id on three others β€” so a type with the wrong id landed on the same number as Shop, and the sidebar drew the tie in whichever order the database felt like. Nothing derives a position from an id any more: a menu is inserted after a neighbour that is actually there, which keeps every position unique, and Shop and Products are treated as one block that cannot be opened. Existing sites are repaired on update.

  • Analytics drew an empty chart on Today. Today is the default range, a single day is a single data point, and a line through one point with no markers is nothing at all β€” so the Traffic Overview card was blank however busy the site was. Today is plotted by the hour now, midnight to midnight in the site's own timezone, with the hours that have not happened yet left out so the line stops at the current hour instead of dropping to the floor.

  • Two forms with the same name no longer share a shortcode. The slug was made from the title without checking for a collision, so a second "Contact Form" got the same slug as the first and [falcon_form slug="contact-form"] rendered whichever of the two the query happened to return first.

  • The post and product editors said nothing when a save was refused. A failed validation redirects back with the reasons in the session, but neither editor printed them: the form came back filled in, nothing was saved, and the only clue was that the page had reloaded. A 150-character SKU went nowhere and said nothing. Both now show the list the page editor already did.

  • A variable product could not be published at all. The editor demanded a Regular Price for every product, and a variable product hides that field β€” each variation is priced β€” so Publish refused and pointed at a control nobody could see. Past that, the insert threw a 500 after the post row had already been written, leaving a product with no shop data priced at zero on the storefront. The parent now takes the cheapest variation's price, which is the figure the archive sorts and filters on, and the sale price follows only a discount on that variation. An empty variable product now says what is missing.

  • Per-variation weight and dimensions were lost when creating a product. store() dropped what update() kept, so a measurement typed while creating had to be typed again later.

  • The last shipping zone and the last tax rate could not be deleted. Both are repeaters, and a repeater with nothing left in it posts no fields at all; the save read that as "this form carried no zones" and kept the old ones. They now carry the same marker coupons already had, so an empty list arrives as an empty list.

  • Media URLs were rewritten relative to the editor's own address, which broke the moment the same content was viewed anywhere else. The editors keep the URLs the library hands them.

  • A closed coupon took as much height as an open form row β€” a 40px circle, a badge stacked above an 18px code, six units of air between cards. It is one line of information, so it now takes one line.


v2.7.0 ​

Released: 2026-09-08

Added ​

  • Custom column widths. Column and Nested Column β†’ Design β†’ Use Custom Width opens a slider for any width the preset fractions cannot express. The presets and the slider are the same setting, so only one is shown at a time, and going back picks the nearest preset rather than leaving the row with nothing selected. Per device, like the presets β€” a column can be 1/3 on desktop and 45% on mobile.

  • A Today range on Analytics, and it is now the default. The question that page is opened to answer is almost always "what is happening now"; a week's total is the wrong shape for it. The other ranges are unchanged and still one click away.

  • Landing-page menus follow the reader. A menu built from #pricing-style links now marks the item whose section is at the top of the viewport, scrolls smoothly when one is clicked, and stops short of a sticky header instead of leaving the heading underneath it. Both the theme header and the Layout builder's Menu element.

  • Hover Border and Hover Animation on the Button element. The border gains a hover width per edge and a hover colour, kept directly under the border they change β€” blank keeps the resting value, and 0 is a real answer. The animation offers Lift Up, Sink Down, Grow, Shrink, Glow and Pulse, and none of them for a reader whose system asks for reduced motion.

Changed ​

  • Analytics counts a visitor once a day, and again the next day. Counting distinct addresses across a whole range had fixed one fault and introduced its opposite: someone who came back on ten different days was still one address, so a month looked no busier than a day. Every figure now counts distinct (address, day) pairs, so the cards agree with each other. Over Today it is the same number it always was β€” which is why this only ever showed on the longer ranges.

    Longer ranges will therefore read higher than before on the same data. That is the correction, not a new fault.

  • New vs Returning is answered across the range. The old query only asked whether an address had been seen before the range began, so a reader who first arrived on Monday and came back every day counted as new all week. Their first day is new, the rest are returns, and the two still add up to the headline.

  • Active Pages lists every page the people here now have read, not only the page each of them is on at this instant. Each row counts people, so re-reading a page never counts twice.

  • Alignment on a full-width Button moves its label. A Full Width button already fills its row, so there was nowhere for Alignment to move it and the control looked broken. It now sets the text alignment inside the button. A button sized to its label is still placed within the row exactly as before.

Fixed ​

  • Importing layouts failed with a database error on any site that had ever deleted a header or footer. posts is unique on (slug, type, lang_code), but the import matched only slug and type and did so through the soft-delete scope β€” so a section in the bin was invisible to the check while still holding its key, and the insert was refused. The full key is matched now, a section in the bin is restored and reused, and a section that still cannot be placed is reported and skipped rather than taking the whole import down.

  • Every custom link in a menu was marked as the current page. An item saved as #pricing has no path of its own, and reading that as / made all of them match on the home page. The theme header and the builder's Menu element also answered the question separately and disagreed with each other; they now share one answer.

  • The unsaved-changes warning appeared when you pressed Save. Most of the admin saves by calling form.submit() from script, which fires no submit event β€” so the guard never saw the save and asked Leave site? at the exact moment the work was being written. It still warns when a tab with unsaved edits is closed, which is all it was ever for.

  • A Button's border could be invisible. Border Color was the only colour field in the panel that hid its opacity, so a border stored at 4% read as #aaa and drew nothing β€” and the canvas ignored opacity altogether, showing a solid border for one the site would not draw. Section borders had the same fault on the canvas.

  • Menu hover settings describe the current item too β€” border and border colour, as text and background already did.

  • The builder canvas and the site now draw a menu identically. Five properties were computed differently on each side, a cleared number field was handled differently, the canvas link inherited the line-height: 0 the editor puts on every element wrapper, and the editor's own padding and dashed border pushed the menu 5px in from where the site draws it.


v2.6.16 ​

Released: 2026-09-08

Fixed ​

  • Changing the navigation font under Typography β†’ Navigation had stopped working. v2.6.15 gave the Menu section its own Navigation Font Size and Font Weight; to have any effect those had to out-specify the typography rule, and doing so silenced it. Both Menu fields are gone again and Typography β†’ Navigation is once more the single place the navigation font is set. Menu keeps what typography does not own: text colour, hover colour, item padding and the dropdown colours.

v2.6.15 ​

Released: 2026-09-08

Fixed ​

  • Navigation Font Size and Font Weight work. v2.6.14 removed them instead of repairing them; both are back and applied. (Superseded by v2.6.16, which moved the navigation font to Typography β†’ Navigation for good.)
  • Dropdown Text Color reaches the mobile menu's sub-items, which were painted a fixed grey.

v2.6.14 ​

Released: 2026-09-08

Fixed ​

  • The Customizer's Menu settings did not reach the theme header. Navigation Text Color was emitted only once a Navigation typography had also been saved, so on most sites it had no rule at all; Menu Item Padding could not do anything because the navigation carried a fixed 32px gap; and the mobile menu was painted with hard-coded classes, so every one of these settings stopped at the desktop breakpoint. Defaults are unchanged, so a site that never opened these controls looks the same.
  • A layout slot switch asks for a state instead of a flip. A double-click, a retried request or a tab opened before the slot changed elsewhere could land on the opposite value β€” read as "I switched it on, reloaded, and it was off".
  • Falcon Builder β†’ Sections could fail with Undefined variable $errors, taking the whole page down with a 500.

v2.6.13 ​

Released: 2026-09-07

Fixed ​

  • A browser that has signed in before is no longer met by the 404. Since v2.6.7 /admin answers a visitor without a session with a 404, so that guessing the obvious path cannot reveal where the login page was moved to. That is right for a stranger and wrong for the site's own administrator: sessions last hours, work in a builder tab lasts longer, and nothing on the site links back to a login page they may never have written down. A bare 404 at that moment reads as a broken site rather than "sign in again".

    A browser that has completed a sign-in here is now sent to the login page instead, with Your session has ended. Please sign in again. It already knows the address, so it learns nothing it did not have; a browser that has never signed in still gets the 404.

    The marker is an ordinary Laravel cookie β€” encrypted and signed with APP_KEY, so it cannot be produced by anyone without the key β€” and it only changes what an unauthenticated visitor is shown. It never signs anyone in.

    On a shared computer it does mean the next person to open /admin reaches the login page. Signing out does not remove it, on purpose: after signing out deliberately, the next visit should still find the way back in.

  • Three pages sent new installs to the wrong address. The installation guide, the introduction and the home page all still said to visit /admin after installing β€” which, since v2.6.7, answers 404 and looks exactly like a failed installation. They now name the login URL the installer prints (/falcon-admin on a fresh install).


v2.6.12 ​

Released: 2026-09-06

Fixed ​

  • The per-minute graph in the Real-Time panel counted page views. It was the last figure on the analytics page still counting rows, so one person opening four pages inside a minute drew a bar four times too tall β€” beside a counter that correctly said one visitor.

    It counts distinct visitors per minute now, like everything else on the page, and the caption says Visitors per minute rather than Visits.


v2.6.11 ​

Released: 2026-09-06

Changed ​

  • Analytics counts people, everywhere. One visitor is one visitor, however many pages they open. That rule now holds across the whole page rather than in the few places it already did.

    Visitors, Visitors Today, Visitors This Month, the period-over-period change, Top Pages, Top Referrers, Traffic Channels, Traffic Sources and the Browser / Device / Operating System breakdowns all counted rows β€” one row per page view β€” so somebody reading four pages arrived as four. All of them count distinct visitors now, by IP address, which is the basis Unique Visitors always used.

    Page views have not been thrown away, because "how much was read" is a real question: the second tile is now Page Views, and the traffic graph still plots page views against visitors. It previously repeated the Unique Visitors figure, which became a duplicate of the headline once that started counting people.

    Tiles are named for what they hold β€” Visitors, Page Views, Visitors Today, Visitors This Month β€” so no figure claims to be people while counting pages.

    Which pages, referrers and sources appear is unchanged. Only the multiplied people are gone.


v2.6.10 ​

Released: 2026-09-06

Fixed ​

  • The Real-Time panel put one visitor on every page they had read. It said "1 active user right now" while the table beneath it listed six pages with one user each β€” the same person, placed on all six at once, reading as six people.

    A visitor is in one place at a time, so the panel is now built from one row per visitor: their most recent page view. Each person is counted once, on the page they are actually on, and the headline count and the table are derived from the same rows β€” so the column always adds up to the number beside the dot. Which pages are listed is unchanged; only the double-counted people are gone.

    This completes what v2.6.9 started: that release stopped a page being counted twice for one person, but still listed that person on every page they had passed through.

  • created_at on analytics rows compared as text, not as a moment, because the model disables timestamps and never cast it. Anything filtering those rows in PHP rather than SQL was comparing strings.


v2.6.9 ​

Released: 2026-09-06

Fixed ​

  • Analytics counted one person as many. Every card is fed from one row per page view, and four of them counted rows where they meant people: Visitors by Country, Top Countries, Active Pages, and the Live Visitors list β€” which showed the latest eight rows, so somebody reading eight pages filled it on their own and read as eight separate visitors from eight places.

    Those four now count distinct visitors. Nothing was slightly off: each figure was multiplied by however much each person happened to read, which is precisely the number a site owner uses to judge whether anything is working. Unique Visitors, New vs Returning and the live "active now" count were already right.

    Visits stay a count of page views, because that is a different and equally real question β€” Top Pages, Recent Visits and the traffic graph are unchanged.

  • A settings change could appear not to save at all. When the shared settings cache cannot be invalidated, the write lands in the database but every later request keeps reading the old value, so the setting silently reverts on the next page load β€” and starts working an hour later when the cache expires on its own. That failure was being swallowed. It is now logged, naming the usual cause: a cache file left owned by another user, which is what happens the moment anyone runs php artisan as root over SSH on a site that runs as www-data.

    If settings seem not to stick, check storage/framework/cache ownership β€” and prefer running artisan as the web user.

  • The real-time analytics feed could not run on SQLite, because its per-minute grouping used a MySQL-only date function while the rest of the page had already been written for both.


v2.6.8 ​

Released: 2026-09-06

Fixed ​

  • A site with an active plugin returned 500 on every front-end page after updating to v2.6.7. Plugins moved into resources/views/plugins in that release, and a security check that only allows a view under resources/views to render if it sits in themes/ or vendor/ had not been told about the new location β€” so the first plugin view a page rendered aborted the request mid-layout.

    It never showed up in development because that check quietly disables itself on a site with no resources/views/vendor directory: realpath() returns false for a directory that is not there, and PHP compares that false against '', which every path starts with. A site that has published views β€” which is any site that has been updated β€” had the check switched on and went down. Plugin views are now allowed explicitly, and the tests around it create that directory so this cannot pass unnoticed again.

  • Turning a layout slot off did nothing, and came back on after a reload. In Falcon Builder β†’ Sections, the switch for a slot with no section assigned to it reported success and drew itself off, but there was nothing to store, so the next page load showed it on again. The endpoint could not tell "nothing is assigned here" from "it is now off" β€” both were the same false. It now says which, so the switch stays honest, and a slot that has a section assigned toggles and persists as it always should have.


v2.6.7 ​

Released: 2026-09-06

Security ​

  • /admin no longer gives away the login page. The login URL can be moved off a guessable path in Settings, but any anonymous request to /admin was answered with a redirect to wherever it had been moved to β€” and /admin/login redirected there too. The one address an attacker is guaranteed to try was handing over the one address the setting exists to hide. To a visitor without a session the admin now simply returns 404.

    A signed-in administrator sees no change. The trade-off is that a session which expires mid-edit now ends in a 404 rather than the login form, so keep the login URL somewhere you can find it.

  • The wishlist no longer leaks the admin login URL either. Its "please log in" reply carried route('admin.login') β€” in JSON, to every anonymous visitor who clicked the heart. Shoppers sign in on the storefront account page, so that is where the wishlist now points, and it passes redirect_to so they come back to their wishlist afterwards instead of being stranded on the account page.

Added ​

  • A warning before you lose unsaved work. Close the tab or navigate away with changes you have not saved and the browser asks first. It covers the page builder, where it follows the same state the Save button does, and every admin screen β€” post, page, product, settings β€” through the shared layout.

    Deliberately quiet: only POST forms count, so typing in a search box never triggers it; only real typing counts, not values scripts set while the page loads; submitting clears it; and rich-text editors are asked directly whether they are dirty, since they type inside their own frame where those events never reach.

  • Nested columns are edited in place, and closed when you are done. A nested row now draws closed, with the same edit/add panel a container or column carries sitting on it. The pencil opens it; a Finished tick closes it again. While it is open the rest of the canvas dims and stops responding, so a click meant for the nested column cannot land in the section behind it, and no new container or column can be started on top of half finished work. Save arms when you finish, not on every keystroke inside.

    Closing puts the editing chrome away, never the design: a row with content in it keeps showing that content, and only an empty one falls back to a placeholder bar. Preview mode ignores all of it and draws the real page.

Fixed ​

  • The Card element ignored its Layout setting on the canvas. Grid, List, Masonry and Carousel all render through a stylesheet the element emits, and the builder sanitises the preview HTML before inserting it β€” which dropped that stylesheet on the floor. Every layout therefore looked identical while the front-end rendered them correctly. The CSS is now lifted out before sanitising and mounted as the preview's own stylesheet, so the canvas changes the moment you switch layout.

  • The Falcon Slider element showed nothing once a slider was chosen. Same cause, one step further: the live preview is an <iframe>, and the sanitiser removes those outright, so the canvas was left with an empty box. The preview frame is now rendered as a real element rather than passed through as markup.

  • A menu item that is only an anchor broke the header on PHP 8.1+. #section has no path for parse_url() to return, and the result went straight into ltrim() β€” a deprecation notice on every page with such an item. Along the way the active-state check learned three things it had never known: the Home item now highlights on the home page, a menu URL written with a trailing slash matches the page it points at, and a link to another site can no longer light up as the current page.

Changed ​

  • Plugins live in resources/views/plugins, alongside themes, instead of a plugins/ directory at the project root. php artisan falcon:update moves an existing install across β€” keeping each plugin's active state, data and migrations β€” and until it runs the old location keeps working, so updating the package on its own breaks nothing. Nothing at the destination is ever overwritten: a name that already exists there is left alone and reported.

v2.6.6 ​

Released: 2026-09-06

Added ​

  • Callout element Pro. The boxed aside that documentation runs on β€” note, tip, success, warning, danger and four more β€” in nine variants and six presets, from a plain accent bar to a solid header. It can be made collapsible, and when it is it uses a real <details>: it opens with the keyboard, and a browser's find-in-page opens it to show a match rather than reporting nothing. The body takes the same small markup the Table's cells do, so a callout can hold a bulleted list, `code`, a link or a button, and it holds text rather than HTML, so one can never carry a script.

  • Table of Contents element Pro. It reads the headings out of the page itself, so nothing has to be listed by hand and nothing goes stale when a section is renamed. Choose which levels to include, five presets, optional numbering, collapse by default, and a sticky mode that follows the reader down the page. The entry for the section being read is highlighted as it scrolls, and can carry its own background colour.

    Anchors are built from the heading text, including scripts whose letters carry combining marks β€” Bengali headings get real anchors rather than a string of dashes.

  • Previous / Next element Pro. Links to the pages either side of this one, ordered by a navigation menu or by date, with either side overridable by hand. It stays inactive on a page that has no Table of Contents, because "previous" and "next" only mean something inside a sequence a reader is actually following.

  • A button in a table cell. [button Buy now](/pricing), with :primary, :ghost and :soft variants β€” the missing half of a pricing or comparison table, which otherwise ends in a row of plain links.

  • Image Lightbox, in the Image element's General tab. The image opens full size on click, using the Gallery's lightbox rather than a second one. Turning it on puts the Link URL field away, and the page ignores any URL already saved there β€” an image that quietly went on navigating would look like the lightbox was broken.

  • Back to Top button, in Customizer β†’ Performance. On by default, with twelve settings: how far down the page it appears, which corner, size, corner radius, three icons, its own colours, an optional reading-progress ring and an option to hide it on phones. Turning it off sends nothing to the page at all β€” no markup, no stylesheet, no script.

  • Text Animation, in the Extra tab of the Title, Text Block, Button and Callout. Sixteen looping animations in three groups β€” motion, emphasis, and light and colour β€” with the speed, delay, repeat count, easing and accent colour all adjustable, and a default speed per animation rather than one speed for all of them. It is distinct from the Scroll Entrance Animation beside it, which plays once on arrival; the two can be used together.

  • Drag anywhere in the navigator. The tree lets a node be moved across branches now β€” an element from one column to another, a column into a different container, an element in or out of a nested column. A drop that would do nothing, or that would put a node inside itself, is refused rather than silently ignored.

  • Paste wherever the clipboard can land. What a copied node is now decides where it can go, rather than where it happened to be right-clicked. An element copied from a plain column goes into a nested one and back; a container can be pasted onto the bare canvas of a page that has nothing on it yet. The menu says what will land where, or why it cannot.

Changed ​

  • Email verification is off on a new install. A fresh install can be logged into straight away instead of waiting on a verification email from a site that has not been given a mail server yet. Turning it on afterwards works as it always did; existing sites are untouched.

Fixed ​

  • Letter spacing did nothing, anywhere. A bare number reached the stylesheet as letter-spacing: 2, which is not a length, so the declaration was dropped β€” the control had never worked on any element, the Table included since v2.6.4. Units for the shared typography controls now live in one place, so line height keeps being unitless while sizes and spacing get their px.

  • A quotation mark in any text setting truncated it. A caption reading He said "hi" was cut off at the first quote when saved. This was in the shortcode converter itself, so it affected every element with a text field, not one of them.

  • The Gallery and Image lightboxes did not cover the screen. A position: fixed overlay is only fixed to the viewport while no ancestor has a transform, a filter or a will-change β€” any of those makes that ancestor the containing block instead. The builder's own entrance animations set one on a wrapper around every animated element, so an image inside one opened into an overlay the size of its own column: the backdrop covered a corner of the page and the picture spilled out of it. Measured on a real page, 593px wide inside a 1200px window.

  • Maintenance mode did not hide the site. The check for who may still see it asked for a permission that is not a staff signal, and on a site whose subscriber role holds it, that was everyone. It asks whether the visitor is an administrator now, and admins browsing the site are shown a bar telling them maintenance mode is on, so it cannot be left running unnoticed.

  • The Heading element's settings panel was empty. Both tabs. It now has the content and design settings every other element has, and can be set to full width.

  • Anchor links now keep the trailing slash, so a link to a section reads /page/#section rather than /page#section. This covers every place a menu is drawn β€” the builder's Menu element, the navigation widget, and the theme's header, dropdowns and footer.

  • The Table of Contents entry being read is tracked by position rather than by an intersection band, which highlighted the second heading at the top of a page, never followed a click, and went blank in the middle of a long section. Its sticky mode works now too: it is applied to the column rather than to the element, which cannot travel outside its own box.

  • Callout lists render the same in the editor and on the page. The admin's stylesheet strips list markers and paragraph margins from everything, so bullets previewed flat and then arrived bulleted. Both renderers now load the same rules.

  • The Callout's icon is chosen from the icon picker rather than typed in as a class name.

Internal ​

  • Eleven new test files, and 147 more tests than v2.6.5 β€” 718 in all. Among them, the builder's inline script is now parsed by node on every run, and the parts of it that decide where a drag or a paste can land are lifted out and run against a real layout, which is coverage nothing in the suite had before: PHPStan does not read Blade templates, so none of that code was seen by anything until now.

v2.6.5 ​

Released: 2026-09-04

Fixed ​

  • The page builder returned a 500 on servers with short_open_tag enabled. The Code Block element added in v2.6.4 ships a sample snippet, and the sample was PHP, so the builder's script file contained the characters that open a PHP tag. Blade compiles a template by running PHP's tokenizer over it, so on a server where a bare <? opens code, everything below that point was handed back as PHP and passed through without being compiled β€” and the builder died with unexpected identifier "App" before drawing anything. Sites where the setting is off, which includes every development machine we build on, were never affected.

    The snippet is now joined at runtime, and the test that has guarded against this since v2.6.3 no longer only reads the templates: it compiles every one of them with the setting on and checks the result parses. That is the check that would have caught this, and it would equally have caught the sitemap fault behind v2.6.3.


v2.6.4 ​

Released: 2026-09-04

Added ​

  • Table element Pro. A real table in the page builder, with six presets, per-column alignment and width, an optional header row and header column, a caption, sticky headers and a max height. Readers can sort by clicking a header β€” numbers and versions sort as values, so 10 does not land before 9, nor v2.10.0 before v2.9.0. On phones a wide table either scrolls or turns each row into a card carrying its column names, because side-scrolling hides the first column, the one that says what the row is about.

    Cells take a small markup β€” `code`, **bold**, *italic*, [text](url), <br> β€” and [check], [cross] or [icon fas fa-star] for icons, which is what a comparison or pricing table is mostly made of. Cells hold text, never HTML, so one can never carry a script.

    Paste a Markdown table and it imports, alignment row and all, along with CSV and a spreadsheet paste, which is the difference between adopting the element and retyping a documentation site by hand. Rows and columns can be picked out with their own colour, and the header and body each take the same typography controls as every other element.

  • Code Block element Pro. Syntax highlighting for thirteen languages in five colour themes, with line numbers, highlighted lines, a window bar with the file name, word wrap and a max height. A copy button puts the original source on the clipboard rather than the numbered lines beside it, and says so when a browser refuses to copy instead of sitting there looking dead.

    Highlighting happens on the server, so a visitor with JavaScript off still gets a coloured, selectable block. Two reveals are available on top of the builder's own entrance animations: a typewriter that types the snippet out character by character, and a line-by-line fade. Both stand aside for prefers-reduced-motion.

  • Head HTML in Appearance β†’ Customize β†’ Custom Scripts. The two existing script fields take JavaScript and are wrapped in a <script> tag, which left nowhere to put the things a site needs in its head that are not script: a Search Console or Facebook verification <meta>, a <link>, or a loader that arrives as <script src="…"> β€” which is how Google Tag Manager, Meta Pixel and Lemon Squeezy are all published. Sites had to edit a theme file, and the next update overwrote it.

Fixed ​

  • DOMPurify was missing from the package. The builder loads it and guards against its absence, so nothing ever appeared broken β€” it simply fell back to unguarded innerHTML, which means client-side sanitising in the canvas has never actually run, on any site. The library is now shipped, and reaches existing sites on the next update.

  • Changing the login or registration URL did nothing on a live site. Both slugs are read while routes are being registered, and a site with cached routes never runs that file β€” so the setting saved, the new URL returned 404 and the old one carried on working, with nothing to say a cache was in the way. Every production install caches its routes, so this affected all of them. Saving either slug now rebuilds the route cache, and a site without one is left alone.


v2.6.3 ​

Released: 2026-09-04

Fixed ​

  • The sitemap returned a 500 on any server with short_open_tag enabled. Blade does not read a template as plain text β€” it runs token_get_all() over the source and applies its directives only to the inline-HTML tokens that come back. Where short_open_tag is On, PHP's tokenizer treats the <? that opens an XML declaration as the start of PHP code, so the rest of the template was handed back as PHP tokens and written to the compiled view uncompiled. Visitors got a parse error instead of a sitemap. The declaration is now assembled from pieces so those two characters never sit together in the file. The template renders identically either way; only servers with short_open_tag=On were affected, which is why it never appeared in local development.
  • A guard now scans every Blade template in the package for the same hazard, so no future template can be served uncompiled on those servers.

v2.6.2 ​

Released: 2026-09-03

Fixed ​

  • The sitemap returned a 500 for the whole site when it met a post with no timestamps.lastmod was written unconditionally, so updated_at being null ended the response β€” and with it every URL in the file. Content that arrives through the WordPress importer, a seeder, or a raw insert can have no timestamps at all. lastmod is optional in the sitemap spec, so it is now emitted only when there is a date, falling back to created_at before being left out entirely. Nobody sees this failure while it is happening β€” it is fetched by search engines, not people β€” so the site simply stops being crawled.
  • A post with an empty slug no longer appears in the sitemap. Its <loc> resolved to the site root, so the home page was listed once more for every such row.
  • The category and tag sections are skipped when a site has removed those archive routes, rather than failing to generate a URL for a route that is not there.
  • The sitemap query now selects only the columns the file actually uses, instead of hydrating every column of every published post on the site.

v2.6.1 ​

Released: 2026-09-01

Added ​

  • Section Separator element. A divider you can drop into any column, with 61 styles in three families: 8 CSS line styles, 15 repeating SVG patterns, and 37 full-width shape dividers (waves, hills, clouds, mountains, grass, arches, aurora and more). Text or an icon can sit on the line, positioned left, centre or right. Shapes take a height, can be flipped horizontally or inverted, and layered shapes carry their own opacities.
  • Custom SVG shapes. Pick an SVG from the media library and its artwork is inlined on the element, so the separator colour, height and flip reach it. The markup is sanitised on the way in and again on render.
  • SVG uploads are now a site decision. SVG was refused outright before, even though Customizer -> Performance -> Allowed Upload Formats offered it. It is now governed by that setting, is off unless a site names it explicitly, and whatever is kept has been rewritten through the sanitiser first, so an SVG in the library cannot carry a script, an event handler or a javascript: link. The same rule applies to a backup restore.

Fixed ​

  • The builder canvas added height a published page never had. Blade partials that began with a UTF-8 byte-order mark emitted it into the page; a BOM is not whitespace, so each one formed a text line inside the element wrapper. A nested row was pushed about 24px down its column and the column's background showed as a band above it, with every padding set to 0. The mark is gone from 29 templates, and the wrapper is now a flex container so stray whitespace cannot do the same again.
  • A column's hover effect (Lift, Zoom, Glow, Fade) was applied to the outer box while the card's background, radius and padding live on the inner one. The lift shadow was drawn square around a rounded card, and hovering the empty area beside the card still triggered it.
  • A nested row carried a 1px transparent border and a flex-basis: 100% that, in a column-direction flex parent, asked it to be as tall as the whole column.

v2.6.0 ​

Released: 2026-08-28

Changed ​

  • Requirements are now Laravel 13+ and PHP 8.3+. The package previously declared support for Laravel 10, 11 and 12 and PHP 8.1, but only Laravel 13 was ever exercised by the test suite. The Composer constraints, the CI matrix and the documentation now all state the versions FalconCMS is actually built and tested against. Existing sites on an older Laravel are not broken β€” Composer simply keeps them on the last release that matched their framework.
  • The CI test and syntax matrices run on PHP 8.3 and 8.4, and orchestra/testbench is pinned to ^11.0, the release line that targets Laravel 13.

Fixed ​

  • Every documentation page rendered a literal %s in its browser title (for example Installation | %s | FalconCMS). The site's titleTemplate used printf syntax instead of VitePress's :title placeholder.

Documentation ​

  • The documentation homepage now links into the docs from every feature card, and adds sections covering installation, custom post types, the builder, e-commerce, plugins, the hook API, requirements and a grouped documentation map.
  • Added a Plugins feature card, a Live Demo call to action, and a card-based "Explore the Documentation" link map.
  • Added page metadata across the site β€” canonical URLs, Open Graph and Twitter tags, and SoftwareApplication / WebSite structured data on the homepage.
  • Enlarged the homepage hero image and reduced the hero heading size.

v2.5.0 ​

Released: 2026-08-28

Added ​

  • Column Order field β€” rearrange a column, or a nested column, visually per breakpoint from the General tab. Desktop, Tablet and Mobile can each have their own order without moving the column in the document, so tab order and screen readers are unaffected.
  • Full icon library in Menu Item Options β€” the icon picker for menu items now offers every icon the builder ships (Font Awesome, Bootstrap, Remix, Boxicons, Lucide β€” ~10,000 icons) instead of a curated subset of about a hundred, with paging so the grid stays fast.

Fixed ​

  • The builder canvas could render a menu's text in the wrong font β€” both a broken Google Fonts request for a custom font, and reading the theme's body font instead of its Navigation font for "Inherit".
  • Desktop preview in the canvas could be narrower than a real desktop, so content spilled past its own column; the canvas now matches the theme's real desktop breakpoint.
  • Cart / Search / Wishlist menu items ignored a custom icon chosen for them, and the count badge ignored the Customizer's Primary Color.

v2.4.0 ​

Released: 2026-08-12

Added ​

  • Shop archive filters β€” a sidebar with product search (title, excerpt and SKU), a dual-handle price range slider, categories, attributes, In stock only and On sale. Filtering happens over AJAX and rewrites the address bar, so a filtered view is a real shareable URL and the back button behaves. With JavaScript switched off the panel is a plain GET form and every filter still works.
  • Attribute filters β€” whatever attributes your products declare appear in the sidebar automatically, with counts. Each attribute gains a Show in filters switch next to Visible on the product page, so a noisy attribute can be kept out of the sidebar while still showing on the product page.
  • "Visible on the product page" now does something β€” ticked attributes appear in the Additional information table. The setting was previously stored but never read.
  • Weight-based shipping β€” shipping zones gain a Weight Based (Per Weight Range) calculation type, banded exactly like the quantity rates. Product weights finally feed into the shipping cost.
  • Customer address book β€” customers save addresses under My Account β†’ Addresses, with separate defaults for billing and shipping. Checkout is pre-filled server-side, and a picker appears when more than one address is saved.
  • Upsells and cross-sells β€” chosen per product in a new Linked Products tab. Upsells show on the product page, cross-sells in the cart. Related products are now drawn from the product's category instead of "the four newest products in the shop".
  • Product structured data β€” product pages emit schema.org JSON-LD: Offer for simple products, AggregateOffer for variable ones, plus availability and star ratings. This is what puts price and stock into a Google result.
  • falcon:reindex-attributes β€” rebuilds the attribute filter index. Only needed after a bulk import or a direct database edit; ordinary saves keep it current.

Fixed ​

  • Cart prices are re-read from the catalogue on every cart, checkout and order. They used to be frozen at the moment an item went in, so an ended sale β€” or a price the shop owner had since corrected β€” never reached a basket that already existed.
  • An expired sale stops applying the moment it ends, rather than whenever falcon:expire-sales next runs. The stored sale price is left untouched, so the figure is still there when the shop owner extends the sale.
  • Variable products report stock from their variations. Selling the last of every size no longer leaves the product advertising itself as in stock. The In stock only filter follows the same rule, so the badge and the filter cannot disagree.
  • Variable products show a price range (ΰ§³1,500 – ΰ§³2,500) instead of the parent row's 0.00.
  • The shop grid applies the tax display conversion. With prices entered without tax and displayed with it, a product used to cost one thing on the shop page and another on its own page.
  • Product type is no longer split across two columns. shop_products.type and .product_type had drifted apart β€” the editor only wrote one of them β€” so a product could read as variable on the storefront and simple in the admin. Both are written now and a migration reconciles existing rows.
  • "Enable tax rates and calculations" could not be ticked from the General tab: the same field was posted twice by one form and the Tax tab's hidden value won.
  • Unchecking "Show in filters" now sticks. An unchecked box submits nothing, and the stored '0' reads as truthy in JavaScript.
  • Shop sits directly under Products in the admin menu, and custom post types are numbered above the pair so a new one cannot come between them.
  • Cart layout: Update cart keeps its place when coupons are switched off, and the cart and checkout buttons share one hover treatment.

Upgrading ​

Run php artisan migrate after updating. Ten migrations ship with this release; eight only add tables or columns. Two adjust existing rows β€” the product type reconcile and the admin menu order β€” and both are reversible. Nothing is demoted: a product that was being treated as variable stays variable.


v2.3.0 ​

Released: 2026-08-05

Added ​

  • Content Box element β€” a repeater element with eight layouts: Classic Icon With Title, Classic Icon On Top, Classic Icon On Side, Classic Icon Boxed, Clean Layout Vertical, Clean Layout Horizontal, Timeline Vertical and Timeline Horizontal. Each box carries its own icon (or image), title, rich content, background and Read More link; the element adds column count, alignment, link type (text or button), link area (the Read More link or the whole box), and full typography, box and timeline-rail styling. Layouts collapse to two columns on tablet and one on mobile.
  • Four more icon libraries β€” Bootstrap Icons, Remix Icon, Boxicons and Lucide join Font Awesome, taking the picker from 2,060 to 10,115 icons. They cost nothing until used: the builder fetches a library's icon list and stylesheet only when its tab is opened, and a page loads a library's stylesheet only when that page actually contains one of its icons.
  • Font Awesome icons are findable by their older names. Font Awesome keeps every previous name working as an alias of the current one, but the picker only listed current names β€” so searching "ambulance", "trash-alt" or "shopping-cart" found nothing even though the icon was right there. 1,102 alias names are now searchable, read from the shipped stylesheet.
  • Taxonomy dynamic sources. A new Taxonomy text source prints a post's terms β€” pick a post type, then one of its taxonomies, with separator, term limit and fallback β€” and a matching Taxonomy URL link source points an element at the term's archive. The post type and taxonomy must both match, so one template can be reused across post types safely.
  • Icon Box β€” Read More typography. The Read More link now has its own font family, size, weight, line height, letter spacing, transform, colour, hover colour, arrow toggle, and controls for its distance from the description and the gap before its arrow.

Fixed ​

  • Every font picker in the builder is searchable. Icon Box, Accordion, Tabs, Ticker, Post Meta and every ACPT custom field still used a plain dropdown of ~1,700 fonts; they now use the same searchable picker as the Title element.
  • Front-end now loads every font the builder can choose. Font collection ran off a hard-coded list of setting keys, so fonts picked for Read More, sub/mobile menus, Post Meta and custom fields were never loaded and silently fell back to the theme font. Detection is now by key name and walks nested layouts, header/footer sections are included, the full 100–900 weight range is requested (Thin and Extra Light used to be missing), and families the bundled catalog doesn't know are dropped β€” one unknown family made Google reject the whole request, which had been taking every font on the page down with it.
  • Post Meta no longer 500s a page. Placed directly on a page or post, the element hit an undefined $post and Blade's error handling reported it as "Cannot end a section without first starting one", which pointed nowhere near the cause.
  • Hover colours are visible in the builder again. Icon Box's Read More hover colour and Breadcrumb's link hover colour rendered on the front-end but looked dead in the canvas, since an inline style can't express :hover.
  • Element panels always open on their first tab. After working in one element's Design tab, the next element you opened β€” a duplicate most visibly β€” also opened on Design.
  • The icon picker's search box no longer carries over. A query typed for one element used to filter the icon grid of the next element you opened.
  • Boxes with a background or border get room inside them. Content Box items whose padding was never set sat flush against their own border, with the icon and Read More link crossing it.

v2.2.7 ​

Released: 2026-08-04

Fixed ​

  • Pro builder options no longer show as locked on a licensed site. The builder's Pro-edit flag was set only by the page/section builder screen, so the Post Card builder and Mega Menu builder β€” which share the same builder scripts β€” read it as missing and locked every Pro element (accordion, tabs, counter, gallery, ticker, breadcrumb, star rating, HTML, card, icon box, icon list, menu, advanced search), dynamic content and global sections even with a valid license. The flag now lives in the shared builder partial, so every builder screen answers from the license.
  • Card element now fills its column on the front-end. A column's inner box is a column-direction flex container whose default content alignment is flex-start, so the card element was sized to fit-content: the cards collapsed to their text width and the row left dead space on the right β€” while the builder canvas (which wraps the same markup in a full-width div) looked correct. The card element now stretches to the column like every other layout block, for grid, list, masonry and carousel alike.

v2.2.6 ​

Released: 2026-08-01

Changed ​

  • Pro is a one-time, perpetual license. Paid Pro features never expire β€” a purchase is owned forever. A license's expiry now only limits updates: when the update window ends, the site keeps every Pro feature and simply needs a renewal to pull newer Pro releases. Refunded/disabled licenses still revoke access. The free core (including e-commerce) stays free for everyone, always β€” licensing never touches it.
  • The License and Updates pages now show "Update window ended β€” features stay active, renew for updates" instead of looking locked out, and the Pro update button is gated by the update window rather than by raw license validity.

v2.2.5 ​

Released: 2026-07-31

Added ​

  • Icon Box β€” Read More link. A Read More / Learn More link can now be shown under the description (text + URL), rendered only when set.
  • Icon Box β€” Link Mode. Choose what the link applies to: Full Box, Only Icon, or Only Title. Defaults to Full Box, so existing icon boxes are unchanged.

Fixed ​

  • Counter animation no longer disappears. The count-up script is now emitted with every Counter and self-dedupes in JavaScript, instead of being gated by a render-once guard that a hidden/earlier render pass (Layout Builder sections, meta/excerpt, nested renders) could consume β€” which stripped the script from the visible page and left the number static.
  • Pro update stops cleanly on read-only vendor files. The Pro updater's pre-flight check now also verifies vendor/falconcms/pro is writable, so a containerised install with a root-owned vendor tree aborts up front (with the exact chown fix) instead of letting Composer half-modify composer.json mid-update.

v2.2.4 ​

Released: 2026-07-31

Fixed ​

  • Boot-seeder no longer crashes when a storefront page was trashed. The default-content seeder now matches on the full unique key (slug + type + language) and ignores global scopes, so a soft-deleted Shop/Cart/Checkout/Account/Blog page is found (and restored) instead of re-inserted. Previously a trashed shop page made the seeder hit a duplicate-slug constraint on boot β€” on containerised installs this could crash-loop the app container (502 Bad Gateway). Each create is now wrapped so the seed can never fail the boot.

v2.2.3 ​

Released: 2026-07-31

Added ​

  • All Google Fonts everywhere. Typography pickers now list the full Google Fonts catalogue (~1,900 families, grouped by category) instead of a short hand-picked set β€” in the Customizer and in every Falcon Builder element. Each font shows its own real weights, and fonts load on demand.
  • Searchable font picker in the Builder. The element font-family control is now a searchable dropdown (like the Customizer), so you can type to find any font.
  • One shared font source. A single falcon_google_fonts() catalog feeds every typography UI β€” add a font once and it appears everywhere, no per-place lists to sync.
  • Title element supports inline HTML. Markup typed into a Title (e.g. <b>, <span style>, <br>) now renders on the canvas and the front-end instead of showing as text.

Changed ​

  • Customizer URL simplified β€” /admin/appearance/customizer is now /admin/customizer.

Fixed ​

  • E-commerce is part of the free core (carried from v2.2) β€” no Pro licence required.

v2.2.2 ​

Released: 2026-07-31

Fixed ​

  • Update no longer reports "completed with errors" when the shop pages already exist.falcon:update's e-commerce page creation now matches on the full unique key (slug + type + language) and ignores language scopes, so existing Shop/Cart/Checkout/ Account pages are found instead of re-inserted (which hit a duplicate-slug constraint).

v2.2.1 ​

Released: 2026-07-31

Added ​

  • In-dashboard Pro updates. Dashboard β†’ Updates now shows a FalconCMS Pro card alongside the core one: it detects a newer Pro release (via a public version manifest, since Pro is a private package), flags it with a NEW badge in the sidebar, and offers a one-click Update Pro Now button. The update is licence-gated β€” a valid, in-date subscription is required; an expired licence is prompted to renew instead of updating. On success, Pro's boot-time sync delivers any newly-bundled code and plugins (e.g. Falcon Slider) automatically.

v2.2 ​

Released: 2026-07-30

Changed ​

  • E-commerce is now part of the free core. The complete shop system β€” products, variants, cart, checkout, orders, coupons, reviews and wishlist β€” no longer requires a Pro license. It works on every FalconCMS site, free forever. (Multi-language, analytics, the advanced builder, custom fields and Falcon Slider remain Pro.)

Added ​

  • Falcon Slider β€” a new Pro plugin: a layer-based, Slider-Revolution-class slider builder. Design slides on a full-screen visual canvas with:

    • Layers β€” text (with SEO h1–h6 tags), image, button, shape, icon, video (self-hosted / YouTube / Vimeo), audio, live countdown, and raw HTML/embed.
    • Per-layer timeline animation β€” 15 entrance/exit presets, text reveals (typewriter / split chars / split words), idle loops (float / bob / pulse / sway / spin), and per-layer delay Β· duration Β· easing.
    • Backgrounds β€” colour, gradient, image, background video, colour & gradient overlays, Ken Burns and mouse parallax.
    • Responsive β€” position, size, font-size and visibility per device (desktop / tablet / mobile), plus layer groups and global (every-slide) layers.
    • Navigation β€” arrows, bullets, progress bar, thumbnails, autoplay, loop and pause-on-hover; auto / full-width / full-screen sizing.
    • Productivity β€” pre-built template gallery, save-as-template, duplicate, import / export, version history (auto-snapshot on every save, 20 kept), full-screen live preview of unsaved changes, and whole-slide links.
    • Performance β€” LCP background preload, layout-shift-free reservation, lazy media, and subset font/icon loading for Core Web Vitals.
    • Embed with the [falcon_slider id="…"] shortcode or the Falcon Slider Falcon Builder element. Governed by the manage_sliders permission.

    See the Falcon Slider documentation.


v2.0 ​

Released: 2026-07-14 Β· current release v2.1.0

FalconCMS is now open-core. The core stays free and MIT-licensed; a new Pro edition unlocks the commercial features (e-commerce, multi-language, analytics, the advanced page builder, custom fields and advanced login). Existing sites keep working β€” nothing is taken away β€” and there is a launch grace window during which every Pro feature stays free. Features a site already used are grandfathered free on that site forever.

Added ​

  • Pro License page (Falcon Builder β†’ License). Paste your license key to activate Pro, deactivate to release it, or hit Re-check now to re-validate on the spot. Each key is enforced per site (Pro = 1 site, Agency = unlimited).
  • One-click Pro install. Paste the access token from your purchase and FalconCMS writes auth.json and installs the falconcms/pro package for you β€” no terminal needed. Manual Composer instructions remain as a fallback.
  • In-app updater (Dashboard β†’ Updates). Check for and install the latest release from the browser, with a backup confirmation and a clear progress dialog.
  • Freemium grace β€” a single fixed cutoff date (not a rolling per-site window), so the transition happens everywhere at once.

Changed ​

  • The "now freemium / upgrade to Pro" banners (admin and cart) disappear once a site holds a valid Pro license.
  • Renamed the internal version constant to FALCON_CMS_VERSION.

Fixed ​

  • Reliable updates & version reporting. The updater installs the exact latest release and reports the installed version correctly β€” no more "update available" immediately after updating.
  • Shop product category now shows on the shop listing (some products previously read "Uncategorized"), with the category eager-loaded to avoid N+1 queries.
  • Clear license messages β€” invalid key, activation-limit-reached and expired keys now say exactly what's wrong and how to fix it, instead of a generic notice.
  • Updating core ahead of the Pro package no longer causes a fatal error.

Extensibility update. FalconCMS also gains a full plugin system β€” the functional counterpart to themes β€” plus a runtime API for adding admin menus, settings pages and settings fields without writing controllers, routes or views, and a security hardening pass on how settings are saved.

Added β€” Plugins & extensibility APIs ​

Plugin system β€” see Plugins

  • Drop-in plugins. A plugin is a folder in plugins/ with a plugin.json manifest and an optional plugin.php bootstrap. Free and unrestricted β€” anyone can write, install and share them.
  • Plugins admin screen with two sub-pages: Installed Plugins (filter by All / Active / Inactive, search, and Activate / Deactivate / Update / Uninstall from row actions) and Add New (drag-and-drop .zip upload, or install from a direct URL).
  • Convention-based loading. src/ is PSR-4 autoloaded, routes/web.php is registered, resources/views/ becomes a slug:: namespace, and database/migrations/ runs on activation β€” no ServiceProvider needed (though one can be declared).
  • Lifecycle hooks β€” optional activate(), deactivate(), uninstall() and upgrade($previousVersion) on a class named in the manifest.
  • Dependencies β€” declared plugins must be active first, are loaded in dependency order, and can't be deactivated or uninstalled while depended upon.
  • Update detection β€” a newer version on disk than the one activated shows Update available; applying it runs new migrations and records the version.
  • Requirement checks on activation for requires_php and requires_cms.
  • Fatal-safe loading β€” a plugin that throws while loading is automatically deactivated and logged instead of taking the site down. A plugin that fails to load is never marked active.
  • CLI: plugin:list, plugin:activate, plugin:deactivate, and make:plugin "Name" to scaffold one.
  • manage_plugins permission, assignable to any role.

Admin Menu API β€” see Admin Menu API

  • falcon_add_menu_page() / falcon_add_submenu_page() register sidebar items at runtime, merged into the DB-driven sidebar so they survive falcon:update.
  • falcon_add_options_page() renders a complete settings page β€” fields, saving and all β€” from an array. Supports a tabbed layout with deep-linkable ?tab=.
  • New falcon_admin_menu action for deferred registration.

Settings Fields API β€” see Settings Fields API

  • falcon_add_settings_field() injects fields into the existing settings screens β€” General, SEO, REST API, Integrations and Shop β€” rendered as native rows and saved by that screen's own Save button.
  • falcon_add_settings_tab() adds a new top-level tab to the Settings nav, with its own page at /admin/settings/{id}.
  • 18 field types: text, number, email, password, url, textarea, checkbox, select, radio, color, date, range, multiselect (searchable, chip-based), tags, image, file, wysiwyg and repeater.
  • Shop fields can target a specific Shop settings tab.
  • New falcon_register_settings action, plus form hooks for the REST API, Integrations and Shop screens.

Changed β€” Plugins & extensibility ​

  • Plugin routes are registered before the frontend catch-all, so plugin URLs resolve instead of falling through to a 404.
  • Themes and plugins now load at the same point in the boot cycle, giving plugins access to every hook a theme has β€” including register-time filters.
  • The dashboard's built-in documentation viewer was removed; the documentation site is the single source of truth.

Security ​

  • Protected options. Internal keys β€” falcon_license_* and falcon_grandfathered_features β€” can no longer be written through settings saves, injected fields or options pages. Previously a crafted settings request could overwrite the cached license state and unlock Pro features.
  • URL scheme validation on image and file fields: only http, https and relative paths are rendered, blocking stored javascript: payloads.
  • Identifier sanitisation β€” field and tab ids are restricted to A–Z a–z 0–9 _ - before reaching markup or inline scripts.

Fixed β€” Plugins & extensibility ​

  • Shop settings nav highlighted two tabs at once (a static class fought the reactive one).
  • The Installed Plugins sidebar item no longer stays highlighted while on Add New.

v1.8.3 ​

Released: 2026-07-04

A Layout Builder fix: every layout's every section now toggles fully independently.

Fixed ​

  • Layout sections are now independent per layout. Enabling a section (notably Content) in one layout no longer makes it appear active in the Global Layout too. The Layout Builder was falling back to "the first published section" for any slot the Global Layout hadn't explicitly assigned, which made a section enabled elsewhere show up as active on Global. Each slot of each layout now reflects only its own assignment and on/off state β€” matching what the frontend renders.

v1.8.2 ​

Released: 2026-07-04

A Layout resolution refinement: header, title bar and footer now cascade cleanly from the custom layout down to your defaults, so content is never left without chrome.

Changed ​

  • Layout slots now cascade: custom layout β†’ Global Layout β†’ theme default. For content matched by a custom layout, if its Header/Title Bar/Footer is toggled off or left unassigned, the slot now inherits the Global Layout's header/footer for that content. If the Global Layout has nothing selected either, the theme's built-in default renders β€” everywhere (frontend and the builder canvas preview). This supersedes v1.8.1's "disabled slots render nothing": a slot with no active assignment always falls through to the next level rather than showing blank space.

v1.8.1 ​

Released: 2026-07-04

A builder-experience & polish release: the page/post builder canvas now previews the real header, page title bar and footer around your content, plus fixes for headings in the classic editor and the admin Customizer menu placement.

Added ​

  • Live header / title bar / footer preview in the builder β€” when you design a page, post, CPT or product (not a Layout template), the canvas now shows the actual Header, Page Title Bar and Footer that the applicable Layout assigns to it, rendered through the real theme so it looks like the live page. They're read-only here β€” hover shows an Edit … Layout Section button that opens that section in the Layout Builder. A slot is previewed only when it's enabled in the layout.

Changed ​

  • Rich Editor headings β€” the Paragraph / Heading 1–6 dropdown is back in the classic editor (it was using a removed TinyMCE 5 control name).
  • Customizer now lives under Falcon Builder on existing sites too β€” a migration moves the Customizer menu item out of Appearance and under Falcon Builder (fresh installs already got this); a legacy "Lazy Builder" menu is renamed to Falcon Builder.
  • Disabled Layout slots render nothing β€” when the Layout Builder is in use, a header/title-bar/footer that is toggled off or unassigned no longer falls back to the theme's built-in chrome (on the frontend and in the builder preview).

Fixed ​

  • Classic-editor headings now use your Customizer heading sizes instead of shrinking to paragraph size (Tailwind's preflight was overriding bare h1–h6; the page builder was already unaffected).
  • Hairline gap between the page content and a full-width footer (a 1px sub-pixel seam showing the body background) is gone.
  • Fixed an infinite recursion that could return a 500 when a page is rendered as its own content (e.g. the Home page inside its assigned footer).

v1.8.0 ​

Released: 2026-07-03

A major builder release: a dedicated Layout Builder for site-wide templates, a new Bread Crumb element, dynamic image backgrounds for containers and columns, and a far more consistent Site Width / Full Width system.

Added ​

  • Layout Builder β€” design site-wide Header, Footer, Page Title Bar and Content templates in the Falcon Builder and assign them globally or by condition. Includes an in-card layout picker, a conditions modal (target a custom layout to specific pages, post types or archives), a per-layout enable/disable toggle (AJAX), and Export / Import of layouts.
  • Custom 404 page β€” build your own "Not Found" page in the Layout Builder; the theme renders it automatically.
  • Bread Crumb element β€” a new builder element that outputs the current page's breadcrumb trail (Home β†’ post type / category β†’ current page), with full typography, colour, separator and alignment controls, plus Schema.org BreadcrumbList structured data for SEO.
  • Dynamic image backgrounds β€” containers, columns and nested columns can now use a dynamic source (Feature Image, Author Avatar or Site Logo) as their Background Image, resolved per-post on the frontend. It layers correctly beneath a Background Gradient, and the builder canvas previews it too.

Changed ​

  • Consistent Site Width / Full Width β€” a container set to Site Width now always constrains to your Customizer Site Width (centered), independent of the Customizer's Boxed/Wide layout, and matches the builder canvas exactly. Full Width containers always span edge-to-edge.
  • Customizer moved under Falcon Builder β€” Appearance β†’ Customize now lives in the Falcon Builder menu; the sidebar's "Lazy Builder" was renamed to Falcon Builder with corrected submenu links, and the standalone Header/Footer builder entries were removed (they live in the Layout Builder now).
  • Product sorting on the shop and product archives only appears when products actually exist.
  • Hardened ACPT import/export β€” re-imports are idempotent, taxonomy terms keep their cpt_slug, and post export is more complete.

Fixed ​

  • The Post Content element set to Full content no longer breaks plain/classic content out to the viewport edge β€” it now respects its parent container's width (it still full-bleeds when the content is itself a builder layout with self-boxing sections).
  • Dynamic backgrounds render inline (no lazy-load dependency) so they paint reliably; the builder canvas shows a neutral "Feature Image" placeholder when editing a template that has no specific post, instead of an unrelated image.

v1.7.4 ​

Released: 2026-06-30

A portability & accounts release: import/export for forms and builder-library items, an email-verification toggle, and a much smarter media backup/restore. Now officially runs on Laravel 13 as well.

Added ​

  • Form import/export β€” every form can be exported to a portable .json file (structure + settings) and imported on any FalconCMS site as a new form, straight from the Forms list
  • Post Card & Mega Menu import/export β€” builder-library items export to .json and import back as new items (with fresh IDs), so designs move easily between sites
  • "Require email verification" toggle β€” Settings β†’ Membership now lets the site owner choose whether new users must verify their email before signing in, or are logged in immediately after registering

Changed ​

  • Smarter media backup & restore β€” a media-only backup now bundles the Media Library records too, so restoring brings the library entries back (not just the files); restore also auto-detects and strips a wrapper folder (e.g. when a downloaded backup was unzipped and re-zipped), and preserves the full Year/Month folder structure
  • Deleting a media item now removes its generated size variants too (e.g. image-300x200.jpg), matching WordPress β€” files that are tracked as their own media item are left alone
  • Honest registration feedback β€” if the verification email can't be sent, registration now says so plainly instead of falsely claiming a link was sent
  • Laravel 13 support β€” added to the documented requirements (Laravel 10, 11, 12, or 13)

Fixed ​

  • Media-only restore now places files at their correct paths (including the media/ sub-folder) instead of flattening them

v1.7.3 ​

Released: 2026-06-30

A tooling & migration release: a new Export/Import pair, one-click Clone for every content type, a smarter Backup tool, plus several builder, security and migration fixes.

Added ​

  • Tools β†’ Export β€” a feature-driven export screen: it lists every registered post type, taxonomy and the media library automatically (so future exportable features appear on their own) and downloads a WordPress-compatible .xml (WXR) file. Pick All content or a single source
  • Tools β†’ Import β€” the counterpart to Export: upload an export .xml and it restores posts, pages, custom post types and taxonomy terms (also accepts standard WordPress WXR files)
  • Clone for posts, pages, products & CPTs β€” every list row now has a Clone action (next to View) that duplicates the item β€” and its taxonomies, custom fields and (for products) shop data, variations & downloads β€” into a fresh draft
  • Duplicate menu β€” the menu editor gains a Duplicate Menu action that copies a navigation menu with its full item hierarchy (the copy is never auto-assigned as header/footer)

Changed ​

  • Backup tool reworked β€” one Create Backup button with three choices: Only Database, Only Media, or Database + Media (a single archive carrying both). Restore is now content-aware β€” it detects from the file itself whether to restore the database, the media, or both, so a whole site can be moved to another install with one file. Uploaded backups are detected the same way
  • Live gallery hover effect on the canvas β€” the Gallery element's Zoom hover now previews in the builder, matching the front end
  • Column / nested-column hover effects now work on the front end β€” Zoom / Lift / Glow / Fade hover types rendered only in the builder before; they now render on the published page too
  • Buttons without a link render cleanly β€” a Button with an empty Link URL no longer outputs an empty <a> tag or a pointer cursor; any value (including #) makes it a real link again
  • Clearer import results β€” re-importing items that already exist now reports them as skipped (including taxonomy terms) with an explanatory note, instead of showing all zeros

Fixed ​

  • Stored-XSS hardening β€” classic (non-builder) post/page content is now sanitised on output (scripts, on* handlers and javascript: URLs are stripped), closing a gap that affected imported HTML content
  • Menu save error β€” saving a menu no longer fails with Unknown column mega_menu_id; the relevant migration now runs, and several migrations were made idempotent (guarded with hasTable/hasColumn) so php artisan migrate runs cleanly on fresh, partially-migrated or already-migrated installs β€” without any data loss
  • Menu selector β€” choosing a menu from the dropdown no longer auto-opens it; the Select button is the trigger
  • Nested-row layout consistency on the builder canvas

v1.7.2 ​

Released: 2026-06-27

A builder polish & tooling release: every Font Awesome free icon in the icon pickers, a media-files backup option, plus several nested-layout and colour-picker fixes that make the builder canvas match the front end.

Added ​

  • Media files backup β€” Tools β†’ Backup now has a Backup Media Files button that zips everything under storage/app/public (uploads, generated images, etc.) into a downloadable archive, and restores media archives back into place. Database snapshots are unchanged
  • Every Font Awesome free icon in the builder β€” the icon pickers (Icon Box, Button icon, Icon List and custom icon fields) now list the full Font Awesome 6 free set β€” 2,060 icons across Solid, Regular and Brands (up from a few hundred). A search box reaches any icon, with the grid capped for snappy scrolling

Changed ​

  • Icon Box font size accepts any CSS unit β€” the Title and Description Font Size fields lost their px/rem dropdown and now take a free-form value (px, rem, em, %, vw, vh, calc()), matching the Title element
  • Nested-column Border & Box-Shadow colour pickers unified β€” they now use the same round-swatch + editable hex design as every other picker, show the opacity-aware #RRGGBBAA code, and the colour renders with its opacity on canvas and front end (responsive per-device)

Fixed ​

  • Nested rows match the front end on the canvas β€” a nested row no longer shows a permanent whitish box; it renders transparent (like a normal element) and reveals its outline + ROW badge only on hover, with no extra padding gap between the row and its parent
  • No more phantom vertical gap inside nested columns β€” columns with default alignment no longer stretch their inner content to a taller sibling's height in the builder, so spacing inside nested columns now looks exactly like the published page

v1.7.1 ​

Released: 2026-06-26

Changed ​

  • Analytics "Page" column shows the site domain for homepage visits β€” homepage hits (including bots that reach the site by raw IP) now display the configured site domain (e.g. demo.example.com) instead of a bare /. Other pages still show their request path

v1.7.0 ​

Released: 2026-06-26

A builder & design-tooling release: one unified colour picker everywhere, responsive background hover colours, full CSS-unit support for font sizes, plus several builder and analytics fixes.

Added ​

  • Background Hover Color for Containers, Columns & Nested Columns β€” a new responsive hover colour (separate desktop / tablet / mobile values). It previews live on hover in the builder canvas and renders as a real :hover rule (with media queries) on the front end
  • Custom Text Color for Buttons β€” when Button Style β†’ Custom is selected, a dedicated text-colour picker sits with the gradient colours; the default style keeps its own text colour

Changed ​

  • One unified colour picker across the whole CMS β€” the main builder, the mega-menu & post-card builders, the Theme Customizer and the Form builder now share a single clean picker: a round swatch, an editable hex field, and a compact popup (saturation square + hue + alpha sliders) with the alpha bar tinted to the current colour. The Form-builder picker also gained an opacity slider
  • Opacity-aware colour fields β€” fields that store opacity separately now show the full 8-digit #RRGGBBAA code, and the alpha slider opens at the correct position
  • CSS units for every font size β€” all typography / font-size inputs across builder elements (and inside header / footer / nested layouts) now accept px, rem, em, %, vw, vh and calc(). Values apply on both the canvas and the front end and survive the shortcode round-trip
  • Title element typography now mirrors the Text Block (font family, weight, size, line-height, letter-spacing, transform) for a consistent editing experience

Fixed ​

  • Column / nested-column background colour ignored responsive values β€” tablet/mobile background colours were rendered with the desktop value on both the canvas and the front end; per-device colours are now honoured
  • A per-device colour was discarded when switching device β€” picking a tablet/mobile colour and then toggling the device preview reverted it; the colour is now committed instead of reverted
  • Analytics "Page" column showed the raw server IP β€” visitors who reached the site directly by IP (bots/scanners) appeared as https://<ip>; the column now shows a clean request path
  • Documentation clarifies that MySQL / MariaDB are the only fully supported databases (SQLite is partial and not recommended; PostgreSQL / SQL Server are unsupported)

v1.6.3 ​

Released: 2026-06-25

Fixed ​

  • Reinstalling over an existing database failed with "table already exists" β€” Running falcon:install (or falcon:update) on top of a database that still had some tables β€” after falcon:uninstall-db, or when installing onto an existing Laravel app whose users / cache / jobs tables remained β€” made migrate try to recreate them and abort. The commands now reconcile first: any migration whose created tables already exist is recorded as run, so migrate skips it and only creates what is genuinely missing. This works for both the app's own and the package's migrations, without editing any migration file

v1.6.2 ​

Released: 2026-06-24

Fixed ​

  • Uninstall could leave a broken User model β€” falcon:uninstall removed the HasCmsPermissions import but only stripped a standalone use HasCmsPermissions; line. When the trait was declared in a combined list (e.g. use HasFactory, Notifiable, HasCmsPermissions;), the reference was left without its import, crashing the app β€” and any later reinstall's migrations β€” with "Trait App\Models\HasCmsPermissions not found". The revert now also removes the trait from a combined use list (verified valid for leading/middle/trailing positions)

v1.6.1 ​

Released: 2026-06-24

Fixed ​

  • Dashboard showed a stale "Installed Version" β€” After updating, the dashboard kept showing an old installed version (e.g. v1.4.2) even though the new code was in place. The version check preferred Composer's reported version, which can be a pinned alias (notably on path-repository installs) and lags behind. It now reads the version from the package's version.json first (bumped on every release), so the dashboard reflects the version actually installed

v1.6.0 ​

Released: 2026-06-24

A consolidation milestone that brings together everything shipped across the 1.5.x line.

Highlights ​

  • Dashboard β€” Redesigned e-commerce KPI cards with month-over-month trend deltas; Top Selling Products, Low Stock and Recent Orders widgets; and an interactive Orders by Country world map (zoom, pan and per-country hover). The whole e-commerce section is now gated behind the access_shop permission
  • Analytics β€” A Visitors by Country world map, a named Traffic Sources breakdown (Google, Facebook, Instagram, YouTube, … Direct, and other sites), and hover tooltips on the real-time active-users sparkline
  • Shop β€” The Conversion Funnel (visitors β†’ product β†’ cart β†’ checkout β†’ orders) now lives on the Shop Overview
  • Security & reliability β€” Internal AJAX fragment endpoints redirect on direct visits instead of leaking raw JSON; reliable geolocation via the shared falcon_geoip() helper; a richer IP blacklist (location, ISP, first/last seen)
  • Lifecycle β€” New falcon:uninstall (full, leaves the app booting cleanly) and falcon:uninstall-db (database-only) commands, plus idempotent core migrations so a reinstall always succeeds

For the granular history of these changes, see the 1.5.x entries below.

v1.5.10 ​

Released: 2026-06-24

Fixed ​

  • App crashed after a database reset β€” The redirect middleware queried cms_redirects on every request and returned a 500 ("Base table or view not found") once the tables were dropped (e.g. after falcon:uninstall-db). It now checks the table exists first and degrades gracefully when it doesn't
  • Reinstall failed with "table already exists" β€” Uninstall keeps the shared Laravel tables (users, sessions, cache, jobs) but clears the migration records, so re-running falcon:install / migrate tried to recreate them and failed with "Table 'users' already exists". The bundled users / cache / jobs migrations are now idempotent (Schema::hasTable guards), so a reinstall succeeds no matter which tables remain

v1.5.9 ​

Released: 2026-06-24

Fixed ​

  • Uninstall left a stale provider cache β€” falcon:uninstall removes the package with composer remove --no-scripts, which doesn't regenerate Laravel's package-discovery cache. bootstrap/cache/packages.php / services.php therefore still referenced FalconCmsServiceProvider, so the app booted with "Class FalconCms\Core\FalconCmsServiceProvider not found". The command now clears those bootstrap caches as its final step. (If you hit this after a manual composer remove, delete bootstrap/cache/packages.php and bootstrap/cache/services.php, then run composer dump-autoload.)

v1.5.8 ​

Released: 2026-06-24

Fixed ​

  • Uninstall left a broken User model β€” The earlier uninstall dropped tables and files but did not remove the HasCmsPermissions trait the installer added to App\Models\User, so after composer remove the app crashed with "Trait FalconCms\Core\Traits\HasCmsPermissions not found". The full uninstall now reverts that automatically

Added ​

  • falcon:uninstall β€” full removal (no leftovers) β€” Reverts the trait/import added to App\Models\User, drops tables + migration records, removes published files, and runs composer remove falconcms/falconcms β€” leaving the app booting cleanly. Options: --all (also drop shared Laravel tables), --force, --keep-files, --no-composer
  • falcon:uninstall-db β€” database-only removal β€” Drops just the FalconCMS tables (and migration records); the package code, files and User model trait stay in place (e.g. to wipe data and re-migrate). Options: --all, --force

v1.5.7 ​

Released: 2026-06-24

Added ​

  • falcon:uninstall command β€” Cleanly removes FalconCMS: drops its database tables, deletes its rows from the migrations table (so a later reinstall re-runs cleanly), and removes published views, themes and assets. Shared Laravel tables (users, sessions, cache, jobs, …) are kept by default to avoid breaking the host app; --all drops them too for a full wipe. Options: --force (skip the confirmation), --all, --keep-files. Finish with composer remove falconcms/falconcms

v1.5.6 ​

Released: 2026-06-24

Fixed ​

  • IP Blacklist β€” country always "Unknown" β€” Blocked IPs were geo-resolved with file_get_contents, which is disabled or blocked on many production hosts, so the country never resolved. A new shared falcon_geoip() helper now uses the Laravel HTTP client (with a timeout, cached 30 days); existing "Unknown" rows are backfilled when the blacklist page is viewed

Added ​

  • IP Blacklist β€” richer detail β€” The blacklist table now shows Location (country + city/region), ISP / network, and both First Blocked and Last Attempt times, with an attempts badge. New blocks capture city, region and ISP

Changed ​

  • Geo lookups unified β€” Visit tracking and the IP blacklist now share the same cached falcon_geoip() helper instead of separate, less reliable lookups

v1.5.5 ​

Released: 2026-06-24

Security ​

  • AJAX fragment endpoints no longer expose raw output on direct visit β€” GET /cart/fragment (mini-cart) and GET /search/live are internal AJAX-only endpoints; opening them directly in a browser previously returned their raw JSON. Non-AJAX (direct navigation) requests are now redirected to the cart and search pages respectively, so the raw payloads are never shown. JS-driven calls (which send X-Requested-With) are unaffected, and only ever returned the visitor's own session data anyway

v1.5.4 ​

Released: 2026-06-24

Added ​

  • Dashboard β€” Orders by Country map β€” An interactive world map highlighting the countries orders came from (shaded by volume), with zoom buttons, mouse-wheel zoom, drag-to-pan and per-country hover (country name + order count), plus a top-countries list. Country values are normalized to ISO-2 from mixed order data
  • Dashboard β€” Top Selling Products, Low Stock & Recent Orders β€” The redundant "Quick Stats" panel is replaced by a best-sellers list (units sold + revenue) and a low-stock alert list; a Recent Orders table now fills the space under the revenue chart
  • Analytics β€” Visitors by Country map β€” The same interactive world map for geo-located visits
  • Analytics β€” Traffic Sources β€” A named-source breakdown (Google, Bing, Facebook, Instagram, YouTube, X, LinkedIn, TikTok, … Direct, and any other site by domain) with visit counts, percentages and favicons
  • Analytics β€” Real-time sparkline tooltip β€” Hovering the real-time active-users bars now shows the visitor count for that minute

Changed ​

  • Dashboard β€” E-commerce KPI cards redesigned β€” Accent strip, soft-tint icon, month-over-month trend delta (↑/↓ %) and a contextual subtext per card
  • Dashboard β€” Shop section permission-gated β€” The whole e-commerce section (revenue, orders, customer names) now requires the access_shop permission (admins bypass), so it is no longer shown to every dashboard-accessing role
  • Shop β†’ Overview β€” Conversion Funnel β€” The conversion funnel (visitors β†’ product β†’ cart β†’ checkout β†’ orders) and conversion rate now live on the Shop Overview, moved from Analytics to keep shop metrics together

v1.5.3 ​

Released: 2026-06-23

Fixed ​

  • Registration β€” default role ignored β€” Self-registration now assigns the role configured in Settings β†’ New User Default Role instead of always using subscriber. Selecting a different role (e.g. Editor, Author) now correctly applies it to newly registered users; if the configured role is missing it safely falls back to subscriber

v1.5.2 ​

Released: 2026-06-23

Changed ​

  • Device limit β€” simpler on/off model β€” The multi-device setting is now a clear cap. Unchecked = unlimited devices; checked = limit concurrent logins to Max devices allowed. The -1 "unlimited" sentinel has been removed β€” the field is a plain positive number again (minimum 1), and the checkbox/help text now reflect the inverted meaning

v1.5.1 ​

Released: 2026-06-23

Fixed ​

  • Multi-device login β€” unlimited (-1) β€” Setting Max devices allowed to -1 now correctly means unlimited concurrent sessions and never blocks sign-in. Previously the limit check (active sessions β‰₯ -1) was always true, so logging in from a second device failed with "Login denied: Only one active session is allowed per account." The -1 sentinel now applies regardless of the multi-device toggle; normal numeric limits and the single-session default are unchanged

Changed ​

  • Settings β€” Max devices allowed β€” The field now accepts -1 (minimum lowered from 1) with a helper note that -1 means unlimited devices

v1.5.0 ​

Released: 2026-06-22

Fixed ​

  • Registration β€” duplicate username β€” Usernames derived from the email local part are now sanitized and made unique (john@a.com and john@b.com no longer collide β†’ john, john1…), fixing the duplicate-username error on sign-up
  • Admin user create/edit β€” Validation errors are now displayed (a top summary plus per-field messages) instead of a database constraint crash; inputs repopulate on failure, and a success message is shown
  • User update redirect β€” Saving a user now returns to the same edit page with the success notice, instead of jumping to the user list

Added ​

  • Password strength & match β€” The admin user create/edit password fields now show a live strength meter and a password-match indicator, matching the registration page

v1.4.9 ​

Released: 2026-06-22

Added ​

  • Analytics β€” major overhaul β€” Bot/crawler filtering, geo location (country/city with flags), real-time active users with a 30-minute sparkline and live tables, sessions, bounce rate, new vs returning visitors, traffic channels, e-commerce conversion KPIs and a visitβ†’cartβ†’checkoutβ†’order funnel, plus donut charts for channels, returning visitors and top countries
  • Analytics β€” data retention β€” New falcon:prune-analytics command with a daily schedule and a cron-independent fallback, with a configurable retention window

Fixed ​

  • Footer logo β€” The default footer logo now uses the white brand logo (the dark logo was invisible on the dark footer) at a larger size, automatically darkened on light footer backgrounds; a custom uploaded logo is always shown as-is

v1.4.8 ​

Released: 2026-06-22

Added ​

  • Registration β€” email verification β€” New sign-ups are no longer logged in immediately; a time-limited (5-minute) signed verification link is emailed instead, and sign-in is blocked until the address is verified. Includes a notice page and a throttled resend flow. A migration marks all existing users as verified so no one is locked out

Fixed ​

  • Order status emails β€” Customers are now emailed on every order status change (pending, on-hold, processing, completed, delivered, cancelled, refunded, partially-refunded, failed), not just on delivery β€” for both single and bulk updates

Changed ​

  • Product Meta element β€” Now available only in post-card mode, like Post Meta and Content

v1.4.7 ​

Released: 2026-06-21

Added ​

  • Builder β€” Product Meta element β€” A new element that displays a product's price (with sale), SKU, availability, stock quantity and type; each field toggleable, with stacked/inline layout, alignment, labels and full design controls
  • Builder β€” Ticker β€” Configurable item spacing, a duplicate-item button, and live scrolling in the builder canvas
  • Dynamic sources β€” Product group β€” Bind any text field to live product data (price, regular/sale price, SKU, stock status, stock quantity); dynamic fields now show a live preview right in the builder using the real value of the post being edited

v1.4.6 ​

Released: 2026-06-21

Fixed ​

  • falcon:update β€” stale published view overrides β€” Update now removes the entire published resources/views/vendor/falcon-cms directory, not just the admin subfolder. A leftover published copy of a namespaced package view (e.g. frontend/builder/column.blade.php) silently shadows the real vendor view, so layout fixes never appear on the site no matter how many caches are cleared. Clearing the whole override namespace guarantees the package's own views are always used

v1.4.5 ​

Released: 2026-06-21

Fixed ​

  • Dashboard Update β€” stale frontend after update β€” The dashboard "Update" now resets the php-fpm OPcache from the web request itself. Previously the falcon:update subprocess ran under CLI php, whose opcache_reset() only clears the CLI OPcache β€” the php-fpm workers that serve frontend pages kept executing the old compiled Blade views, so builder/layout fixes did not appear on the live site until a manual container restart
  • Dashboard footer β€” Default admin footer credit changed to "Theme developed by Falcon CMS"

Changed ​

  • Taxonomy screens β€” Removed the non-functional "Screen Options" and "Help" buttons from the top-right of all taxonomy list pages (Categories, Tags, Product Categories, Product Tags, and custom ACPT taxonomy terms)

v1.4.4 ​

Released: 2026-06-21

Fixed ​

  • Dashboard Update β€” php-fpm binary β€” The dashboard "Update" button ran falcon:update with PHP_BINARY, which in a web (php-fpm) request points at the php-fpm executable and cannot run artisan (it printed FastCGI usage and aborted, so migrations/cache-clear/OPcache reset never ran). The updater now locates a real CLI php binary, checking absolute paths first since the php-fpm worker often runs with a stripped PATH

v1.4.3 ​

Released: 2026-06-21

Fixed ​

  • Page Builder β€” Preview mode blank canvas β€” Toggling the builder's eye-icon Preview no longer blanks the whole canvas. In preview the canvas kept grid-area: auto, which auto-placed it into the now-hidden sidebar's 0-width grid column; it is now pinned to its named canvas area so the design stays visible

v1.4.2 ​

Released: 2026-06-21

Fixed ​

  • Page Builder β€” Row content layout β€” Elements inside a column with Content Layout set to "Row" now stay side-by-side and never wrap to the next line (flex-wrap: nowrap); previously flex-wrap: wrap caused elements to stack when they did not fit
  • falcon:update β€” OPcache β€” OPcache is now reset after cache clearing so freshly compiled Blade views are served immediately without requiring a server restart

v1.4.1 ​

Released: 2026-06-21

Fixed ​

  • Multi-device login β€” -1 value for Max Devices now correctly means unlimited; previously count() >= -1 was always true, blocking all logins even when unlimited was intended
  • Page Builder β€” Nested Column row layout β€” Elements inside a column with Content Layout set to "Row" now render side-by-side on the frontend; previously width: 100% on element wrappers caused items to stack vertically despite flex-direction: row

v1.4.0 ​

Released: 2026-06-20

Added ​

  • Demo mode β€” Login page β€” Demo credentials box displayed above login form when APP_DEMO=true
  • Demo mode β€” User management β€” All fields on user create and user edit pages disabled with warning banner when APP_DEMO=true
  • Demo mode β€” Settings β€” register_url and login_url inputs disabled with warning banner when APP_DEMO=true
  • Docs β€” Demo page β€” Live demo request page with lead capture form; credentials sent to visitor's email via EmailJS after form submission

Fixed ​

  • Footer logo β€” Default FalconCMS logo always shown in footer column 1; embedded as base64 to remove file dependency; theme_footer_logo / theme_site_logo cleared from DB on falcon:update so stale overrides are never applied
  • falcon:update β€” Published admin views deleted on update so vendor views are always served fresh (no stale published copies)

v1.3.18 ​

Released: 2026-06-20

Added ​

  • Customizer β€” Performance β€” "Clear All Cache" button for one-click cache clearing from the admin

Fixed ​

  • Product editor β€” Added x-cloak to product data metabox to prevent Alpine.js FOUC on page load
  • falcon:update β€” Admin views automatically re-published during update to keep published copies in sync
  • Sale end date β€” sale_ends_at datetime input minimum set using client-side local time instead of server UTC
  • Product archive β€” productCategories relation used in archive-product.blade.php; eager loaded on CPT archive queries to prevent N+1
  • Sale end date validation β€” Removed after:now rule causing false rejections in some timezones
  • PHP_BINARY β€” Correctly resolved to CLI php in web (php-fpm) context
  • Product categories β€” Category label display corrected on product cards and single product pages
  • Shop β€” Tab active-state bug fixed; hold_stock order cancellation implemented
  • Page Builder β€” Fixed offset constants in parseColumnsFromContent()
  • Hooks & helpers β€” Remaining lazy_ class and helper references renamed to falcon_

v1.0.0 ​

Released: 2026-06-15

Initial public release of FalconCMS β€” a powerful Laravel CMS package with page builder, e-commerce, and a WordPress-like admin dashboard.

Core ​

  • WordPress-like Admin Dashboard β€” Sidebar navigation, top bar, role-based permissions, activity logs
  • Page Builder (Falcon Builder) β€” Drag-and-drop visual editor with rows, columns, and element blocks
  • Post & Page Management β€” Custom post types, categories, tags, featured images, SEO fields
  • Media Library β€” Upload, manage, and select images/files across the admin
  • User & Role Management β€” Granular permission system with custom roles
  • Multi-language Support β€” Built-in language management
  • Theme System β€” Installable themes with Customizer support (header, footer, colors, typography)
  • Hook Architecture β€” WordPress-style add_lazy_action / add_lazy_filter for extensibility
  • Custom Options Pages β€” Register custom settings pages via config

E-Commerce (Shop) ​

  • Product Management β€” Simple and variable products, SKU, stock, sale price with scheduled expiry (sale_ends_at)
  • Digital / Downloadable Products β€” Attach files from the media library; secure token-based download links with expiry and download count limits
  • Orders β€” Full order lifecycle (pending β†’ processing β†’ shipped β†’ completed), order notes, status history
  • Cart & Checkout β€” AJAX cart, coupon codes, shipping zones, tax rules
  • Payments β€” Cash on Delivery, Stripe, SSLCommerz integrations
  • Customer Account β€” Order history, downloads tab, address management
  • Sales Reports β€” Revenue by period (daily/weekly/monthly), top products, customer LTV, CSV export
  • Shop Settings β€” Currency, inventory, email notifications, shipping, tax, coupon management

Admin UI ​

  • URL-aware Settings Tabs β€” Tab switches update the browser URL via history.replaceState
  • Sidebar Collapse β€” "Collapse Menu" button; icon-only mode persisted in localStorage with no flash on navigation
  • FalconCMS Branding β€” FCM logo in admin top bar

Security ​

  • HTTP Security Headers β€” X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy, CSP, HSTS
  • Rate Limiting β€” Login, forgot-password, comments, cart operations, file downloads
  • CSRF Protection β€” All state-changing routes protected
  • Input Validation β€” Cart quantities, file uploads, comment length, user enumeration prevention
  • Secure Downloads β€” Token-based file delivery; tokens expire and have per-user download limits

Developer Tools ​

  • Artisan Commands β€” lazy:expire-sales (scheduled sale price cleanup)
  • REST API β€” Configurable API key authentication
  • Backup & Snapshots β€” Database and file backup tools
  • WordPress Import β€” Import posts from a WordPress XML export
  • Analytics Dashboard β€” Basic traffic and content stats
  • Maintenance Mode β€” Toggle from Customizer with custom message and countdown timer

Released under the MIT License.