-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Description
History & Purpose
Currently BookStack uses a fixed system for URLs of content within the system which uses "slugs" generated from the name of content. Upon this there's also a fairly hidden id-based system for pages. Examples of existing content urls:
/books/my-awesome-book/pages/my-cool-page
/link/102 (Page permalink)
/books/my-awesome-book/chapter/my-brilliant-chapter
/books/my-awesome-book
/shelves/my-terriffic-shelf
The original idea behind using slugs is provide the user an indication of the likely destination content from the URL alone. A user observing the uri /books/frogs would instantly know the link will likely lead to a book about frogs.
Over the years since building BookStack a number of cases have arisen which has indicated this scheme is not ideal in some scenarios. This proposal/discussion puts forward a new scheme, to address these scenarios, to use as default going forward.
This is an open discussion to gain feedback, details below are not at all final. Comments are very much welcomed. This is not assured to go ahead, especially if the impact looks to be greater than actual long-term benefits.
Targets
Achieve more "Permanent" URLs by default
Right now URLs use slugs which are generated based upon the name of an item.
Changes to name can cause changes to the URL which can break URL references. We do have a system to help handle these scenarios, by referring to the revisions system, but this does not cover every change and revisions may be pruned.
We do have the /link/<page_id> permalinks but these use the database incrementing integers which can leak detail regarding system content (Gap in ids may indicate hidden pages).
There are additional ways we could improve the current URL handling on changes but I think it may be better to use a more reliable base system than apply patches.
Allow flexibility of the content URL
While the existing URLs provide good indication of content, this breaks down when other languages are used. The URL path sections, between slugs, is hard-coded to English which may not be understandable to the reader. In addition, we attempt some conversion to latin for some slugs which can completely remove the original content name for some languages.
We've also seen both requests to have a minimal length URL, and a longer, more descriptive, URL.
Proposed Scheme
The proposed new URL scheme is that shown below. This reflects what would be the new default for a "Page" item URL. The default configuration is intended to closely align with the appearance of the existing default URLs. The components of this scheme are broken down in sections below.
/p-4b72a/:/books/my-awesome-book/pages/my-cool-page
|-------|-|----------------------------------------|
^ ^ ^
UID Separator Configurable Trail
Examples for existing item types
/p-4b72a/:/books/my-awesome-book/pages/my-cool-page
/c-e29bf/:/books/my-awesome-book/chapter/my-brilliant-chapter
/b-7itu3/:/books/my-awesome-book
/s-45da1/:/shelves/my-terriffic-shelf
UID
This acts as a unique identifier for an item within BookStack. It will be a flexible-length case-insensitive (defaulting to lower case) alpha-numeric string defaulting to minimum 5 characters. This is used instead of a UUID-like ID to keep this short and usable in URLs with little impact. It's case-insensitive for compatibility with case-insensitive systems.
The UID is prefixed with an type letter followed by a hyphen. The type letter represents the content type (p = page) which allows type identification from the UID alone while ensuring UIDs are unique across content types. The hyphen separates the type indicator while allowing a pattern to match upon to prevent confusion with other systems URL at the same path prefix.
Separator
The separator simply exists to separate the UID from the configurable trail portion of the URL.
This allows us to still use the core ID-based URL for system endpoints (For example /b-7itu3/create-page) while having clear separation to the configurable trail to prevent conflicts.
Configurable Trail
This portion of the URL would be system-admin configurable as required. It would default to match the current BookStack slug scheme, but we would provide an interface to allow per-content-type (book/page/chapter/shelf) configuration of this trail using static and dynamic-placeholder elements.
The available dynamic-placeholder elements would initially be as follows:
{{name}}- URL encoded version of the item name.{{slug}}- Name-generated slug, as we provide now.{{book_slug}}- - Name-generated slug, as we provide now. Chapters and pages only.
This could be expanded on in the future, but the initial implementation goal would be to match existing options.
The trail could be made empty if desired, which would cleanly generate item URLs with no trail and no separator components.
Considerations
- Some of these changes are based upon the feedback received via community channels, but the actual overall desire for such changes, across the whole existing BookStack user-base, is tremendously hard to judge.
- Non-content URLs will remain the same. For example the
/booksendpoint would remain as-is, which may limit the flexibility benefits in scenarios where users want to get away from the default BookStack terms, although this isn't a core goal here. - This won't be an instant switch-over to new URLs. It's important we make any changes in a stable manner. We'd look to support existing URL schemes in parallel for a significant time afterwards.
- The UIDs would effectively be replacing current integer-based IDs in purpose. We'll need to think how we roll these out for the API, where ID's are used heavily. We could use both in parallel for some time but there are complications in regards to how relations are shown.
Personal Thoughts
I'm not fully sure on the propose scheme. The separator especially makes it look a little ugly, but it's the closest I could think when thinking about the technical handling and attempting to have a default aligning with the current URL scheme.
After writing this out, It's very hard to assess if such a change would be worth it. The benefits right now are very edge-case based but these may amplify long-term.