BookStack Release v25.11

Today arrives BookStack v25.11 which makes some significant changes to the database structure, while expanding on API capabilities along with other various improvements.

Upgrade Notices

  • Large Database Changes - Significant changes have been made to the database structure. It’s essential you have good backups for your instance before updating, and that you allow extra time for the database to migrate during the update process. On large instances this could be in the range of minutes rather than seconds.
  • Caching - The APP_NAME env option is no longer used for the cache key. This option was never documented at all, but if you used this to prevent cache collisions please instead use the CACHE_PREFIX option.

Database Changes

For every version of BookStack before today, each element of the content hierarchy (Shelves, Books, Chapters and Pages) had their own database table which affords simplicity and ease-of-use for most developer scenarios. This separate table format is not so great when we need to query across different types of items which is very common in BookStack, in areas such as activity lists, book contents, search results, and many other areas. This would result in making extra queries per item type or performing inefficient unions across tables. In some cases, this would present as quirks to the end-user. An example of this is the BookStack search results, which do not have a stable page-count (including via the API) while not being able to sort relevancy across item types and result pages as we’d really like.

In this release the structure has changed significantly, merging the core information of all hierarchy elements into a single table, where they can be indexed & queried as one set of data, while more unique item-specific data is placed into one of two secondary tables.

The results of this are fewer database queries in many areas, leading to a faster and more responsive system. This also allows us to have better search result quality, stability, and paging of search results:

View of the bottom of the search results page in BookStack, showing a page select navigation element with 5 pages, currently on page 1

As development goes on we’ll update further areas of the application to make use of this more efficient structure. This approach also has the benefit of fewer database changes and performance implications in the event we add a new hierarchy item in the future.

Ultimately though, apart from proper search paging, this should present no functional difference to end-users or applications/developers using our stable API interfaces, since attention has been paid to ensure those remain stable across this restructuring.

App Time-zones

This release adds a new APP_DISPLAY_TIMEZONE option, which allows you to define a separate time-zone which will be used for absolute dates shown within the user interface. This will default to the existing APP_TIMEZONE, but that can now be instead used to define just the storage time-zone format for date-times in the database. Generally it’s a good idea to set APP_TIMEZONE to UTC, so it’s stable & standard, then use APP_DISPLAY_TIMEZONE to configure the time-zone for which most users would be considered within.

As part of these changes, we’ve also gone through all the locations where absolute times are shown in-app, and made their format consistent:

View of a page revision list in BookStack, focused on the revision date for an entry, showing “2025-07-28 13:26:42 UTC (3 months ago)”

As seen above, display of absolute times will now include a short-hand time-zone indicator so the reader can be sure to understand exactly what time it represents, regardless of if they’re in the same time-zone or not. Further details about these options can be found in our documentation here.

Groovy Code Language Highlighting

This release adds code syntax highlighting support for Groovy, a Java-syntax-compatible object-oriented programming language for the Java platform:

View of the code editor in the BookStack page editor, with the “Groovy” language selected, and with an example set of Groovy code with various highlighting colours

This will show as an option in the WYSIWYG code editor, or can be utilised in the markdown editor by using groovy in the opening code block tag.

New Flags for the “Create Admin” Command

The create admin command has received a couple of new options in this release:

  • --generate-password: Generate a random password, and echo it back out as the only output on success.
  • --initial: Update the default admin@admin.com user if it exists, otherwise create a new admin user if there’s no existing admin accounts, otherwise do nothing.

These new options provide the components needed to allow automation & scripts to have some control over the initial admin user account in BookStack. This should allow our installation scripts, and any other third-party use/install method, to safely migrate over to having more secure initial accounts rather than globally known default admin credentials. This will be an ongoing change, as I reach-out to other projects to assist in using these more secure approaches, before eventually removing the default user account creation entirely.

API: Docs Navigation Improvements

The API documentation, found at /api/docs within a BookStack instance, has a sidebar which was becoming quite long with all the endpoints & models being supported over time, making it more difficult to find what’s needed.

In this release, the sidebar has now been organised with the main hierarchy elements (pages, chapters, books and bookshelves) at the start, and everything below that in alphabetical order by model name.

The sidebar also gains a jump-menu, allowing you to quickly find the endpoints for the data model you need.

View of the BookStack API docs page, focused on the sidebar where there’s a “Jump to Section” drop-down listing various sections of the page

API: Comments

Comments are now available as part of the BookStack REST API. There’s full create, read, update and delete actions available:

Cropped view of the BookStack API docs page sidebar, showing the heading “Comments” with GET - list, POST - create, GET - read, PUT - update and DELETE - delete listed under it, reflecting the available API endpoints for comments

In addition to the comment-specific endpoints, the page-read endpoint will now include all comments for that page, formatted in the same thread-tree style as seen in the UI to prevent extra client-side handling needed to replicate this format.

API: Image Data

We’ve had image API endpoints for a while, but there was a limitation that the actual data could not be read via the API, outside of exports, leaving images inaccessible in environments such as those using local_secure_restricted image storage.

To address this, we have a couple of new endpoints:

Cropped view of the API docs page in BookStack, showing the details for two image-gallery endpoints

Both of these endpoints will simply return the image data for the requested image, with one allowing you to look-up image by ID, and the other by URL; the latter added as a convenience helper for direct data fetching based on image links within content.

Translations

It wouldn’t be a feature release without a load of translation updates! A big thanks again to all the meticulous multilingual marvels of language below who have helped translate BookStack since our last feature release:

  • Silvia Isern (eiendragon) - Catalan - 996 words
  • Tim (thegatesdev) - Dutch - 172 words
  • ahmad abbaspour (deshneh.dar.diss) - Persian - 148 words
  • Dennis Kron Pedersen (ahjdp) - Danish - 145 words
  • João Faro (FaroJoaoFaro) - Portuguese - 114 words
  • Jeff Huang (s8321414) - Chinese Traditional - 107 words
  • CellCat - Chinese Simplified - 77 words
  • iamwhoiamwhoami - Swedish - 70 words
  • toras9000 - Japanese - 55 words
  • Vitaliy (gviabcua) - Ukrainian - 46 words
  • Grogui - French - 32 words
  • Ngoc Lan Phung (lanpncz) - Vietnamese - 32 words
  • m0uch0 - Spanish - 31 words
  • scureza - Italian - 22 words
  • ltnzr - French - 17 words
  • cbridi - Portuguese, Brazilian - 16 words
  • MrCharlesIII - Arabic - 16 words
  • Indrek Haav (IndrekHaav) - Estonian - 14 words
  • David Olsen (dawin) - Danish - 13 words
  • HrCalmar - Danish - 11 words
  • Honza Nagy (honza.nagy) - Czech - 11 words
  • M Nafis Al Mukhdi (mnafisalmukhdi1) - Indonesian - 9 words
  • Danilo dos Santos Barbosa (bozochegou) - Portuguese, Brazilian - 7 words
  • Frank Holler (holler.frank) - German; German Informal - 6 words
  • mabdullah - Arabic - 5 words
  • Worive - French; Catalan - 4 words
  • Chris (furesoft) - German - 3 words

Word counts are those tracked by Crowdin, indicating original EN words translated.

Codebase Updates

In this release we upgraded the core framework used from Laravel 11 to Laravel 12. This was done much earlier than usual, mostly thanks to being a minor upgrade which does not impose PHP minimum version changes and therefore doesn’t impact BookStack’s requirements.

Along with this, other codebase changes have been made such as:

  • Upgrading our static code analysis to be more strict, and address a range of existing lack of typing.
  • Upgraded BookStack’s PHP dependencies across major versions where needed.
  • Updated permission checks to use enums instead of strings to avoid string-based-errors.
  • Removed some redundant columns from the database, and added better clean-up & nullification of old IDs.

Next Steps

Since this release was so heavy on large back-end changes, I’d like the next one to be a lighter release of little improvements which hopefully I can provide as a bit of a Christmas present for the end of December. One of these improvements will be focused on building a more robust and focused slug/URL tracking solution to further assist URL change resolution.

Since it was skipped for this release cycle due to time, I’ll also look to include an initial developer API implementation for our new WYSIWYG editor.

Full List of Changes

Released in v25.11

  • Added API endpoints for comments. (#5850, #4194))
  • Added API endpoints for reading image data. (#5860, #5519)
  • Added Groovy code syntax highlighting support. (#5822)
  • Added new flags to the create admin command. (#5749)
  • Added option for display timezone, and improved UI use consistency. (#5790, #4786)
  • Added proper pagination to search. (#5854)
  • Updated API docs with better model ordering, and quick navigation select. (#5865)
  • Updated codebase to meet PHPstan level 3. (#5785)
  • Updated database comments table to remove redundant text column. (#4821)
  • Updated database format for core item types. (#5800)
  • Updated framework to Laravel 12, and perform some major dependency upgrades. (#5782)
  • Updated page delete handling to nullify related images instead of leaving old IDs. (#5846)
  • Updated permission handling in code to use enums instead of strings. (#5793)
  • Updated translations with latest Crowdin changes. (#5843)
  • Updated user delete handling to nullify, or better handle, ID references on delete. (#5844)
  • Fixed old API-scripts link leading to archived repo. (#5813)
  • Fixed search timeout when a high per-page frequency match was encountered. (#5863)

Released in v25.07.3

  • Updated translations with latest Crowdin changes. (#5786)
  • Updated PHP package versions.
  • Fixed PWA manifest access when behind authenticated proxies. Thanks to @tfnh621. (#5820)

Released in v25.07.2

  • Updated new WYSIWYG editor with various fixes focused on collapsible block behaviour & interaction. (#5775)
  • Updated translations with latest Crowdin changes. (#5759)
  • Updated versions of PHP dependencies.
  • Updated code to address some remaining PHP 8.4 deprecations.
  • Fixed diagrams in ZIP imports not being editable post-import. (#5761)
  • Fixed books detaching from shelves on shelf update where users don’t have permission to view child books. (#5728)

Released in v25.07.1

  • Updated translations with latest Crowdin changes. (#5740)
  • Updated PHP package versions.
  • Fixed open redirect with stricter location checking.
  • Fixed users being logged out on ZIP import errors. (#5754)
  • Fixed menu accessibility tagging. (#5753, #5752)
  • Fixed scenarios where MAIL_PORT could interfere with tests. (#5755)

Header Image Credits: Photo by David Gubler (CC-BY-SA-4) - Image Modified