From 715921e036e63f4cc2e7821999255ad70cfa78a9 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 31 Jan 2026 22:43:21 +0000
Subject: [PATCH 01/13] Initial plan
From 89c89c9f9fa9fd466cef7423eb9964c5cd14b1da Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 31 Jan 2026 22:49:25 +0000
Subject: [PATCH 02/13] =?UTF-8?q?Add=20complete=205.1=E2=86=926.0=20upgrad?=
=?UTF-8?q?e=20guide=20and=20remove=20old=20upgrade=20guides?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: lcharette <2566513+lcharette@users.noreply.github.com>
---
.../01.46-to-50/01.changelog/docs.md | 139 ----
.../22.upgrading/01.46-to-50/02.guide/docs.md | 347 ---------
.../01.46-to-50/03.roadmap/docs.md | 54 --
.../6.0/22.upgrading/01.46-to-50/chapter.md | 12 -
.../01.51-to-60/01.changelog/docs.md | 334 +++++++++
.../22.upgrading/01.51-to-60/02.guide/docs.md | 672 ++++++++++++++++++
.../01.51-to-60/03.what-to-expect/docs.md | 376 ++++++++++
.../6.0/22.upgrading/01.51-to-60/chapter.md | 86 +++
.../02.50-to-51/01.changelog/docs.md | 107 ---
.../22.upgrading/02.50-to-51/02.guide/docs.md | 291 --------
.../02.50-to-51/03.roadmap/docs.md | 27 -
.../6.0/22.upgrading/02.50-to-51/chapter.md | 14 -
app/pages/6.0/22.upgrading/chapter.md | 54 +-
13 files changed, 1518 insertions(+), 995 deletions(-)
delete mode 100644 app/pages/6.0/22.upgrading/01.46-to-50/01.changelog/docs.md
delete mode 100644 app/pages/6.0/22.upgrading/01.46-to-50/02.guide/docs.md
delete mode 100644 app/pages/6.0/22.upgrading/01.46-to-50/03.roadmap/docs.md
delete mode 100644 app/pages/6.0/22.upgrading/01.46-to-50/chapter.md
create mode 100644 app/pages/6.0/22.upgrading/01.51-to-60/01.changelog/docs.md
create mode 100644 app/pages/6.0/22.upgrading/01.51-to-60/02.guide/docs.md
create mode 100644 app/pages/6.0/22.upgrading/01.51-to-60/03.what-to-expect/docs.md
create mode 100644 app/pages/6.0/22.upgrading/01.51-to-60/chapter.md
delete mode 100644 app/pages/6.0/22.upgrading/02.50-to-51/01.changelog/docs.md
delete mode 100644 app/pages/6.0/22.upgrading/02.50-to-51/02.guide/docs.md
delete mode 100644 app/pages/6.0/22.upgrading/02.50-to-51/03.roadmap/docs.md
delete mode 100644 app/pages/6.0/22.upgrading/02.50-to-51/chapter.md
diff --git a/app/pages/6.0/22.upgrading/01.46-to-50/01.changelog/docs.md b/app/pages/6.0/22.upgrading/01.46-to-50/01.changelog/docs.md
deleted file mode 100644
index 754262e3..00000000
--- a/app/pages/6.0/22.upgrading/01.46-to-50/01.changelog/docs.md
+++ /dev/null
@@ -1,139 +0,0 @@
----
-title: What's new ?
-description: A detailed look at what's new in UserFrosting 5.
-obsolete: true
----
-
-UserFrosting 5 is the culmination of two years of work. It is a complete rewrite of the backend PHP code. And by complete, we _really_ mean **complete**. No class was left untouched! The key points are :
-- Slim 3 upgraded to Slim 4
-- Pimple Dependency Injection Container replaced with [PHP-DI](https://php-di.org)
-- Frontend assets management replaced with [Webpack Encore](https://symfony.com/doc/current/frontend.html)
-- New Sprinkle system, now with extra modularity
-- Skeleton type main repo for easier initial development
-- Built-in sprinkle are now loaded by Composer
-- New Event dispatcher and listener services
-- New Bakery command available for easier debugging
-- Added return type, type-hint and other quality improvement across all code
-- (Almost) 100% test coverage and quality check through PHPStan
-- ***And so much more***
-
-The Slim migration itself is a big deal. While brining UF to a more modern era, it had the most impact on the core changes applied to the UserFrosting framework. Most changes were made in response to the new Slim 4 requirements and changes. It also required the use of a new Dependency Injector, which itself _really_ brought UserFrosting 5 to a whole new level. You should really check out [PHP-DI](https://php-di.org), it's awesome!
-
-Basically, UserFrosting 5 uses updated dependencies, all of existing code have been updated to new standard and new test coverage should provide better long term stability.
-
-## What UserFrosting 5 isn't ?
-
-UserFrosting 5 is not a drop-in replacement for UserFrosting 4. The whole backend has been rewritten, with a new container, new sprinkle system, etc. which will require most sprinkle and app to be updated manually.
-
-## What's the same ?
-
-UserFrosting 5 keeps the same frontend as UserFrosting 4. But the bases have been set for the future, with Webpack Encore and the current AdminLTE theme have been separated in it's own Sprinkle, all of which provides the necessary tools for [Vue.js](https://vuejs.org) or other similar frontend in the future.
-
-The database structure is 99% identical to UserFrosting 4. One migration have been added, but it's a simple, optional even, modification. This means your data shouldn't be impacted by the upgrade.
-
-## New requirements
-
-With the release of PHP 8 in november 2020 some major updates where made to the system requirements. UserFrosting 5 now requires :
-- PHP 8.0 or higher
-- [Node.js](https://nodejs.org/en/) 18 or higher
-- [Composer 2](https://getcomposer.org/)
-
-While any version of PHP 8 is supported, we recommend you use the latest version.
-
-## New Structure
-
-This is where all the magic happened. The [new structure](structure) introduced in UserFrosting 5 makes it even more easier to separate your code from UserFrosting's code. This also makes it easier for new developer to get started with UserFrosting. Upgrading will also be easier, as everything is now managed by Composer. Requesting a new major version will required to edit your `composer.json` file. Finally, default pages and content are not part of the Core Sprinkle anymore. This makes easier to overwrite default pages.
-
-The old directory structure looked like this:
-
-```txt
-├── app/
- ├── cache/
- ├── database/
- ├── logs/
- ├── sessions/
- ├── sprinkles/
- ├── account/
- ├── admin/
- ├── core/
- └── yourSprinkle/
- ├── assets/
- ├── config/
- ├── locale/
- ├── routes/
- ├── schema/
- ├── src/
- ├── Bakery/
- ├── Controllers/
- ├── Database/
- ├── [...]
- └── Sprunje/
- ├── templates/
- ├── tests/
- ├── composer.json
- └── asset-bundles.json
- ├── storage/
- ├── system/
- ├── tests/
- ├── .env
- ├── defines.php
- └── sprinkles.json
-├── public/
-├── vendor/
-└── composer.json
-```
-
-The new structure looks like this:
-```txt
-├── app/
- ├── assets/
- ├── cache/
- ├── config/
- ├── database/
- ├── locale/
- ├── logs/
- ├── schema/
- ├── src/
- ├── Bakery/
- ├── Controllers/
- ├── Database/
- ├── [...]
- ├── Routes/
- ├── Sprunje/
- └── yourSprinkle.php
- ├── storage/
- ├── templates/
- ├── tests/
- └── .env
-├── public/
-├── vendor/
- ├── account/
- ├── admin/
- └── core/
-├── composer.json
-├── package.json
-└── webpack.config.js
-```
-
-As you see, since `/vendor` should be omitted from version control (your Github Repository), the new structure is much more cleaner! This doesn't means your code can't be distributed and added as a sprinkle in another UserFrosting powered app. [Community Sprinkle](sprinkles/community) are still a thing! This new structure even makes it easier to develop them!
-
-### Sprinkles
-All [bundled Sprinkles](structure/sprinkles#bundled-sprinkles) are now managed by Composer, and directly required in your project's `composer.json`. Gone is the `app/sprinkles` directory. Your app now sits in `/app` directly and other Sprinkles will now be loaded into the `vendor/` directory, like any other dependencies.
-
-Gone is also `app/sprinkles.json`. To register sprinkles, we now use **[Sprinkle Recipe](sprinkles/recipe)**. Recipes makes it easier for sprinkle to define other sprinkle as dependencies. In fact, recipe also makes it easier for Sprinkles to _register_ any class and resources they need. UserFrosting 4 used to rely on naming convention and auto-discovery, which was prone to errors. Registering resources also makes the structure more adaptable, as there's **no** naming convention anymore for classes : The structure of `/src` can be whatever you want! You can read more about [Sprinkle Recipe here](sprinkles/recipe).
-
-Finally, as mentioned before, the AdminLTE Theme has been moved to it's own Sprinkle. This will make it easier to switch theme in the future, but also means some reference will need to be updated.
-
-### Routes
-
-Routes used to be in `sprinkles/routes`. While still technically PHP files, they were not part of any namespace, and were included using the [`require()`](https://www.php.net/manual/fr/function.require.php) method. Routes are now namespaced, same as any other class in `src/`.
-
-It also means routes file are not directly overwritten anymore, similar to template files. They're not real classes, and must be mapped, or in case of UserFrosting 5, injected properly.
-
-### Dependency injection
-
-As mentioned in previous paragraphs, UserFrosting 5 now uses [PHP-DI](https://php-di.org) a. This brings a **ton** of new features and capability. The best way to understand how it affect your code in UserFrosting 5, head over to the [Dependency Injection Chapter](dependency-injection).
-
-## Migrating
-
-Now that we've cover the basics changes, follow on to the next pages to the steps required to bring your app up to date with UserFrosting 5.
diff --git a/app/pages/6.0/22.upgrading/01.46-to-50/02.guide/docs.md b/app/pages/6.0/22.upgrading/01.46-to-50/02.guide/docs.md
deleted file mode 100644
index 882800eb..00000000
--- a/app/pages/6.0/22.upgrading/01.46-to-50/02.guide/docs.md
+++ /dev/null
@@ -1,347 +0,0 @@
----
-title: Upgrade Guide
-description: Upgrade guide from version 4.6.x to 5.0.x
-obsolete: true
----
-
-Upgrading an existing sprinkle from UserFrosting 4 to UserFrosting 5 can unfortunately be a difficult task. It all depends on how much customization of the core code you have done. Very basic sites will be easy to upgrade, very complex ones could be a nightmare. However, it's for the greater good; UserFrosting 5 is more modern and uses new techniques.
-
-> [!WARNING]
-> This guide contains the most important changes and the actions you need to take to upgrade your UserFrosting 4 Sprinkle. However, **it's far from complete**, as there are too many changes to document. Make sure you have a backup of your existing application and your **development database** before starting.
-> If you spot anything missing, don't hesitate to contribute to this page via the [*edit this page*](https://github.com/userfrosting/learn/blob/5.1/pages/22.upgrading/01.46-to-50/02.guide/docs.md) button at the top.
-
-## Before you start
-
-The upgrade path for your UserFrosting 4 sprinkle will depend on how many features you're using. The good news is, the database structure is the same, and the frontend is 90% the same.
-
-To begin the upgrade journey, **the first thing you should do is a [fresh install](installation) of UserFrosting 5**. This is important, as it will allow you to familiarize yourself with the new structure, as well as validate that your [local development environment](background/develop-locally-serve-globally) is up to date and meets the [minimum requirements](installation/requirements).
-
-Once you have a functioning vanilla version of UserFrosting 5, you can begin to upgrade your sprinkle.
-
-> [!NOTE]
-> While the database structure is mostly the same between V4 and V5, it is highly recommended you keep a backup of your existing application and your **development database**.
-
-## Upgrading your sprinkle structure
-
-As seen on the [previous page](upgrading/46-to-50/changelog), one of the biggest changes is the app structure. It's recommended before you start to head over to [Chapter 3 - App Structure](structure), to learn more about this new structure.
-
-Once you're familiar with the new structure, it's time to move things around so your sprinkle meets the new structure. There are two options here: You can either start from scratch from the [Skeleton repo](structure/introduction#the-app-skeleton-your-project-s-template), *or* you can manually upgrade in place.
-
-The first option is easier as the base has been set up for you, and you can start right away moving your code into the skeleton created from the sprinkle template, in a new git repository. However, its drawback is you'll probably lose your Git History. The second option is harder, but since you're starting from your existing code, you'll keep your git history if your code is saved on GitHub for example.
-
-### Option 1 - Start over from the Skeleton
-
-To start with this option, the first step is to create a [fresh install](installation) from the app skeleton. You'll then have an empty sprinkle with the new structure, ready to copy your code into it. However, there are some steps you need to follow before going further.
-
-#### Update `composer.json`
-
-The Skeleton comes with a basic `composer.json`. This defines the PSR-4 autoload namespace to `UserFrosting\App\`. You should edit this file to fit your sprinkle, as well as use the **same namespace as your old sprinkle**.
-
-> [!NOTE]
-> **Important:** To make sure your migrations and database data are preserved, the app namespace must be the same
-
-You'll also need to update the namespace in every existing class, `index.php`, and `bakery`. See [Customizing Your Sprinkle](sprinkles/customize#custom-namespace-and-name) for more information.
-
-Once this is done, you can run `composer update` to fetch dependencies.
-
-#### Edit the Recipe
-
-Next up, you should familiarize yourself with the [Sprinkle Recipe](sprinkles/recipe#name). Right now, the only thing you must update is the sprinkle name, but we'll come back later to the recipe.
-
-#### Moving your code
-
-The last part is to move your code from `app/sprinkles/{YourSprinkle}/` from your old install (usually from `app/sprinkles/{YourSprinkle}/`) to `app/` in the new directory.
-
-At this point, you can skip to [Upgrading components](upgrading/46-to-50/guide#upgrading-components).
-
-### Option 2 - Upgrade in place
-
-To start with this option, you should already be familiar with UserFrosting 5 directory structure, as it involves moving some directories around and editing some files. It also assumes your code (your sprinkle) was located (and not as a community sprinkle for example). You should have a UserFrosting 5 skeleton repo on hand to copy some files.
-
-#### Moving files and directories
-
-- Delete:
- - `composer.json`
- - `bakery`
- - `build/`
- - `vagrant/`
- - `public/index.php`
- - `app/system/`
- - `app/tests/`
- - `app/defines.php`
- - `app/.htaccess`
- - `app/sprinkles/account/`
- - `app/sprinkles/admin/`
- - `app/sprinkles/core/`
- - `app/sprinkles.example.json`
- - `app/sprinkles.json`
-- Move everything inside `app/sprinkles/{YourSprinkle}/` to `app/`, and delete the empty `app/sprinkles/` directory.
-- Copy from the skeleton, replacing existing files:
- - `/public/index.php`
- - `/bakery`
- - `/package.json`
- - `/webpack.config.js`
- - `/webpack.entries.js`
- - `docker-compose.yml`
- - `docker/`
- - `.gitignore`
-
-#### Updating `composer.json`
-
-In UserFrosting 4, your `composer.json` was located in `app/sprinkles/{YourSprinkle}/composer.json`. It was merged with the main composer file and the dependent sprinkles on build. With UserFrosting 5, there's only one `composer.json`: Yours. And it lives in `/composer.json`.
-
-This step requires you to merge your `composer.json` with UF5's. Start by moving your file, which should now be located at `/app/sprinkles.json` to `/composer.json`.
-
-Next, you'll need to update some dependencies. Open `composer.json` **from the skeleton**, and copy every dependency from `required` and `require-dev` from it to your `composer.json`.
-
-You should also update the path for the `autoload` and `autoload-dev` sections to point to `app/src/` and `app/tests/` respectively.
-
-> [!NOTE]
-> **Important:** Don't change the namespace if you want to keep the existing migration
-
-Once this is done, you can run `composer update` to fetch dependencies.
-
-#### The Recipe
-
-The next step is to create your [sprinkle recipe](sprinkles/recipe#name).
-
-Start by:
-- Copy `app/src/MyApp.php` from the skeleton into your app, inside `app/src/`
-- You can rename `MyApp` to whatever you want. Simply don't forget to adapt the next steps with the name you chose.
-- Change the namespace inside your `app/src/MyApp.php` to the namespace you use in your `composer.json`.
-
-We'll update the rest of your recipe later.
-
-#### The entry files
-
-Finally, you'll need to update both *entry files*, aka `/bakery` and `/public/index.php`, with the correct reference to your recipe. Open both files, and replace `UserFrosting\App\MyApp` and `MyApp` with the correct reference to your recipe. See [this page](sprinkles/customize#the-entry-files) for more information and examples.
-
-## Upgrading components
-
-At this point, your UserFrosting 5 app is _kind of ready_ to work. You simply need to upgrade every component you use. The following list might contain stuff you're not using, but you should still go through them as they contain links and tips you may need later.
-
-Remember, this guide will give you only the big picture of what changed, but it will point you to the relevant parts of the documentation where more detail can be found.
-
-### Global changes
-
-It's important to note some changes have been applied at large and affect pretty much every PHP class, based on PHP 8 new features. These changes include:
-
-- Extensive use of type declaration and [return types](https://dev.to/karleb/return-types-in-php-3fip)
-- [Named Arguments](https://www.php.net/releases/8.0/en.php#named-arguments)
-- [Constructor property promotion](https://www.php.net/releases/8.0/en.php#constructor-property-promotion)
-- [Union type](https://www.php.net/releases/8.0/en.php#union-types)
-- [Etc.](https://www.php.net/releases/8.0/en.php)
-
-Keep this in mind, especially if you've extended built-in classes. Not only may these classes have been renamed or moved, but the method declaration might have changed even if the code of these methods hasn't.
-
-### Services -> Dependency Injection
-
-Services have been updated for UserFrosting 5. While the principle is the same, the way to register a service is different. Services are now served by the new dependency injection container, PHP-DI. You should head over to the [Dependency Injection Chapter](dependency-injection) to learn more about PHP-DI integration in UserFrosting 5 before going further.
-
-Your services definition must first be updated to implement `UserFrosting\ServicesProvider\ServicesProviderInterface`. For example:
-
-**OLD:**
-```php
-class ServicesProvider
-{
- public function register(ContainerInterface $container)
- {
- // ...
- }
-}
-```
-
-**NEW:**
-```php
-use UserFrosting\ServicesProvider\ServicesProviderInterface;
-
-class ServicesProvider implements ServicesProviderInterface
-{
- public function register(): array
- {
- return [
- // ...
- ];
- }
-}
-```
-
-You'll also need to **register your service** in your recipe. Check out [Adding Services](dependency-injection/adding-services) for more information.
-
-Finally, instead of injecting the whole container and retrieving your service from it, you should inject the service directly into the class using [autowiring](dependency-injection/the-di-container#autowiring) in the class constructor or through [route service injection](routes-and-controllers/controller-classes#service-injection) for example.
-
-For example:
-
-**OLD:**
-```php
-public function __construct($ci)
-{
- $this->camHelper = $ci->camHelper;
-}
-```
-
-**NEW:**
-```php
-public function __construct(protected CamHelper $camHelper): void
-{
-
-}
-```
-
-### Classmapper
-
-The classmapper has been removed in UF5. PHP-DI should be used instead, via the "autowire" and [interface binding](dependency-injection/the-di-container#binding-interfaces). Existing classmapper definitions should be moved inside a service, and calls to the classmapper should be updated to use dependency injection via the controller or other methods.
-
-### Migrations
-
-Migrations are mostly the same, only the class structure has changed, as well as the need to register migrations in your Sprinkle Recipe. The key points regarding migration are as follows:
-
-1. Up/Down return type: The `up()` and `down()` methods [must now have a return type of `void`](database/migrations#base-class).
-
-2. Migrations must [now extend](database/migrations#base-class) `UserFrosting\Sprinkle\Core\Database\Migration`. Change `use UserFrosting\System\Bakery\Migration;` to `use UserFrosting\Sprinkle\Core\Database\Migration;` in every one of your migrations.
-
-3. [Dependencies](database/migrations#dependencies) must now be declared in a static property. Change `public $dependencies = [];` to `public static $dependencies = [];` in every one of your migrations.
-
-4. Migrations are not auto-discovered anymore. You need to add them to your sprinkle recipe, using `MigrationRecipe`. See [the migration chapter](database/migrations#sprinkle-recipe) for more information and a detailed guide.
-
-### Seeds
-
-Seeds are also mostly the same; they just need to implement `\UserFrosting\Sprinkle\Core\Seeder\SeedInterface` and have a `run()` function with a return type of `void`. They are also not auto-discovered, so need to be added to your sprinkle recipe using `SeedRecipe`.
-
-See [the seeding chapter](database/seeding) for more details.
-
-### Models
-
-The only change in the database model is the `$timestamps` property is now `true` by default. It used to be `false`. `public $timestamps = true;` can be removed from your models unless you're **not** using timestamps, in which case you should add `public $timestamps = false;`.
-
-### Routes
-
-The way to register routes has changed. The definition is mostly the same; however, the routes are now real PHP classes instead of static PHP resources. Check out the [Registering routes](routes-and-controllers/registering-routes) guide for more information.
-
-To update your routes, you should start by:
-
-1. Moving your routes from `app/routes/*` to `app/src/Routes/*`.
-2. Updating your route definitions so they are classes [implementing RouteDefinitionInterface](routes-and-controllers/registering-routes).
-3. Registering your routes in your Sprinkle Recipe.
-
-A few other key points to know:
-1. Definitions for route groups have changed. See [Slim Documentation](https://www.slimframework.com/docs/v4/objects/routing.html#route-groups) for more information.
-2. Controller resolution should be updated to make use of [PHP’s `::class` operator](https://www.slimframework.com/docs/v4/objects/routing.html#container-resolution).
-3. Middleware must now be called by their class name. For example, `authGuard` must be updated to `UserFrosting\Sprinkle\Account\Authenticate\AuthGuard::class`.
-
-### Sprunje
-The Sprunje class used to accept options in the constructor. To make it easier to [inject dependencies](dependency-injection/the-di-container), options should now be defined using the `setOptions` method. Sprunje should now be injected into controllers.
-
-**OLD:**
-```php
-public function camsList(Request $request, Response $response, array $args)
-{
- // GET parameters
- $params = $request->getQueryParams();
-
- /** @var /UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- /** @var \UserFrosting\Sprinkle\Core\Router $router */
- $router = $this->ci->router;
-
- $sprunje = new CamsSprunje($classMapper, $params, $router);
-
- return $sprunje->toResponse($response);
-}
-```
-
-**NEW:**
-```php
-public function camsList(Request $request, Response $response, CamsSprunje $sprunje): Response
-{
- // GET parameters
- $params = $request->getQueryParams();
-
- return $sprunje->setOptions($params)->toResponse($response);
-}
-```
-
-This also means the **Classmapper** is no longer available in Sprunjes. You should inject the necessary classes and services into your Sprunjes.
-
-### Controllers
-
-Simple changes have been made to controller classes:
-
-1. Remove `extends SimpleController`, no extension is required anymore.
-2. `use Slim\Http\Request;` must be changed to `use Psr\Http\Message\ServerRequestInterface as Request;`
-3. `use Slim\Http\Response;` must be changed to `use Psr\Http\Message\ResponseInterface as Response;`
-4. Since the DI container is not available globally in the controllers, the services you require must be [injected via the constructor](routes-and-controllers/controller-classes#service-injection).
- 1. For example, to use the `view` service, inject `Slim\Views\Twig`.
-5. Routes placeholder, usually in the `$args` variables, should now [be directly injected](https://php-di.org/doc/frameworks/slim.html#route-placeholder-injection). See [Retrieving URL Parameters](https://learn.userfrosting.com/routes-and-controllers/client-input#retrieving-url-parameters) for more information.
-
-See the [Controller classes](routes-and-controllers/controller-classes) guide for more information.
-
-> [!NOTE]
-> If your sprinkle extends a controller class from a default sprinkle instead of `SimpleController`, note that **every** controller class from the default sprinkles has been moved, renamed, and rewritten as *Action classes*. You will need to check out the sprinkle source code to find out how to update your sprinkle.
-
-### Bakery
-
-Simple changes have been made to bakery commands:
-
-1. Commands must extend `Symfony\Component\Console\Command\Command` instead of `UserFrosting\System\Bakery\BaseCommand`.
-2. Services should be injected through the class constructor (don't forget to call the parent constructor) or via [attribute injection](https://php-di.org/doc/attributes.html#inject).
-3. Add the `use UserFrosting\Bakery\WithSymfonyStyle;` trait to access `$this->io`.
-4. Commands should return `return self::SUCCESS;` or `return self::FAILURE;`.
-
-The biggest change is you're now required to **register your command in your sprinkle recipe**. Check out the [Bakery CLI](cli/custom-commands#command-class-template) chapter for more information.
-
-Also note that the `create-admin` command has been renamed `create:admin-user`. If you were adding custom commands to the "bake" command, you can now use the [Extending Aggregator Commands](cli/extending-commands) guide to achieve this more easily.
-
-### Resources Stream / Locator
-
-Not much has changed regarding the Resource Locator. Refer to the [Locator Service](advanced/locator) page for more information. Note, however, that the two streams below have been renamed:
-
-1. log -> logs
-2. session -> sessions
-
-### Template
-
-Three points are to be considered when working with templates:
-
-First, sprinkles have been renamed. If you're extending a default sprinkle, you'll need to update the sprinkle reference in the `extends` tag. For example: `{% extends "@admin/pages/activities.html.twig" %}` => `{% extends "@admin-sprinkle/pages/activities.html.twig" %}`. Check the table below for a list of sprinkle identifiers.
-
- | Name | Slug |
- |------------------|------------------|
- | Admin Sprinkle | admin-sprinkle |
- | AdminLTE Theme | adminlte-theme |
- | Account Sprinkle | account-sprinkle |
- | Core Sprinkle | core-sprinkle |
-
-In a similar way, some Twig templates have been moved to the "AdminLTE" sprinkle. Be sure to check the new structure if you're extending templates with the `extends` tag. Some template files previously in the Admin Sprinkle might be in the AdminLTE sprinkle now.
-
-FontAwesome has also been updated, and references to icons must also be updated: `fa` -> `fas`.
-
-### Misc
-
-1. Facades (Translator, etc.) are no longer available. The corresponding service should be injected properly now.
-2. Router `PathFor` has been changed. To generate a route based on its name, inject `UserFrosting\Sprinkle\Core\Util\RouteParserInterface` and use the `urlFor` method.
-3. Exceptions have changed, especially HTTP ones. For example: `use UserFrosting\Support\Exception\ForbiddenException;` => `use UserFrosting\Sprinkle\Account\Exceptions\ForbiddenException;`. Check out the [Exception and Error Handling](advanced/error-handling#default-exceptions) guide for more information.
-
-### Login redirect
-
-If your sprinkle was implementing a custom post-login destination, be sure to [check out the updated recipe](recipes/custom-login-page#changing-the-post-login-destination).
-
-### Testing
-
-If your sprinkle had automated testing:
-1. [Create a new Sprinkle Test case](testing/writing-tests/testcase)
-2. `setupTestDatabase` has been removed, it's no longer necessary.
-3. `UserFrosting\Sprinkle\Core\Tests\RefreshDatabase` is now `UserFrosting\Sprinkle\Core\Testing\RefreshDatabase`.
-4. `TestDatabase` is removed.
-5. `withTestUser` usage [has been updated](testing/writing-tests/traits#withtestuser).
-6. [Factories have been overhauled](testing/writing-tests/factories).
-
-## Assets
-
-Asset management has been completely changed. Instead of a custom solution, UserFrosting 5 now uses [Symfony's Webpack Encore](https://github.com/symfony/webpack-encore) to handle and build frontend assets. Your first stop should be the [Asset Chapter](asset-management) or the documentation for an in-depth guide for this new system.
-
-The key points here are:
-1. Your `asset-bundles.json` must be replaced with a new [entrypoint and entries](asset-management/asset-bundles).
-2. Rendering of assets (CSS and JS entries) [must be updated](asset-management/asset-bundles#rendering-entrypoints). Check out the `content/scripts_site.html.twig` and `content/stylesheets_site.html.twig` files from the skeleton repo for an example.
-3. Static assets must be [copied to the built directory](asset-management/basic-usage).
diff --git a/app/pages/6.0/22.upgrading/01.46-to-50/03.roadmap/docs.md b/app/pages/6.0/22.upgrading/01.46-to-50/03.roadmap/docs.md
deleted file mode 100644
index 4778bdbf..00000000
--- a/app/pages/6.0/22.upgrading/01.46-to-50/03.roadmap/docs.md
+++ /dev/null
@@ -1,54 +0,0 @@
----
-title: Future Roadmap
-description: ""
-obsolete: true
----
-
-## How will future update be done?
-
-You may be thinking at this point, how easy will it be to update to future version? The new structure has been created to make this easier. With UserFrosting 4, your Sprinkle where typically a fork of the whole UserFrosting project. This meant upgrading involved a complex git command to fetch upstream updates.
-
-With UserFrosting 5, updating should be as simple as doing `composer update`.
-
-- Revision versions (5.0.x) will require only `composer update` and `php bakery bake`;
-- Minor versions (5.x) will require `composer update`, `php bakery bake`, and optional upgrade tasks in an upgrade page;
-- Major version (6.0) will have a dedicated upgrade guide;
-
-Our commitment for UserFrosting 5 is for all bundled sprinkles (Core, Account, Admin and AdminLTE) and the Framework to follow the same "minor" version number. They might not have the same revision, but assuming you're starting with the "5.1" skeleton, you'll have "5.1" version of bundled sprinkle as well as the framework.
-
-## The Roadmap
-
-Now that UserFrosting 5 has been release, what does the future hold for the UserFrosting community? Here's a preview of what's planned for future versions. As always, your help and support is greatly appreciated. If you want to get involved in the future of UserFrosting, this list should help you get started with topic that you can get involved with.
-
-### UserFrosting 5.0.x
-
-The main focus of UserFrosting 5.0.x is to squash some bugs, and improve the code quality.
-
- - Address all "todo" inside the code;
- - Fix bugs in the login
- - Etc.
-
-### UserFrosting 5.1
-
-The main focus of UserFrosting 5.1 is :
-
-- Officially add PHP 8.3 support, drop PHP 8.1
-- Update locales (translations), move them to their custom sprinkle
-- Update Fontawesome
-- 100% test coverage on the core Sprinkle;
-- Improve Docker support
-- Remove Assets in Framework
-- Update Laravel
-- Add automated test on MariaDB
-- Etc.
-
-### UserFrosting 6
-
-Yes, UserFrosting 6 is already being planned! While UF5 goal was to completely rewrite the PHP backend, UF6 goal will be to completely rewrite the frontend !
-
-- Brand new custom theme, replacing AdminLTE, based on [UIKit](https://getuikit.com)
-- Replacing Handlebar and every frontend javascript code with [Vue.js](https://vuejs.org)
-
-The best part is UserFrosting 5 introduced the necessary tools to make this transition works. It could in fact be entirely possible to create the new frontend on UserFrosting 5 as an optional sprinkle! However, the goal for UserFrosting 6 is to make this new frontend the default one.
-
-You can find a proof of concept of this new Vue.js based UI (built in UF5 beta) here : [https://github.com/userfrosting/demo-vue/tree/main](https://github.com/userfrosting/demo-vue/tree/main)
diff --git a/app/pages/6.0/22.upgrading/01.46-to-50/chapter.md b/app/pages/6.0/22.upgrading/01.46-to-50/chapter.md
deleted file mode 100644
index fd85ab9e..00000000
--- a/app/pages/6.0/22.upgrading/01.46-to-50/chapter.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-title: 4.x to 5.0
-description: Upgrade guide for UserFrosting 5
-obsolete: true
----
-
-# Upgrading to UserFrosting 5
-
-Welcome, intrepid developers, to the wonders of **UserFrosting 5**! Since you're here, it's probably because you already enjoy UserFrosting 4 and you're willing to take your first step into the UserFrosting 5 journey. That's makes you awesome! Take a cupcake for the road and follow the next page as we go through the complex yet simple process.
-
-> [!NOTE]
-> If you're coming for a version older than UserFrosting 4, then you're even more awesome! You _definitely_ deserve a cupcake! If this is your case, you should consider [upgrading to V4 first](4.6/upgrading/3x-to-40), or start from scratch.
\ No newline at end of file
diff --git a/app/pages/6.0/22.upgrading/01.51-to-60/01.changelog/docs.md b/app/pages/6.0/22.upgrading/01.51-to-60/01.changelog/docs.md
new file mode 100644
index 00000000..133bfac1
--- /dev/null
+++ b/app/pages/6.0/22.upgrading/01.51-to-60/01.changelog/docs.md
@@ -0,0 +1,334 @@
+---
+title: What's New in 6.0
+description: Comprehensive changelog of new features, improvements, and breaking changes in UserFrosting 6.0
+wip: true
+---
+
+# UserFrosting 6.0 Changelog
+
+This page provides a comprehensive overview of changes in UserFrosting 6.0. For detailed migration instructions, see the [Migration Guide](upgrading/51-to-60/guide).
+
+## Major Changes
+
+### Unified Monorepo Architecture
+
+**What Changed**: UserFrosting has consolidated from six separate repositories into a single monorepo.
+
+**Before (5.1)**:
+```
+userfrosting/UserFrosting (Skeleton)
+userfrosting/framework (Core Framework)
+userfrosting/sprinkle-core (Core Sprinkle)
+userfrosting/sprinkle-account (Account Sprinkle)
+userfrosting/sprinkle-admin (Admin Sprinkle)
+userfrosting/theme-adminlte (AdminLTE Theme)
+```
+
+**After (6.0)**:
+```
+userfrosting/monorepo (Everything)
+```
+
+**Impact**:
+- Simpler dependency management
+- Consistent versioning across all components
+- Easier development and contribution workflow
+- Faster releases and bug fixes
+
+### Frontend Stack Overhaul
+
+#### Vite Replaces Webpack Encore
+
+**What Changed**: Asset bundling moved from Webpack Encore to Vite.
+
+**Key Benefits**:
+- ⚡ **Instant dev server**: No more waiting for compilation—changes appear in milliseconds
+- 🔥 **Hot Module Replacement**: Update code without losing application state
+- 📦 **Optimized builds**: Smaller bundles with automatic code splitting
+- 🎯 **Better DX**: Clearer error messages and simpler configuration
+
+**Breaking Changes**:
+- `webpack.config.js` → `vite.config.ts`
+- `encore` CLI commands → `php bakery assets:vite` commands
+- Different asset URL structure in development
+- Asset manifest format changed
+
+#### Vue 3 & TypeScript First-Class Support
+
+**What Changed**: Modern JavaScript development is now the default.
+
+**New Features**:
+- Vue 3 Single File Components (`.vue`) with `
+```
+
+> [!NOTE]
+> jQuery is deprecated but still supported in 6.0. You can migrate gradually, but new code should use Vue 3.
+
+## Step 9: Update Custom Sprinkles
+
+### Update Sprinkle Structure
+
+If you have custom sprinkles, update their structure:
+
+**Before (5.1)**:
+```
+app/sprinkles/mysprinkle/
+├── composer.json
+├── assets/
+│ └── webpack.config.js
+├── src/
+└── templates/
+```
+
+**After (6.0)**:
+```
+app/sprinkles/mysprinkle/
+├── composer.json
+├── assets/
+│ ├── vite.config.ts # If needed
+│ └── main.ts
+├── src/
+└── templates/
+```
+
+### Update Sprinkle Recipe
+
+Verify your sprinkle's Recipe class is compatible with UserFrosting 6.0. Most sprinkle recipes should work without changes, but review the [Sprinkles documentation](sprinkles) for any API changes.
+
+## Step 10: Database Migrations
+
+### Run Migrations
+
+UserFrosting 6.0 includes database updates:
+
+```bash
+# Run migrations
+php bakery migrate
+
+# If you encounter issues, rollback and retry
+php bakery migrate:rollback
+php bakery migrate
+```
+
+### Verify Database
+
+Check that all tables are present and properly structured:
+
+```bash
+# Check migration status
+php bakery migrate:status
+```
+
+## Step 11: Build and Test
+
+### Build Assets
+
+```bash
+# Build assets for production
+npm run vite:build
+
+# Verify build output
+ls -la public/assets/
+```
+
+### Start Development Servers
+
+Open two terminals:
+
+**Terminal 1** - PHP backend:
+```bash
+php bakery serve
+```
+
+**Terminal 2** - Vite frontend:
+```bash
+npm run vite:dev
+```
+
+### Test Your Application
+
+Visit `http://localhost:8080` and thoroughly test:
+
+- [ ] Homepage loads correctly
+- [ ] Login/logout functionality
+- [ ] User registration
+- [ ] Admin panel access
+- [ ] All custom features
+- [ ] API endpoints
+- [ ] Forms and validation
+- [ ] Asset loading (check browser console for errors)
+
+### Check Browser Console
+
+Open browser DevTools (F12) and verify:
+- No JavaScript errors
+- Assets loading correctly (200 status codes)
+- No 404 errors for missing files
+
+## Step 12: Production Deployment
+
+### Build Production Assets
+
+```bash
+# Build optimized production assets
+npm run vite:build
+
+# Verify build output
+ls -la public/assets/.vite/
+```
+
+### Update Environment Variables
+
+In production `.env`:
+
+```bash
+# Disable Vite dev server
+VITE_DEV_SERVER=false
+```
+
+### Deploy
+
+Follow your normal deployment process, ensuring:
+
+- Built assets are deployed (`public/assets/`)
+- Dependencies are installed (`composer install --no-dev`)
+- Configuration is set for production
+- Database migrations are run
+
+### Clear Caches
+
+```bash
+# Clear application caches
+php bakery cache:clear
+
+# Clear route cache
+php bakery cache:clear-routes
+```
+
+## Troubleshooting Common Issues
+
+### "Cannot find module" Errors
+
+**Symptom**: Vite can't find imported modules
+
+**Solution**:
+```bash
+# Clear node_modules and reinstall
+rm -rf node_modules package-lock.json
+npm install
+```
+
+### Assets Not Loading
+
+**Symptom**: 404 errors for assets in browser
+
+**Solution**:
+- Verify `vite.config.ts` paths are correct
+- Check `.env` has correct `VITE_DEV_SERVER` setting
+- Ensure Vite dev server is running (development)
+- Verify assets are built (`public/assets/`) (production)
+
+### Vue Components Not Rendering
+
+**Symptom**: Vue components don't appear on page
+
+**Solution**:
+- Check browser console for Vue errors
+- Verify Vue is imported in `main.ts`
+- Ensure components are properly registered
+- Check that mounting point (`#app`) exists in template
+
+### Database Migration Errors
+
+**Symptom**: Migrations fail to run
+
+**Solution**:
+```bash
+# Reset and re-run migrations (DEVELOPMENT ONLY)
+php bakery migrate:reset
+php bakery migrate
+
+# Check migration status
+php bakery migrate:status
+```
+
+### Performance Issues in Development
+
+**Symptom**: Slow page loads during development
+
+**Solution**:
+- Ensure Vite dev server is running (`npm run vite:dev`)
+- Check `optimizeDeps` in `vite.config.ts`
+- Clear Vite cache: `rm -rf node_modules/.vite`
+
+## Rollback Plan
+
+If you need to rollback to 5.1:
+
+```bash
+# Restore backups
+git checkout main
+cp composer.json.backup composer.json
+cp package.json.backup package.json
+
+# Reinstall old dependencies
+composer install
+npm install
+
+# Restore database from backup
+# (use your database backup restore process)
+```
+
+## Next Steps
+
+After successfully upgrading:
+
+1. **Review Documentation**: Read through the updated [Asset Management](asset-management) chapter
+2. **Optimize Assets**: Learn about [Vite Configuration](asset-management/vite-configuration) for performance tuning
+3. **Modernize Code**: Gradually convert jQuery to Vue 3 components
+4. **Add TypeScript**: Consider adding type safety to your custom code
+5. **Explore Features**: Check out new Vite features like HMR and code splitting
+
+## Getting Help
+
+If you encounter issues:
+
+- **Documentation**: [UserFrosting Learn](/)
+- **Community Chat**: [chat.userfrosting.com](https://chat.userfrosting.com)
+- **GitHub Issues**: [github.com/userfrosting/monorepo/issues](https://github.com/userfrosting/monorepo/issues)
+- **Stack Overflow**: Tag questions with `userfrosting`
+
+Congratulations on upgrading to UserFrosting 6.0! 🎉
diff --git a/app/pages/6.0/22.upgrading/01.51-to-60/03.what-to-expect/docs.md b/app/pages/6.0/22.upgrading/01.51-to-60/03.what-to-expect/docs.md
new file mode 100644
index 00000000..50a62dec
--- /dev/null
+++ b/app/pages/6.0/22.upgrading/01.51-to-60/03.what-to-expect/docs.md
@@ -0,0 +1,376 @@
+---
+title: What to Expect After 6.0
+description: Future roadmap and plans for UserFrosting beyond version 6.0
+wip: true
+---
+
+# What to Expect After UserFrosting 6.0
+
+UserFrosting 6.0 represents a major milestone in the framework's evolution, but it's not the end of the journey. This page outlines what you can expect in terms of updates, maintenance, and future development.
+
+## Version Support Policy
+
+### UserFrosting 6.0 (Current)
+
+**Status**: Active Development & Support
+
+- **New Features**: Regular feature additions
+- **Bug Fixes**: Prompt bug fixes and improvements
+- **Security Updates**: Immediate security patches
+- **Documentation**: Continuously updated and improved
+- **Community Support**: Active help via chat and GitHub
+
+**Recommended For**: All new projects and actively maintained applications.
+
+### UserFrosting 5.1 (Legacy)
+
+**Status**: Security Maintenance Only
+
+- **New Features**: ❌ No new features
+- **Bug Fixes**: ⚠️ Critical bugs only
+- **Security Updates**: ✅ Security patches for 12-18 months from 6.0 release
+- **Documentation**: 🔒 Frozen (available at [learn.userfrosting.com/5.1](https://learn.userfrosting.com/5.1))
+- **Community Support**: ⚠️ Limited, focus shifted to 6.0
+
+**End of Life**: Approximately 12-18 months after UserFrosting 6.0 stable release.
+
+**Recommended For**: Stable production applications that don't need new features and can't allocate migration time.
+
+## Release Cadence
+
+### Minor Releases (6.1, 6.2, etc.)
+
+**Frequency**: Every 3-4 months
+
+**What to Expect**:
+- New features that don't break backward compatibility
+- Performance improvements
+- Developer experience enhancements
+- Additional documentation and examples
+- Dependency updates (within semver constraints)
+
+**Example Features**:
+- Additional Vue 3 components
+- New Bakery CLI commands
+- Enhanced debugging tools
+- More Vite plugins and optimizations
+- Improved testing utilities
+
+### Patch Releases (6.0.1, 6.0.2, etc.)
+
+**Frequency**: As needed (typically every 2-4 weeks)
+
+**What to Expect**:
+- Bug fixes
+- Security patches
+- Documentation corrections
+- Dependency security updates
+- Performance optimizations
+
+## Planned Features & Improvements
+
+> [!NOTE]
+> The following are **potential future features** being considered. They are not commitments, and priorities may change based on community feedback and maintainer availability.
+
+### Short-Term (Next 6 Months)
+
+#### Enhanced Vue 3 Components Library
+
+**Status**: Under Development
+
+**Description**: A comprehensive set of pre-built Vue 3 components for common UserFrosting patterns:
+- Data tables with sorting, filtering, pagination
+- Form builders with validation
+- Modal dialogs
+- Alert/notification system
+- User pickers and role selectors
+
+**Why**: Reduce boilerplate and speed up development.
+
+#### Improved TypeScript Support
+
+**Status**: Planned
+
+**Description**:
+- Complete type definitions for all UserFrosting services
+- Type-safe API client generation
+- Better IDE autocomplete and error checking
+- Stricter type checking in core components
+
+**Why**: Catch errors earlier and improve developer experience.
+
+#### Testing Tools & Examples
+
+**Status**: In Progress
+
+**Description**:
+- More comprehensive testing documentation
+- Example test suites for common scenarios
+- Better factory definitions
+- Integration test helpers
+- Frontend testing with Vitest
+
+**Why**: Make testing easier and encourage test-driven development.
+
+### Mid-Term (6-12 Months)
+
+#### GraphQL API Option
+
+**Status**: Exploring
+
+**Description**: Optional GraphQL API layer alongside REST:
+- Type-safe queries and mutations
+- Efficient data fetching (no over/under-fetching)
+- Better support for complex frontend applications
+- Subscriptions for real-time features
+
+**Why**: Modern alternative to REST for complex data requirements.
+
+#### Enhanced CLI Tools
+
+**Status**: Planned
+
+**Description**:
+- Interactive sprinkle generator (`bakery make:sprinkle`)
+- Component scaffolding (`bakery make:vue-component`)
+- Migration helpers (`bakery make:migration`)
+- Better error messages and debugging output
+
+**Why**: Speed up common development tasks.
+
+#### Performance Monitoring
+
+**Status**: Exploring
+
+**Description**:
+- Built-in performance profiling
+- Database query logging and analysis
+- Asset loading optimization suggestions
+- Production monitoring hooks
+
+**Why**: Help developers identify and fix performance bottlenecks.
+
+### Long-Term (12+ Months)
+
+#### Headless CMS Mode
+
+**Status**: Concept
+
+**Description**: Optional headless mode where UserFrosting acts as a pure API backend:
+- Decoupled frontend deployment
+- Mobile app support
+- Third-party integration
+- Multi-frontend architecture
+
+**Why**: Support modern application architectures.
+
+#### Plugin Marketplace
+
+**Status**: Concept
+
+**Description**: A curated marketplace for UserFrosting extensions:
+- Vetted third-party sprinkles
+- Easy installation and updates
+- Quality ratings and reviews
+- Commercial and free options
+
+**Why**: Foster ecosystem growth and make extending UserFrosting easier.
+
+#### Multi-Tenancy Support
+
+**Status**: Concept
+
+**Description**: Built-in support for multi-tenant applications:
+- Tenant isolation
+- Shared or separate databases
+- Per-tenant customization
+- Tenant-aware routing and assets
+
+**Why**: Support SaaS applications built with UserFrosting.
+
+## Breaking Changes Policy
+
+UserFrosting follows [Semantic Versioning](https://semver.org/):
+
+### Major Versions (7.0, 8.0, etc.)
+
+**Frequency**: Every 2-3 years
+
+**May Include**:
+- Breaking API changes
+- Removal of deprecated features
+- Major architectural changes
+- Updated system requirements
+- New best practices
+
+**Migration**: Comprehensive upgrade guides provided.
+
+### Minor Versions (6.1, 6.2, etc.)
+
+**Frequency**: Every 3-4 months
+
+**Guarantees**:
+- ✅ Backward compatible
+- ✅ Safe to upgrade
+- ✅ Deprecations may be introduced (with warnings)
+- ✅ No breaking changes
+
+**Migration**: Usually drop-in replacement, minimal changes needed.
+
+### Patch Versions (6.0.1, 6.0.2, etc.)
+
+**Frequency**: As needed
+
+**Guarantees**:
+- ✅ Bug fixes only
+- ✅ No new features
+- ✅ No API changes
+- ✅ Safe to upgrade immediately
+
+**Migration**: No code changes required.
+
+## Deprecation Strategy
+
+When features are deprecated:
+
+1. **Announcement**: Deprecated features are clearly marked in documentation
+2. **Warning Period**: At least one minor version before removal
+3. **Alternatives**: Migration path provided to new approach
+4. **Support**: Deprecated features continue working until next major version
+
+**Example Timeline**:
+- **6.0**: Feature X is current
+- **6.1**: Feature X deprecated, Feature Y introduced as replacement
+- **6.2-6.x**: Both Feature X and Y available, warnings in logs
+- **7.0**: Feature X removed, Feature Y is the standard
+
+## Community Involvement
+
+UserFrosting is open-source and community-driven. You can influence the roadmap:
+
+### Contribute Code
+
+- Submit pull requests to [userfrosting/monorepo](https://github.com/userfrosting/monorepo)
+- Fix bugs, add features, improve documentation
+- Review and test pull requests from others
+
+### Provide Feedback
+
+- Report bugs and request features on [GitHub Issues](https://github.com/userfrosting/monorepo/issues)
+- Participate in discussions on [chat.userfrosting.com](https://chat.userfrosting.com)
+- Vote on feature requests and proposals
+
+### Support Development
+
+- [Donate on Ko-fi](https://ko-fi.com/lcharette)
+- [Become a sponsor on Open Collective](https://opencollective.com/userfrosting)
+- Hire core team members for consulting/development
+
+### Spread the Word
+
+- Share your UserFrosting projects
+- Write tutorials and blog posts
+- Answer questions from other users
+- Rate and review UserFrosting
+
+## Staying Updated
+
+### Announcements
+
+Official announcements are posted to:
+- [GitHub Releases](https://github.com/userfrosting/monorepo/releases)
+- [UserFrosting Blog](https://www.userfrosting.com/blog/) (when available)
+- [Community Chat](https://chat.userfrosting.com)
+
+### Newsletter
+
+Sign up for the UserFrosting newsletter (when available) to receive:
+- Major version announcements
+- Security advisories
+- Featured community projects
+- Tips and tutorials
+
+### Social Media
+
+Follow UserFrosting on social media for updates:
+- Twitter/X: [@UserFrosting](https://twitter.com/userfrosting) (if available)
+- GitHub: [userfrosting](https://github.com/userfrosting)
+
+## Upgrading Between Versions
+
+### Minor Version Upgrades (e.g., 6.0 → 6.1)
+
+**Process**:
+```bash
+# Update dependencies
+composer update
+npm update
+
+# Run any new migrations
+php bakery migrate
+
+# Rebuild assets
+npm run vite:build
+
+# Clear caches
+php bakery cache:clear
+```
+
+**Expected Time**: 15-30 minutes
+
+**Risk Level**: Low - backward compatible
+
+### Major Version Upgrades (e.g., 6.x → 7.0)
+
+**Process**:
+- Comprehensive upgrade guide provided
+- Review breaking changes
+- Update custom code
+- Test thoroughly
+
+**Expected Time**: Several hours to several days (depending on customization)
+
+**Risk Level**: Medium to High - breaking changes likely
+
+## Framework Philosophy
+
+As UserFrosting continues to evolve, these principles guide development:
+
+### Modern But Pragmatic
+
+We embrace modern tools and practices, but only when they provide clear benefits:
+- ✅ Adopt proven technologies (Vue 3, Vite, TypeScript)
+- ⚠️ Be cautious with bleeding-edge features
+- ❌ Avoid "hype-driven development"
+
+### Backward Compatibility
+
+We take backward compatibility seriously:
+- Breaking changes only in major versions
+- Clear migration paths provided
+- Deprecated features supported for reasonable periods
+
+### Developer Experience
+
+We prioritize developer happiness:
+- Fast development builds (Vite)
+- Clear error messages
+- Comprehensive documentation
+- Active community support
+
+### Educational Focus
+
+UserFrosting aims to teach best practices:
+- Documentation explains the "why" not just the "how"
+- Examples demonstrate modern PHP/JavaScript patterns
+- Comments in code help developers learn
+
+## Questions?
+
+Have questions about the future of UserFrosting?
+
+- **Technical Questions**: Ask in [chat.userfrosting.com](https://chat.userfrosting.com)
+- **Feature Requests**: Open an issue on [GitHub](https://github.com/userfrosting/monorepo/issues)
+- **General Discussion**: Start a thread in the community chat
+
+The UserFrosting team is committed to making this the best PHP framework for user-centered applications. Thank you for being part of the journey! 🚀
diff --git a/app/pages/6.0/22.upgrading/01.51-to-60/chapter.md b/app/pages/6.0/22.upgrading/01.51-to-60/chapter.md
new file mode 100644
index 00000000..79a9ba32
--- /dev/null
+++ b/app/pages/6.0/22.upgrading/01.51-to-60/chapter.md
@@ -0,0 +1,86 @@
+---
+title: 5.1.x to 6.0.x
+description: Complete upgrade guide for migrating from UserFrosting 5.1 to 6.0
+wip: true
+---
+
+# Upgrading from UserFrosting 5.1 to 6.0
+
+Welcome to **UserFrosting 6.0**! This major release represents a significant evolution of the framework, bringing modern development tools, improved performance, and a streamlined architecture.
+
+This guide walks you through the upgrade process step-by-step. While the changes are substantial, we've designed the migration path to be as smooth as possible.
+
+> [!WARNING]
+> This is a **major version upgrade** with breaking changes. Allocate appropriate time for testing and migration. Start with a development environment and thoroughly test before deploying to production.
+
+> [!NOTE]
+> Before proceeding, ensure you're running the latest version of UserFrosting 5.1 and have reviewed its changelog.
+
+## What This Guide Covers
+
+This section provides detailed information about:
+
+- **[Changelog](upgrading/51-to-60/changelog)**: Comprehensive list of changes, additions, and removals in 6.0
+- **[Migration Guide](upgrading/51-to-60/guide)**: Step-by-step instructions for upgrading your application
+- **[What to Expect](upgrading/51-to-60/what-to-expect)**: Future roadmap and what comes next after 6.0
+
+## Quick Overview
+
+The most significant changes in UserFrosting 6.0:
+
+### Repository Consolidation
+UserFrosting 5.1 was distributed across six separate repositories:
+- Skeleton (main application)
+- Framework (core framework)
+- Core (core sprinkle)
+- Account (user management sprinkle)
+- Admin (admin panel sprinkle)
+- AdminLTE (theme sprinkle)
+
+UserFrosting 6.0 consolidates everything into a **single monorepo** at `https://github.com/userfrosting/monorepo`. This simplifies development, versioning, and dependency management.
+
+### Frontend Modernization
+**Before (5.1)**:
+- Webpack Encore for asset bundling
+- jQuery for DOM manipulation
+- Bootstrap for UI components
+- Handlebars for client-side templating
+
+**After (6.0)**:
+- Vite for lightning-fast asset bundling with HMR
+- Vue 3 for reactive components
+- UIkit 3 for modern UI framework (in AdminLTE theme)
+- TypeScript for type-safe development
+- Native ES modules
+
+### Development Experience
+- **Faster builds**: Vite's instant dev server startup vs Webpack's compilation
+- **Hot Module Replacement**: See changes instantly without page refresh
+- **Better errors**: Clear, actionable error messages
+- **Simplified config**: Less boilerplate, more intuitive
+
+### PHP Requirements
+- **Minimum PHP version**: 8.1 (up from 8.0)
+- **Recommended PHP version**: 8.4
+- **Node.js requirement**: 18.0+ (LTS 24 recommended)
+
+## Migration Time Estimate
+
+Depending on your application's complexity:
+
+- **Simple application** (minimal customization): 2-4 hours
+- **Moderate application** (custom sprinkles, some frontend work): 1-2 days
+- **Complex application** (extensive customizations, multiple sprinkles): 3-5 days
+
+The frontend migration (Webpack → Vite) typically requires the most attention, especially if you have custom Vue components or complex asset pipelines.
+
+## Getting Help
+
+If you encounter issues during the upgrade:
+
+1. Check the [Troubleshooting](troubleshooting) chapter
+2. Search existing [GitHub issues](https://github.com/userfrosting/monorepo/issues)
+3. Ask in the [UserFrosting chat](https://chat.userfrosting.com)
+4. Open a new issue with detailed information about your setup
+
+Ready to begin? Start with the [Changelog](upgrading/51-to-60/changelog) to understand what's changed, then follow the [Migration Guide](upgrading/51-to-60/guide) for step-by-step instructions.
diff --git a/app/pages/6.0/22.upgrading/02.50-to-51/01.changelog/docs.md b/app/pages/6.0/22.upgrading/02.50-to-51/01.changelog/docs.md
deleted file mode 100644
index 0cbc4327..00000000
--- a/app/pages/6.0/22.upgrading/02.50-to-51/01.changelog/docs.md
+++ /dev/null
@@ -1,107 +0,0 @@
----
-title: What's new in 5.1
-description: A detailed look at what's new in UserFrosting 5.1
-obsolete: true
----
-
-UserFrosting 5.1 focuses on adding PHP 8.3 support, removing PHP 8.1 support, upgrading Laravel, PHPUnit & FontAwesome dependencies and continue improving code quality.
-
-## Changed Requirements
-UserFrosting 5.1 removes support for PHP version 8.1, which has reached [End Of Life](http://php.net/supported-versions.php) as of November 2023 and won't receive security update as of November 2024. **PHP version 8.3 is now recommended**.
-
-## Upgraded Dependencies
- - Update from Laravel 8 to Laravel 10
- - Update from PHPUnit 9 to PHPUnit 10
- - Update from Monolog 2 to Monolog 3
- - Update FontAwesome 5 to FontAwesome 6
-
-## Detailed changes
-Changes generally applied across UserFrosting includes :
- - Add automated testing against MariaDB [#1238](https://github.com/userfrosting/UserFrosting/issues/1238) on each sprinkles
- - Complete 100% test coverage & PHPStan Level 8 validation across all default packages
-
-### UserFrosting Framework
-#### General
-- Removed `src/Assets` (it isn't used as part of UserFrosting 5.0)
-- SprinkleManager is a bit more strict on argument types. Recipe classed must be a `class-string`. The actual instance of the class will now be rejected (it wasn't a documented feature anyway).
-
-#### Fortress
-Complete refactoring of Fortress. Mostly enforcing strict types, updating PHPDocs, simplifying code logic and making uses of new PHP features and method. Most classes have been deprecated and replaced by new classes with updated implementation.
-
-In general, instead of passing the *schema* in the constructor of Adapters, Transformers and Validators class, you pass it directly to theses class methods. This makes it easier to inject the classes as services and reuse the same instance with different schemas.
-
-[Check out the updated documentation](routes-and-controllers/client-input/validation) for more information on new class usage, as well as the upgrade guide.
-
-#### Config
-- Methods `getBool`, `getString`, `getInt` & `getArray` now return `null` if key doesn't exist, to make it on par with parent `get` method.
-
-#### Alert
-- Messages are now translated at read time ([#1156](https://github.com/userfrosting/UserFrosting/pull/1156), [#811](https://github.com/userfrosting/UserFrosting/issues/811)). Messages will be translated when using `messages` and `getAndClearMessages`. `addMessage` now accept the optional placeholders, which will be stored with the alert message. `addMessageTranslated` is **deprecated**.
-- Translator is not optional anymore. `setTranslator` method has been removed.
-- `addValidationErrors` is deprecated (N.B.: It can't accept the new `\UserFrosting\Fortress\Validator\ServerSideValidatorInterface`)
-
-#### UniformResourceLocator
-- Two locations cannot have the same name anymore. An `InvalidArgumentException` will be thrown otherwise. (Ref [userfrosting/UserFrosting#1243](https://github.com/userfrosting/UserFrosting/issues/1243)).
-- [*DEPRECATION*] Location's `getSlug` is deprecated (redundant with the name and not really used).
-
-### Core sprinkle
-#### Rework of the assets building commands
-This change allows new bakery command to update Npm assets, and eventually allows sprinkles to replace webpack with something else (eg. Vite). The new commands are :
- - `assets:install` : Alias for `npm install`.
- - `assets:update` : Alias for `npm update`.
- - `assets:webpack` : Alias for `npm run dev`, `npm run build` and `npm run watch`, each used to run Webpack Encore.
- - `assets:build` : Aggregator command for building assets. Include by default `assets:install` and `assets:webpack`. The `webpack` and `build-assets` command are now alias of this command. `bake` also uses this command now. Sub commands can be added to `assets:build` by listening to `AssetsBuildCommandEvent`.
-
-*tl;dr* : Use `php bakery assets:build` instead of `php bakery webpack` or `php bakery build-assets`.
-
-See [Assets Chapter](asset-management) and [Bakery commands](cli/commands) for more details.
-
-#### Loggers changes
-The different loggers now implement their own interface, for more flexibility with dependency injection. Debuggers should now be injected using their interface, instead of their class name.
-
-| Class name | Interface |
-| ------------------ | --------------------------- |
-| DebugLogger | DebugLoggerInterface |
-| ErrorLogger | ErrorLoggerInterface |
-| MailLogger | MailLoggerInterface |
-| QueryLogger | QueryLoggerInterface |
-| UserActivityLogger | UserActivityLoggerInterface |
-
-Behind the scene, each interface extends `Psr\Log\LoggerInterface`. Plus, instead of *extending* `Monolog\Logger`, each loggers now *wraps* `Monolog\Logger`. This makes the loggers decoupled from Monolog implementation, in favor of the PSR implementation, making it easier to replace Monolog if required.
-
-Finally, `UserActivityLogger` used to define some constants. These have been moved to `UserActivityTypes` enum.
-
-#### New bakery commands
-- [`serve`](cli/commands#serve) : Run the php built-in web server to test your application
-- [`debug:twig`](cli/commands#debug) : List all twig namespaces to help debugging
-
-#### New Twig Function
-Any configuration values can now be accessed in Twig using the [config](templating-with-twig/filters-and-functions#config) helper function. Before, only `site` subarray were available in Twig. Use this carefully, as sensitive information (ie. passwords) could be stored in config !
-
-#### Misc changes
-- Session database model now implements
-- `UserFrosting\Sprinkle\Core\Database\Models\Interfaces\SessionModelInterface`;
-- Use our own RouterParser, wrapped around Slim's RouteParser. Allows to add 'fallback' routes when names routes are not found.
-
-### Account sprinkle
-Missing permissions slugs were missing from the original seed, and thus from to the database ([#1225](https://github.com/userfrosting/UserFrosting/issues/1225)). See the next page for more information on this.
-
-### Admin Sprinkle
-No significant changes.
-
-### AdminLTE theme
-Add fallback routes when 'index' is not defined (Fix [#1244](https://github.com/userfrosting/UserFrosting/issues/1244))
-
-## Complete change Log
-
-See the changelog of each component for the complete list of changes included in this release.
-- [Skeleton](https://github.com/userfrosting/UserFrosting/blob/5.1/CHANGELOG.md#510)
-- [Framework](https://github.com/userfrosting/framework/blob/5.1/CHANGELOG.md#510)
-- [Core sprinkle](https://github.com/userfrosting/sprinkle-core/blob/5.1/CHANGELOG.md#510)
-- [Account sprinkle](https://github.com/userfrosting/sprinkle-account/blob/5.1/CHANGELOG.md#510)
-- [Admin sprinkle](https://github.com/userfrosting/sprinkle-admin/blob/5.1/CHANGELOG.md#510)
-- [AdminLTE sprinkle](https://github.com/userfrosting/theme-adminlte/blob/5.1/CHANGELOG.md#510)
-
-## Migrating
-
-Now that we've cover the basics changes, follow on to the next pages to the steps required to bring your app up to date with UserFrosting 5.1.
diff --git a/app/pages/6.0/22.upgrading/02.50-to-51/02.guide/docs.md b/app/pages/6.0/22.upgrading/02.50-to-51/02.guide/docs.md
deleted file mode 100644
index f21b52f8..00000000
--- a/app/pages/6.0/22.upgrading/02.50-to-51/02.guide/docs.md
+++ /dev/null
@@ -1,291 +0,0 @@
----
-title: Upgrade Guide
-description: Upgrade guide from version 5.0.x to 5.1.x
-obsolete: true
----
-
-## Dependencies
-### Composer
-
-Upgrading UserFrosting to `5.1.x` from `5.0.x` is as simple as updating your `composer.json` file and fetching updated dependencies! First, you'll need to edit your `composer.json`.
-
-Update from :
-```json
-// ...
-"require": {
- "php": "^8.0",
- "ext-gd": "*",
- "userfrosting/framework": "^5.0",
- "userfrosting/sprinkle-core": "^5.0",
- "userfrosting/sprinkle-account": "^5.0",
- "userfrosting/sprinkle-admin": "^5.0",
- "userfrosting/theme-adminlte": "^5.0"
-},
-// ...
-```
-
-To:
-```json
-// ...
-"require": {
- "php": "^8.1",
- "ext-gd": "*",
- "userfrosting/framework": "~5.1.0",
- "userfrosting/sprinkle-core": "~5.1.0",
- "userfrosting/sprinkle-account": "~5.1.0",
- "userfrosting/sprinkle-admin": "~5.1.0",
- "userfrosting/theme-adminlte": "~5.1.0"
-},
-// ...
-```
-
-Now, simply use composer to get up to date with everything :
-
-```bash
-$ composer update
-```
-
-### NPM
-
-Open `package.json` and update from :
-
-```json
-// ...
-"dependencies": {
- "@userfrosting/sprinkle-admin": "^5.0",
- "@userfrosting/theme-adminlte": "^5.0"
-},
-// ...
-```
-
-To:
-```json
-// ...
-"dependencies": {
- "@userfrosting/sprinkle-admin": "~5.1.0",
- "@userfrosting/theme-adminlte": "~5.1.0"
-},
-// ...
-```
-
-Now, simply use npm and [Bakery](cli) to get up to date with everything else:
-
-```bash
-$ npm update
-$ php bakery bake
-```
-
-## Migrating your Sprinkles
-
-### Font Awesome
-
-UserFrosting 5.1 now ships with Font Awesome 6 in the AdminLTE theme. While Font Awesome 6 is backward compatible with Font Awesome 5, some icons [have been renamed](https://docs.fontawesome.com/web/setup/upgrade/whats-changed#icons-renamed-in-version-6) and you might need to manually update these in your sprinkle.
-
-Checkout the Font Awesome guide for more information : [https://docs.fontawesome.com/web/setup/upgrade/whats-changed](https://docs.fontawesome.com/web/setup/upgrade/whats-changed)
-
-### Missing default permissions
-
-Some built-in permissions [were missing from the database](https://github.com/userfrosting/UserFrosting/issues/1225) :
- - `uri_role`
- - `uri_roles`
- - `uri_permissions`
- - `view_role_field`
- - `create_role`
- - `delete_role`
- - `update_user_field_role`
- - `update_role_field`
- - `view_user_field_permissions`
- - `view_system_info`
- - `clear_cache`
-
-To add them to the database, run `php bakery seed` and select `UserFrosting\Sprinkle\Account\Database\Seeds\DefaultPermissions`. These will also be added to the `site-admin` role when running the seed.
-
-> [!WARNING]
-> If your application defines custom permissions to the `site-admin` role or you customized this role, **do not run the seed** unless you want to lose any custom changes. Running the seed will revert back the role to it's default state.
-
-The `site-admin` role is now on par with the root user permission by default, except for the last two permissions added, `view_system_info` & `clear_cache`. Theses can be added to the role if desired using the UI.
-
-### `urlFor` service change
-
-When calling [`urlFor`](templating-with-twig/filters-and-functions#urlfor) **in PHP** (not Twig) to generate a route from its name, the service has been replaced. Find and replace the following import to upgrade:
-- Find : `use Slim\Interfaces\RouteParserInterface;`
-- Replace : `use UserFrosting\Sprinkle\Core\Util\RouteParserInterface;`
-
-### Alerts
-
-When using the [alerts](advanced/alert-stream) service, replace `addMessageTranslated(...);` with `addMessage(...);`. The old method is still available, but it is deprecated and will be removed in a future version.
-
-### Fortress
-
-Fortress has been completely rewritten for UserFrosting 5.1. Most classes have been kept and will continue working, but these have been marked deprecated and will be removed in future version. It is recommended to upgrade your code now to avoid issues later.
-
-#### RequestSchema
-The `UserFrosting\Fortress\RequestSchema` constructor's first argument now accepts the schema data as an array, as well as a string representing a path to the schema json or yaml file. The argument can still be omitted to create an empty schema. This change makes `UserFrosting\Fortress\RequestSchema\RequestSchemaRepository` obsolete and and such been ***deprecated***. For example:
-
-```php
-// Before
-$schemaFromArray = new \UserFrosting\Fortress\RequestSchema\RequestSchemaRepository([
- // ...
-]);
-
-// After
-$schemaFromArray = new \UserFrosting\Fortress\RequestSchema([
- // ...
-]);
-```
-
-#### RequestDataTransformer
-`UserFrosting\Fortress\RequestDataTransformer` is ***deprecated*** and replaced by `\UserFrosting\Fortress\Transformer\RequestDataTransformer` (*notice the difference in the namespace !*).
-
-When using the new class, instead of passing the schema in the constructor, you pass it directly to `transform()` or `transformField()`. For example :
-
-```php
-// Before
-$transformer = new \UserFrosting\Fortress\RequestDataTransformer($schema);
-$result = $transformer->transform($data, 'skip');
-
-// After
-$transformer = new \UserFrosting\Fortress\Transformer\RequestDataTransformer();
-$result = $transformer->transform($schema, $data, 'skip');
-```
-
-`\UserFrosting\Fortress\RequestDataTransformerInterface` is also ***deprecated*** and replaced by `\UserFrosting\Fortress\Transformer\RequestDataTransformerInterface`.
-
-> [!TIP]
-> Before, `RequestDataTransformer` was typically created inside the controllers each time it was needed. It now can be injected using `RequestDataTransformerInterface`.
-
-#### ServerSideValidator
-`\UserFrosting\Fortress\ServerSideValidator` is ***deprecated*** and replaced by `\UserFrosting\Fortress\Validator\ServerSideValidator` (*notice the difference in the namespace !*).
-
-When using the new class, instead of passing the schema in the constructor, you pass it directly to `validate()`. For example :
-
-```php
-// Before
-$validator = new \UserFrosting\Fortress\ServerSideValidator($schema, $this->translator);
-$result = $validator->validate($data);
-
-// After
-$adapter = new \UserFrosting\Fortress\Validator\ServerSideValidator($this->translator);
-$result = $validator->validate($schema, $data);
-```
-
-`\UserFrosting\Fortress\ServerSideValidatorInterface` is also ***deprecated*** and replaced by `\UserFrosting\Fortress\Validator\ServerSideValidatorInterface`.
-
-> [!TIP]
-> Before, `ServerSideValidator` was typically created inside the controllers each time it was needed. It now can be injected using `ServerSideValidatorInterface`. The translator will be "sub-injected" at the same time.
-
-#### FormValidationAdapter
-`UserFrosting\Fortress\Adapter\FormValidationAdapter` is ***deprecated***. Instead of defining the format in the `rules` method, you simply use of the appropriate class for the associated format.
-
-| Arguments | Code | Replacement class |
-| ------------------------------------------ | ----------------------------------------------------- | ---------------------------------------------------------- |
-| `$format = json` & `$stringEncode = true` | `rules()` or `rules('json')` or `rules('json', true)` | `UserFrosting\Fortress\Adapter\FormValidationJsonAdapter` |
-| `$format = json` & `$stringEncode = false` | `rules('json', false)` | `UserFrosting\Fortress\Adapter\FormValidationArrayAdapter` |
-| `$format = html5` | `rules('html5')` | `UserFrosting\Fortress\Adapter\FormValidationHtml5Adapter` |
-
-Finally, instead of passing the schema in the constructor, you now pass it directly to `rules()`.
-
-For example :
-```php
-// Before
-$adapter = new FormValidationAdapter($schema, $this->translator);
-$result = $adapter->rules('json', false);
-
-// After
-$adapter = new FormValidationArrayAdapter($this->translator);
-$result = $adapter->rules($schema);
-```
-
-```php
-// Before
-$adapter = new FormValidationAdapter($schema, $this->translator);
-$result = $adapter->rules(); // Or $result = $adapter->rules('json');
-
-// After
-$adapter = new FormValidationJsonAdapter($this->translator);
-$result = $adapter->rules($schema);
-```
-
-> [!TIP]
-> Again, the required adapter can now be injected into your class.
-
-#### JqueryValidationAdapter
-`UserFrosting\Fortress\Adapter\JqueryValidationAdapter` is ***deprecated***. Instead of defining the format in the `rules` method, you simply use of the appropriate class for the associated format.
-
-| Arguments | Code | Replacement class |
-| ------------------------------------------ | ------------------------------------------------------ | ------------------------------------------------------------ |
-| `$format = json` & `$stringEncode = false` | `rules()` or `rules('json')` or `rules('json', false)` | `UserFrosting\Fortress\Adapter\JqueryValidationArrayAdapter` |
-| `$format = json` & `$stringEncode = true` | `rules('json', true)` | `UserFrosting\Fortress\Adapter\JqueryValidationJsonAdapter` |
-
-```php
-// Before
-$validator = new JqueryValidationAdapter($schema, $this->translator);
-$result = $validator->rules();
-
-// After
-$validator = new JqueryValidationAdapter($this->translator);
-$result = $validator->rules($schema);
-```
-
-#### Validation errors
-
-`FormValidationAdapter` and `JqueryValidationAdapter` used to have an `errors()` method to fetch validation errors messages and `validate` used to return true if errors where found, an false otherwise. These messages are now directly returned as an array when calling `validate`. An empty array means no error. Therefor, the way to handle them has changed :
-
-Old :
-```php
-if ($validator->validate($data) === false && is_array($validator->errors())) {
- $e = new ValidationException();
- $e->addErrors($validator->errors());
-}
-```
-
-New :
-```php
-$errors = $this->validator->validate($schema, $data);
-if (count($errors) !== 0) {
- $e = new ValidationException();
- $e->addErrors($errors);
-
- throw $e;
-}
-```
-
-This change affect alert's `addValidationErrors`, which can't be used anymore.
-
-Old :
-```php
-$validator = new \UserFrosting\Fortress\ServerSideValidator($schema, $this->translator);
-if ($validator->validate($data) === false && is_array($validator->errors())) {
- $this->alert->addValidationErrors($validator);
- return;
-}
-```
-
-New :
-```php
-$validator = new \UserFrosting\Fortress\Validator\ServerSideValidator($this->translator);
-$errors = $this->validator->validate($schema, $data);
-if (count($errors) !== 0) {
- foreach ($errors as $idx => $field) {
- foreach ($field as $eidx => $error) {
- $this->alert->addMessage('danger', $error);
- }
- }
- return;
-}
-```
-
-### UserActivityLogger
-
-If using `UserActivityLogger` service, the default constants have been moved to the `UserActivityTypes` enum.
-
-| Old | New |
-| ------------------------------------------ | ------------------------------------ |
-| UserActivityLogger::TYPE_REGISTER | UserActivityTypes::REGISTER |
-| UserActivityLogger::TYPE_VERIFIED | UserActivityTypes::VERIFIED |
-| UserActivityLogger::TYPE_PASSWORD_RESET | UserActivityTypes::PASSWORD_RESET |
-| UserActivityLogger::TYPE_LOGGED_IN | UserActivityTypes::LOGGED_IN |
-| UserActivityLogger::TYPE_LOGGED_OUT | UserActivityTypes::LOGGED_OUT |
-| UserActivityLogger::TYPE_PASSWORD_UPGRADED | UserActivityTypes::PASSWORD_UPGRADED |
-
-Plus, injections can be replaced from `UserActivityLogger` to `UserActivityLoggerInterface`.
diff --git a/app/pages/6.0/22.upgrading/02.50-to-51/03.roadmap/docs.md b/app/pages/6.0/22.upgrading/02.50-to-51/03.roadmap/docs.md
deleted file mode 100644
index 54928f7d..00000000
--- a/app/pages/6.0/22.upgrading/02.50-to-51/03.roadmap/docs.md
+++ /dev/null
@@ -1,27 +0,0 @@
----
-title: Coming up next
-description: ""
-obsolete: true
----
-
-### UserFrosting 5.2
-
-The main focus of UserFrosting 5.2 will be :
-
-- Update locales (translations), move them to their custom sprinkle
-- Improve Docker support
-- Add Redis/Memecache session driver
-- (Maybe) Update Laravel to version 11
-- (Maybe) Require PHP 8.2 minimum
-- Etc.
-
-No release date has been determined right now. If you would like to give a hand, don't hesitate to contribute by sending a Pull Request on GitHub, or getting in touch on the [Chat](https://chat.userfrosting.com).
-
-### UserFrosting 6
-
-Meanwhile, work for [UserFrosting 6](upgrading/46-to-50/roadmap#userfrosting-6) is moving along! As a reminder, UF6 goal is to completely rewrite the frontend, with a brand new custom theme replacing AdminLTE and based on [UIKit](https://getuikit.com). Handlebar and every frontend javascript code will also be replaced with [Vue.js](https://vuejs.org).
-
-You can find a proof of concept of this new Vue.js based UI (built with UF5) and the foundation of the new theme, **Pink Cupcake**, at the links below.
-
-- [userfrosting/demo-vue](https://github.com/userfrosting/demo-vue/tree/main)
-- [userfrosting/theme-pinkcupcake](https://github.com/userfrosting/theme-pinkcupcake)
diff --git a/app/pages/6.0/22.upgrading/02.50-to-51/chapter.md b/app/pages/6.0/22.upgrading/02.50-to-51/chapter.md
deleted file mode 100644
index 2b95fe9e..00000000
--- a/app/pages/6.0/22.upgrading/02.50-to-51/chapter.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-title: 5.0.x to 5.1.x
-description: Upgrade guide for UserFrosting 5.1
-obsolete: true
----
-
-# Upgrading to UserFrosting 5.1
-
-Welcome, loyal developers, to the wonders of **UserFrosting 5.1**!
-
-UserFrosting 5.1 focuses on adding PHP 8.3 support, removing PHP 8.1 support, upgrading Laravel, PHPUnit & FontAwesome dependencies and continue improving code quality.
-
-> [!NOTE]
-> Before going further, make sure you're running the latest version of UserFrosting 5.0 and reviewed it's [upgrade guide](upgrading/46-to-50).
\ No newline at end of file
diff --git a/app/pages/6.0/22.upgrading/chapter.md b/app/pages/6.0/22.upgrading/chapter.md
index 7ffe9dd2..387da164 100644
--- a/app/pages/6.0/22.upgrading/chapter.md
+++ b/app/pages/6.0/22.upgrading/chapter.md
@@ -1,11 +1,57 @@
---
title: Upgrading
-description: Upgrading to future versions of UserFrosting is easy...
-obsolete: true
+description: Guide for upgrading to UserFrosting 6.0 from previous versions.
+wip: true
---
#### Chapter 22
-# Upgrading
+# Upgrading to UserFrosting 6.0
-Upgrading to newer versions of UserFrosting is easy, owing to the clean separation of the core codebase from your project's code. This chapter goes through this process for each new version in the 5 release cycle.
+UserFrosting 6.0 represents a major evolution of the framework, consolidating what was previously spread across six separate repositories into a single, unified monorepo. This structural change, combined with a modernized frontend stack and improved developer experience, makes this one of the most significant updates in UserFrosting's history.
+
+While the changes are substantial, the upgrade process is manageable when approached systematically. This chapter guides you through migrating from UserFrosting 5.1 to 6.0, explaining what's changed, why it changed, and how to update your application to take advantage of the new architecture.
+
+## What's New in 6.0
+
+UserFrosting 6.0 brings several major improvements:
+
+- **Unified Monorepo**: All components (Framework, Core, Account, Admin, AdminLTE) consolidated into one repository
+- **Modern Frontend Stack**: Transition from Webpack Encore to Vite with Hot Module Replacement
+- **Vue 3 & TypeScript**: First-class support for modern JavaScript development
+- **UIkit 3**: Updated UI framework replacing Bootstrap (in AdminLTE theme)
+- **Improved Developer Experience**: Faster build times, better error messages, simpler configuration
+- **PHP 8.1+ Required**: Leveraging modern PHP features and improved performance
+
+## Should You Upgrade?
+
+If you're starting a new project, absolutely use UserFrosting 6.0. For existing applications, consider:
+
+- **Green light**: If you're actively developing and can allocate migration time
+- **Yellow light**: If your app is in maintenance mode but could benefit from security updates
+- **Red light**: If your app is stable and you don't need new features (5.1 will receive critical security updates)
+
+UserFrosting 5.1 continues to receive security updates, so there's no immediate pressure to upgrade production applications. However, 6.0's improvements make it worthwhile for active projects.
+
+## Before You Begin
+
+> [!IMPORTANT]
+> **Back up your application and database** before starting the upgrade process. Test the upgrade in a development environment first, never directly in production.
+
+Requirements for UserFrosting 6.0:
+- PHP 8.1 or higher (8.4 recommended)
+- Composer 2
+- Node.js 18.0 or higher (24 LTS recommended)
+- npm 9.0 or higher
+
+## Upgrade Strategy
+
+The migration from 5.1 to 6.0 involves several layers:
+
+1. **Repository structure**: Moving from multiple repositories to monorepo
+2. **Dependencies**: Updating Composer and npm packages
+3. **Frontend assets**: Migrating from Webpack Encore to Vite
+4. **Configuration**: Adjusting for new structure and features
+5. **Custom code**: Updating your sprinkles for API changes
+
+This chapter walks you through each of these steps systematically.
From 4ec6d51667832b378e86c3054f1c087900d8671a Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 31 Jan 2026 22:51:41 +0000
Subject: [PATCH 03/13] Update Chapter 15 introduction and overview for Vue
3/modern stack
Co-authored-by: lcharette <2566513+lcharette@users.noreply.github.com>
---
.../15.client-side-code/01.overview/docs.md | 280 ++++++++++++++++--
app/pages/6.0/15.client-side-code/chapter.md | 63 +++-
2 files changed, 316 insertions(+), 27 deletions(-)
diff --git a/app/pages/6.0/15.client-side-code/01.overview/docs.md b/app/pages/6.0/15.client-side-code/01.overview/docs.md
index 0820642c..8cdd3cc6 100644
--- a/app/pages/6.0/15.client-side-code/01.overview/docs.md
+++ b/app/pages/6.0/15.client-side-code/01.overview/docs.md
@@ -1,25 +1,261 @@
---
-title: Overview
-description: An overview of the client-side components that ship with UserFrosting.
-obsolete: true
+title: Client-Side Stack Overview
+description: Understanding the modern frontend tools and libraries that power UserFrosting 6.0
+wip: true
---
-UserFrosting uses jQuery and Bootstrap to provide a rich, intuitive, and modern user interface.
-
-It also uses the following components by default (of course, you can replace any of these as you see fit in your own Sprinkles):
-
-- [Handlebars.js](http://handlebarsjs.com/) - [client-side templating engine](client-side-code/client-side-templating)
-- [FontAwesome](http://fontawesome.io/) - Wildly popular icon library
-- [Ionicons](http://ionicons.com/) - More icons
-- [Tablesorter](https://mottie.github.io/tablesorter/docs/) - Flexible client-side table sorting
-- [jQuery Validation Plugin](https://jqueryvalidation.org/) - client-side [validation](routes-and-controllers/client-input/validation)
-- [select2](http://select2.github.io/) - Dropdowns that support search, autocomplete, and more
-- [Moment.js](https://momentjs.com/) - Parse, validate, manipulate, and display dates in JavaScript
-- [URI.js](http://medialize.github.io/URI.js/) - URL parsing library
-- [SpeakingURL](https://pid.github.io/speakingurl/) - URL slug generation
-- [iCheck](http://icheck.fronteed.com/) - Attractive checkboxes
-- [clipboard.js](https://clipboardjs.com/) - A modern approach to copy text to clipboard
-- [jquery-slimscroll](http://rocha.la/jQuery-slimScroll) - required by AdminLTE theme
-- [fastclick](https://github.com/ftlabs/fastclick) - required by AdminLTE theme
-
-This chapter fills in some of the gaps in communication between the client and server-side code bases, and explains how UserFrosting uses Handlebars.js and custom jQuery plugins to build dynamic, fully interactive features in your client's browser.
+UserFrosting 6.0 uses a modern, component-based approach to building user interfaces. This page introduces the core technologies and explains how they work together to create fast, interactive web applications.
+
+## Core Technologies
+
+### Vue 3 - The Progressive Framework
+
+[Vue 3](https://vuejs.org/) is the heart of UserFrosting's client-side architecture. It's a progressive JavaScript framework that makes building interactive UIs straightforward and enjoyable.
+
+**What makes Vue 3 special**:
+- **Reactive data binding**: Your data and UI stay in sync automatically
+- **Component-based**: Build reusable pieces that encapsulate structure, style, and behavior
+- **Single File Components**: Keep your HTML, CSS, and JavaScript together in `.vue` files
+- **Composition API**: Organize complex logic more effectively than Options API
+- **Virtual DOM**: Efficient updates minimize browser repaints
+- **TypeScript-first**: Excellent TypeScript integration out of the box
+
+**Example** - A simple reactive component:
+```vue
+
+
+
+
+
+```
+
+No DOM manipulation, no event listeners to wire up manually—Vue handles it all.
+
+### TypeScript - Type Safety for JavaScript
+
+[TypeScript](https://www.typescriptlang.org/) is JavaScript with syntax for types. It helps you catch errors during development instead of in production.
+
+**Benefits**:
+- **Catch bugs early**: Type checking finds errors before you run the code
+- **Better IDE support**: Autocompletion, refactoring, and inline documentation
+- **Self-documenting**: Types serve as living documentation
+- **Safer refactoring**: Rename variables, methods, and interfaces with confidence
+
+**Example**:
+```typescript
+interface User {
+ id: number
+ username: string
+ email: string
+}
+
+function greetUser(user: User): string {
+ return `Hello, ${user.username}!`
+}
+
+// TypeScript catches this error at compile time:
+// greetUser({ id: 1 }) // Error: Missing required properties
+```
+
+> [!TIP]
+> TypeScript is optional but highly recommended. You can start with regular JavaScript and gradually add types as you learn.
+
+### UIkit - Modern CSS Framework
+
+[UIkit](https://getuikit.com/) is a lightweight, modular CSS framework that provides the building blocks for UserFrosting's default AdminLTE theme.
+
+**Key features**:
+- **Lightweight**: Smaller bundle size than Bootstrap
+- **Modular**: Import only the components you need
+- **LESS-based**: Easy theme customization with variables
+- **Responsive**: Mobile-first design out of the box
+- **Rich components**: Modals, dropdowns, accordions, and more
+
+**Example** - UIkit button:
+```html
+
+```
+
+### Vite - Modern Build Tool
+
+[Vite](https://vitejs.dev/) (covered in [Asset Management](asset-management)) handles building and bundling your frontend code.
+
+**Development benefits**:
+- **Instant server start**: No bundling during development
+- **Hot Module Replacement**: See changes immediately without page refresh
+- **Fast builds**: Significantly faster than Webpack
+
+### Axios - HTTP Client
+
+[Axios](https://axios-http.com/) is a promise-based HTTP client for making API requests.
+
+**Why we use it**:
+- **Consistent API**: Works the same in browsers and Node.js
+- **Automatic JSON parsing**: No need for `response.json()`
+- **Request/response interceptors**: Add authentication headers globally
+- **Better error handling**: Structured error objects
+- **Cancel requests**: Abort pending requests when needed
+
+**Example**:
+```typescript
+import axios from 'axios'
+
+// GET request
+const response = await axios.get('/api/users')
+const users = response.data
+
+// POST request with data
+await axios.post('/api/users', {
+ username: 'alex',
+ email: 'alex@example.com'
+})
+```
+
+## Supporting Libraries
+
+UserFrosting includes these additional libraries for common tasks:
+
+### FontAwesome - Icon Library
+
+[FontAwesome](https://fontawesome.com/) provides thousands of icons for your interface.
+
+**Usage in templates**:
+```html
+ User Profile
+ Settings
+```
+
+### Luxon - Date & Time Handling
+
+[Luxon](https://moment.github.io/luxon/) (modern replacement for Moment.js) handles date parsing, formatting, and manipulation.
+
+**Example**:
+```typescript
+import { DateTime } from 'luxon'
+
+const now = DateTime.now()
+const formatted = now.toFormat('yyyy-MM-dd HH:mm:ss')
+const relative = now.toRelative() // "2 hours ago"
+```
+
+### Highlight.js - Code Syntax Highlighting
+
+[Highlight.js](https://highlightjs.org/) provides syntax highlighting for code blocks (used in UserFrosting's documentation).
+
+## Legacy Libraries (Deprecated)
+
+> [!WARNING]
+> These libraries are included for backward compatibility but are **deprecated**. New code should not use them.
+
+### jQuery (Deprecated)
+
+**Status**: Included but deprecated. Will be removed in a future version.
+
+**Migration**: Replace jQuery code with Vue 3 components or vanilla JavaScript.
+
+**Why deprecated**: Modern browsers have native APIs for what jQuery provided, and Vue's reactivity makes DOM manipulation unnecessary.
+
+### Handlebars (Deprecated)
+
+**Status**: Deprecated in favor of Vue templates.
+
+**Migration**: Convert Handlebars templates to Vue Single File Components.
+
+**Why deprecated**: Vue's template syntax is more powerful and integrates better with component logic.
+
+### Bootstrap (Removed from Core)
+
+**Status**: Replaced by UIkit in the default AdminLTE theme.
+
+**Migration**: Convert Bootstrap classes to UIkit equivalents.
+
+**Why changed**: UIkit provides a modern, lightweight alternative with excellent customization through LESS.
+
+## How It All Works Together
+
+Here's how these technologies combine in a typical UserFrosting page:
+
+1. **Backend (PHP/Twig)**: Renders the initial HTML structure and injects data
+2. **Vue 3**: Takes over specific parts of the page (or the entire page) for interactivity
+3. **TypeScript**: Provides type safety for your Vue components and utilities
+4. **UIkit**: Styles components with responsive, beautiful CSS
+5. **Axios**: Communicates with the backend API for dynamic data
+6. **Vite**: Bundles everything together efficiently
+
+**Example flow**:
+```
+User loads page
+ ↓
+Twig renders HTML + data
+ ↓
+Vue mounts to DOM
+ ↓
+User clicks button
+ ↓
+Vue handles click event
+ ↓
+Axios sends API request
+ ↓
+Server responds with JSON
+ ↓
+Vue updates UI reactively
+```
+
+## Development Workflow
+
+Your typical development cycle:
+
+1. **Start dev servers** (in two terminals):
+ ```bash
+ php bakery serve # Backend (port 8080)
+ npm run vite:dev # Frontend (port 5173)
+ ```
+
+2. **Make changes** to Vue components or TypeScript files
+
+3. **See results instantly** via Hot Module Replacement—no page refresh needed
+
+4. **Build for production**:
+ ```bash
+ npm run vite:build
+ ```
+
+## File Organization
+
+Frontend code lives in `app/assets/`:
+
+```
+app/assets/
+├── main.ts # Application entry point
+├── theme.less # Main stylesheet (UIkit customization)
+├── components/ # Vue components
+│ ├── MyComponent.vue
+│ └── shared/
+│ └── Button.vue
+├── composables/ # Reusable Vue logic
+│ └── useAuth.ts
+├── css/ # Additional stylesheets
+├── public/ # Static assets (images, fonts)
+└── types/ # TypeScript type definitions
+```
+
+## What's Next?
+
+Now that you understand the stack, explore how to:
+
+- **[Export Variables](client-side-code/exporting-variables)**: Pass data from PHP to JavaScript
+- **[Build Vue Components](client-side-code/vue-components)**: Create reactive user interfaces
+- **[Work with Forms](client-side-code/components/forms)**: Handle user input and validation
+- **[Create Tables](client-side-code/components/tables)**: Display and manipulate data
+- **[Show Alerts](client-side-code/components/alerts)**: Provide user feedback
+
+> [!NOTE]
+> Don't feel overwhelmed! You don't need to master everything at once. Start with the basics and gradually explore more advanced features as needed.
diff --git a/app/pages/6.0/15.client-side-code/chapter.md b/app/pages/6.0/15.client-side-code/chapter.md
index 61366205..e1dab007 100644
--- a/app/pages/6.0/15.client-side-code/chapter.md
+++ b/app/pages/6.0/15.client-side-code/chapter.md
@@ -1,11 +1,64 @@
---
-title: Client-side Code
-description: UserFrosting ships with client-side plugins and code that allow the backend to seamlessly interface with popular Javascript libraries and offer a rich, modern user experience.
-obsolete: true
+title: Client-Side Development
+description: Building modern interactive user interfaces with Vue 3, TypeScript, and UIkit
+wip: true
---
#### Chapter 15
-# Client-side Code
+# Client-Side Development
-UserFrosting ships with client-side plugins and code that allow the backend to seamlessly interface with popular Javascript libraries and offer a rich, modern user experience.
+Modern web applications are fundamentally different from the static document-based websites of the past. Today's users expect rich, interactive experiences that respond instantly to their actions—without waiting for page reloads or server round-trips.
+
+UserFrosting 6.0 embraces this reality with a modern frontend stack centered around **Vue 3**, **TypeScript**, and **UIkit**. This chapter teaches you how to build reactive, component-based user interfaces that feel fast and responsive while integrating seamlessly with UserFrosting's backend.
+
+## The Modern Frontend Stack
+
+UserFrosting 6.0 uses these core technologies for client-side development:
+
+- **Vue 3**: Progressive JavaScript framework for building reactive user interfaces
+- **TypeScript**: Type-safe JavaScript that catches errors during development
+- **UIkit**: Lightweight, modular CSS framework with beautiful components
+- **Vite**: Lightning-fast build tool with Hot Module Replacement
+- **Axios**: Promise-based HTTP client for API communication
+
+Gone are the days of jQuery selectors and DOM manipulation. Vue 3's reactive data binding and component-based architecture make it easier to build complex UIs while writing less code.
+
+## Why Vue 3?
+
+If you're coming from jQuery or vanilla JavaScript, Vue 3 might seem like a significant change. Here's why it's worth learning:
+
+**Reactive Data Binding**: Changes to your data automatically update the UI. No more manually finding elements and updating their content.
+
+**Component-Based**: Break your UI into reusable pieces. Each component encapsulates its HTML, CSS, and JavaScript.
+
+**TypeScript Support**: Catch bugs before they reach production with type checking and intelligent code completion.
+
+**Better Performance**: Virtual DOM and optimized reactivity mean faster updates and smoother interactions.
+
+**Modern Developer Experience**: Hot Module Replacement (HMR) shows your changes instantly without page reloads.
+
+## What This Chapter Covers
+
+This chapter is your guide to building client-side features in UserFrosting:
+
+- **[Overview](client-side-code/overview)**: Understanding the client-side stack and available tools
+- **[Exporting Variables](client-side-code/exporting-variables)**: Passing data from PHP/Twig to JavaScript
+- **[Vue Components](client-side-code/vue-components)**: Building reactive components with Vue 3
+- **[Forms](client-side-code/components/forms)**: Creating validated, AJAX-powered forms
+- **[Tables](client-side-code/components/tables)**: Building data tables with sorting and filtering
+- **[Collections](client-side-code/components/collections)**: Managing dynamic lists of items
+- **[Alerts](client-side-code/components/alerts)**: Displaying notifications and messages
+
+> [!TIP]
+> If you're new to Vue 3, don't worry! This chapter explains concepts as we go. You don't need to be a Vue expert to build great features with UserFrosting.
+
+## Learning Path
+
+**If you're new to Vue**: Start with [Overview](client-side-code/overview) to understand the basics, then work through the component examples.
+
+**If you know Vue 2**: The [Vue Components](client-side-code/vue-components) section highlights what's different in Vue 3.
+
+**If you're upgrading from UserFrosting 5.1**: The component sections show how to migrate from jQuery plugins to Vue 3 patterns.
+
+Ready to build modern, interactive user interfaces? Let's dive in!
From 0fb9520abefe2dc804096a24c00a4f84a48e50de Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 31 Jan 2026 23:04:07 +0000
Subject: [PATCH 04/13] Update Chapter 15: exporting-variables and
vue-components for modern stack
Co-authored-by: lcharette <2566513+lcharette@users.noreply.github.com>
---
.../02.exporting-variables/docs.md | 438 +++++++--
.../03.client-side-templating/docs.md | 186 ----
.../03.vue-components/docs.md | 895 ++++++++++++++++++
3 files changed, 1243 insertions(+), 276 deletions(-)
delete mode 100644 app/pages/6.0/15.client-side-code/03.client-side-templating/docs.md
create mode 100644 app/pages/6.0/15.client-side-code/03.vue-components/docs.md
diff --git a/app/pages/6.0/15.client-side-code/02.exporting-variables/docs.md b/app/pages/6.0/15.client-side-code/02.exporting-variables/docs.md
index 578a87f9..30914b9c 100644
--- a/app/pages/6.0/15.client-side-code/02.exporting-variables/docs.md
+++ b/app/pages/6.0/15.client-side-code/02.exporting-variables/docs.md
@@ -1,133 +1,391 @@
---
-title: Exporting Variables to Javascript
-description: The server-side variables that UserFrosting automatically exports to your pages as Javascript variables, and suggestions for exporting additional variables in your application.
-obsolete: true
+title: Passing Data from Server to Client
+description: How to pass server-side data to your Vue components and JavaScript code in UserFrosting 6.0
+wip: true
---
-We often need to access the value of some server-side variable in our client-side code. For example, we use the value `site.uri.public` throughout our Javascript code when building urls for AJAX requests. The value of this variable is taken directly from UserFrosting's configuration variable of the same name, and embedded into a Javascript variable on every page.
+Modern web applications need to pass data from the backend (PHP) to the frontend (JavaScript/Vue). UserFrosting provides several strategies for this, depending on your needs.
-There are a number of ways to get the values of specific variables from the server to the client. For example:
+This page covers the main approaches: global configuration objects, page-specific data, component props, and data attributes. Choose the right approach based on your use case.
-- Embedding data in the page DOM (HTML attributes), and then retrieving it from the DOM using `.prop`, `.val`, `.data`, or some other Javascript method
-- Making a separate AJAX request for the value of the variable
-- Printing the value of a PHP/Twig variable directly into a `
{% endblock %}
```
-Twig will automatically convert the array you passed to `render` in your page controller method to a JSON object:
-
-```js
-
-// Appears in the rendered page DOM for /account/register
-
-var page = {
- "validators": {
- "register": {
- "rules": {
- "user_name": {
- "rangelength": [
- 1,
- 50
- ],
- "noLeadingWhitespace": true,
- "noTrailingWhitespace": true,
- "required": true,
- "username": true
- },
- ...
- },
- "messages": {
- "user_name": {
- "rangelength": "Username must be between 1 and 50 characters in length.",
- "noLeadingWhitespace": "The value for 'Username' cannot begin with spaces, tabs, or other whitespace.",
- "noTrailingWhitespace": "The value for 'Username' cannot end with spaces, tabs, or other whitespace.",
- "required": "Please specify a value for 'Username'.",
- "username": "Username may consist only of lowercase letters, numbers, '.', '-', and '_'."
- },
- ...
- }
- }
- }
-};
+**JavaScript/TypeScript Access**:
+```typescript
+// The page object is now available globally
+console.log(page.api_endpoint) // "/api/users"
+console.log(page.per_page) // 25
+
+// Use it in your Vue components or vanilla JS
+const users = page.initial_data
```
-## Dynamically extending JSON objects
+This approach works well for validation rules, API endpoints, initial data loads, and feature flags specific to a page.
+
+### 3. Vue Component Props (Best for Component Data)
+
+When using Vue 3 components, pass data directly as props through the component's mounting HTML.
-Occasionally, you will want to dynamically modify the contents of `site`, `page`, or some other JSON variable. For example, you might want to override a variable on a specific page. To do this, you can use jQuery's `extend` method:
+**Twig Template**:
+```twig
+
+
+
+
+```
+
+Or, better yet, pass props when creating the Vue app:
+
+**Twig Template**:
+```twig
+
-```js
```
-You should do this in your page template's `scripts_page` block, after loading the original versions of the variables but before loading any page asset bundles.
+**TypeScript**:
+```typescript
+import { createApp } from 'vue'
+import UserProfile from './components/UserProfile.vue'
+
+createApp(UserProfile, {
+ userId: window.userProfileData.userId,
+ username: window.userProfileData.username,
+ email: window.userProfileData.email
+}).mount('#user-profile')
+```
+
+### 4. Data Attributes (Best for Small Amounts of Data)
+
+For simple, element-specific data, use HTML5 `data-*` attributes. This is ideal when your JavaScript needs to know about specific elements on the page.
+
+**Twig Template**:
+```twig
+
+```
+
+**TypeScript**:
+```typescript
+document.querySelectorAll('.delete-user').forEach(button => {
+ button.addEventListener('click', async (e) => {
+ const target = e.currentTarget as HTMLButtonElement
+ const userId = target.dataset.userId
+ const userName = target.dataset.userName
+
+ if (confirm(`Delete user ${userName}?`)) {
+ await deleteUser(userId)
+ }
+ })
+})
+```
+
+**Vue 3 Alternative** (using template refs):
+```vue
+
+
+
+
+
+```
+
+### 5. API Requests (Best for Dynamic Data)
+
+For data that changes frequently or is too large to embed, fetch it via API calls after the page loads.
+
+**TypeScript**:
+```typescript
+import axios from 'axios'
+
+interface User {
+ id: number
+ username: string
+ email: string
+}
+
+// Fetch data after page load
+async function loadUsers(): Promise {
+ const response = await axios.get(`${site.uri.public}/api/users`)
+ return response.data
+}
+
+// Use in your code
+const users = await loadUsers()
+```
+
+**Vue 3 Composable** (reusable logic):
+```typescript
+// composables/useUsers.ts
+import { ref, Ref } from 'vue'
+import axios from 'axios'
+
+export function useUsers() {
+ const users: Ref = ref([])
+ const loading = ref(false)
+ const error = ref(null)
+
+ async function fetchUsers() {
+ loading.value = true
+ error.value = null
+
+ try {
+ const response = await axios.get(`${site.uri.public}/api/users`)
+ users.value = response.data
+ } catch (e) {
+ error.value = e as Error
+ } finally {
+ loading.value = false
+ }
+ }
+
+ return { users, loading, error, fetchUsers }
+}
+```
+
+## Choosing the Right Approach
+
+Use this decision tree:
+
+| Data Type | Best Approach | Why |
+|-----------|---------------|-----|
+| Site-wide config (URLs, CSRF) | Global `site` object | Available everywhere, cached |
+| Page-specific settings | Global `page` object | Page scope, easy access |
+| Component initialization | Vue props | Type-safe, reactive |
+| Element metadata | Data attributes | Semantic, standard HTML |
+| Large/dynamic data | API requests | Reduces initial page size |
+| Real-time data | API + polling/WebSockets | Always current |
+
+## Modern ES Modules and TypeScript
+
+With Vite and modern JavaScript, avoid global variables when possible. Instead, export and import values:
+
+**config.ts**:
+```typescript
+// Re-export site config with types
+export interface SiteConfig {
+ uri: {
+ public: string
+ }
+ csrf: {
+ name: string
+ value: string
+ keys: {
+ name: string
+ value: string
+ }
+ }
+}
+
+// Access global site object with type safety
+export const siteConfig: SiteConfig = (window as any).site
+```
+
+**Usage**:
+```typescript
+import { siteConfig } from './config'
+
+// Now fully typed!
+const url = `${siteConfig.uri.public}/api/users`
+```
+
+## Security Considerations
+
+> [!WARNING]
+> **Never expose sensitive data to the client:**
+> - Database credentials
+> - API keys or secrets
+> - Other users' private information
+> - Internal system paths
+> - Unfiltered user input (XSS risk)
+
+**Safe to expose:**
+- Public URLs and endpoints
+- CSRF tokens (designed for client use)
+- Current user's own data
+- Public configuration settings
+
+**Remember**: Anything in the HTML can be viewed by the user. Treat all client-side data as potentially compromised.
+
+## Debugging Data Transfer
+
+### View Available Data
+
+Open your browser's console and type:
+```javascript
+console.log('Site config:', site)
+console.log('Page data:', page)
+```
+
+### Validate JSON Structure
+
+If data isn't working as expected, check that your PHP array converts correctly to JSON:
+
+```php
+// Good - simple types convert cleanly
+'count' => 42,
+'name' => 'John',
+'active' => true
+
+// Problematic - resource types don't serialize
+'database' => $pdo, // ❌ Won't work
+
+// Solution - extract only the data you need
+'user' => [
+ 'id' => $user->id,
+ 'name' => $user->username
+]
+```
+
+## What's Next?
+
+Now that you know how to pass data from server to client, learn how to use it in:
+
+- **[Vue Components](client-side-code/vue-components)**: Build reactive UIs with the data
+- **[Forms](client-side-code/components/forms)**: Submit data back to the server
+- **[Tables](client-side-code/components/tables)**: Display collections of data
+
+> [!TIP]
+> Start simple with global objects (`site`, `page`), then graduate to Vue props and API calls as your application grows in complexity.
diff --git a/app/pages/6.0/15.client-side-code/03.client-side-templating/docs.md b/app/pages/6.0/15.client-side-code/03.client-side-templating/docs.md
deleted file mode 100644
index 1848be09..00000000
--- a/app/pages/6.0/15.client-side-code/03.client-side-templating/docs.md
+++ /dev/null
@@ -1,186 +0,0 @@
----
-title: Client-side Templating
-description: An overview of how UserFrosting uses Handlebars.js for client-side templating.
-obsolete: true
----
-
-
-In [Templating with Twig](templating-with-twig), we learned how Twig helps you separate the logic of your server-side application from the layout of the pages it generates. Handlebars.js plays a similar role on the client side of your application, in Javascript. The main difference is that with Twig we are often generating complete pages, whereas with Handlebars we typical only generate smaller snippets of HTML to be inserted into the DOM.
-
-## Handlebars.js basic usage
-
-Handlebars is fairly straightforward to use. A Handlebars template is created by calling `Handlebars.compile` on a string:
-
-```js
-var counterTemplate = Handlebars.compile("Owls in my care: {{owls.count}}");
-```
-
-We can then render this template, calling the template on a JSON object and appending the rendered template to an element in our page's DOM:
-
-```js
-var counterRendered = counterTemplate({
- owls: {
- count: 5
- }
-});
-var counterDOM = $(counterRendered).appendTo($("#parentDiv"));
-```
-
-Of course, the JSON object is optional and can be omitted if your template does not contain any dynamically generated content.
-
-### Template blocks
-
-Since writing long HTML snippets as strings can become unwieldy and difficult to read, we can place our templates in `script` tags with the `text/x-handlebars-template` type attribute. The entire `script` block can then be rendered in our page's Twig template:
-
-```html
-
-{# This contains a series of
-{% endverbatim %}
-```
-
-By placing each Handlebars template in a separate `script` tag, and giving each one a unique `id`, we make it easy to choose a template to compile and render in our Javascript code:
-
-```js
-var owlTemplate = Handlebars.compile($("#owl-description-item").html());
-```
-
-Note that since Handlebars and Twig have similar syntax, we wrap our Handlebars templates in Twig's `verbatim` tag so that Twig won't try to parse the Handlebars template when it renders the page.
-
-## Template syntax
-
-Handlebars.js and Twig use a similar syntax. As with Twig, placeholders are represented using the `{{double-mustache}}` notation. However, compared to Twig, Handlebars.js is fairly sparse in terms of control structures and other features.
-
-### If blocks
-
-In Handlebars, `#if` is a **helper**. Helpers always begin with `#` in their opening tag, and `/` in their closing tag.
-
-```html
-
- {{#if author}}
-
{{firstName}} {{lastName}}
- {{else}}
-
Unknown Author
- {{/if}}
-
-```
-
-It's also important to note that the `if` helper in Handlebars doesn't support logical expressions. For example:
-
-```html
-
-{{#if author == "Attenborough"}}
-
{{firstName}} {{lastName}}
-{{/if}}
-```
-
-To compare two values in an if/else block, use our custom Handlebars helper instead:
-
-```html
-{{#ifx author '==' 'David Attenborough' }}
-
{{firstName}} {{lastName}}
-{{/ifx}}
-```
-
-> [!IMPORTANT]
-> `#ifx` supports the basic logical operators (`==`, `!=`, `>`, `<`, etc), but does not support compound expressions. You can instead nest your expressions, or create your own custom helper. For more information, see [this Stack Overflow question](http://stackoverflow.com/questions/8853396/logical-operator-in-a-handlebars-js-if-conditional).
-
-### Loops
-
-Handlebars.js provides a limited syntax for loops using the `#each` helper:
-
-If you pass this object:
-
-```js
-var data = {
- owls: [
- "Fluffers",
- "Slasher",
- "Muhammad Owli"
- ]
-}
-```
-
-...when rendering this template:
-
-```html
-
- {{#each owls}}
-
{{this}}
- {{/each}}
-
-```
-
-Handlebars will generate the `li`s with the values from the `owls` list. In an `#each` block, `this` refers to the current value in our iteration over the array.
-
-In the real world, it's actually **fairly rare** that you will end up using the `#each` helper. More likely, you will end up with a template that renders just a **single element** of a list or row in a table. You'll then render each row using a jQuery loop:
-
-**Template:**
-
-```html
-{# "Parent" element that will hold your list of owls #}
-
-
-
-{# Handlebars template for generating the list items in myOwls #}
-{% verbatim %}
-
-{% endverbatim %}
-```
-
-Your page Javascript might have something like:
-
-```js
-// Compile the template
-var owlItemTemplate = Handlebars.compile($("#owls-list-item").html());
-
-// Loop through the owls, rending each item individually and then insert in the parent element
-$.each(data.owls, function (idx, owl) {
- var owlItemRendered = owlItemTemplate(owl);
- $(owlItemRendered).appendTo($("#myOwls"));
-});
-```
-
-This approach is very common in client side templating, because users often need to dynamically interact with collections of elements. Having a template for a single row or item allows you to dynamically add and remove individual items in your client-side application.
-
-## Other built-in helpers
-
-Handlebars' full list of built-in helpers can be found [here](http://handlebarsjs.com/guide/builtin-helpers.html#if).
-
-## Extra helpers
-
-UserFrosting provides some additional helpers on top of Handlebars' built-in ones:
-
-### dateFormat
-
-Format an ISO date using [Moment.js](http://momentjs.com).
-
-```
-{{name}} was adopted on {{dateFormat adoption_date format="MMMM YYYY"}}.
-```
-
-`format` should be a valid Moment.js [format string](https://momentjs.com/docs/#/displaying/format/).
-
-### phoneUSFormat
-
-Format a string as a US phone number (`(xxx) xxx-xxxx`)
-
-### currencyUsdFormat
-
-Format a floating-point value as US currency.
diff --git a/app/pages/6.0/15.client-side-code/03.vue-components/docs.md b/app/pages/6.0/15.client-side-code/03.vue-components/docs.md
new file mode 100644
index 00000000..a7900363
--- /dev/null
+++ b/app/pages/6.0/15.client-side-code/03.vue-components/docs.md
@@ -0,0 +1,895 @@
+---
+title: Building Vue 3 Components
+description: Learn how to create reactive, reusable UI components with Vue 3 Single File Components
+wip: true
+---
+
+Vue 3 is UserFrosting's recommended approach for building interactive user interfaces. Unlike the imperative jQuery patterns of the past, Vue uses declarative, component-based architecture that makes your code easier to understand, test, and maintain.
+
+This guide introduces Vue 3 components and shows you how to use them in UserFrosting applications.
+
+## What Are Vue Components?
+
+A Vue component is a self-contained piece of UI with its own:
+- **Template** (HTML structure)
+- **Logic** (JavaScript/TypeScript behavior)
+- **Styles** (CSS, scoped to the component)
+
+Think of components as custom HTML elements you can reuse throughout your application.
+
+**Simple example**:
+```vue
+
+
+
+
+
+
+
+```
+
+This single file defines everything the component needs. When used in your application, it creates an interactive button that tracks how many times it's been clicked.
+
+## Single File Components (SFCs)
+
+Vue 3 components in UserFrosting are written as **Single File Components** with a `.vue` extension. Each file contains everything the component needs in one place.
+
+**File structure**:
+```
+app/assets/
+└── components/
+ ├── UserCard.vue
+ ├── UserForm.vue
+ └── shared/
+ ├── Button.vue
+ └── Modal.vue
+```
+
+### Anatomy of an SFC
+
+**UserCard.vue** - A complete component example:
+```vue
+
+
+
+
+
{{ username }}
+
{{ email }}
+
+
+
+
+
+
+
+
+
+```
+
+The beauty of SFCs is that everything related to the component lives in one file, making it easy to understand and maintain.
+
+## Composition API with Script Setup
+
+UserFrosting uses Vue 3's `
+
+
+
+
+
{{ greeting }}
+
Age: {{ user.age }}
+
+
+
+```
+
+**Why we prefer `
+
+
+
{{ fullName }}
+
+
+```
+
+## Template Syntax
+
+Vue templates look like HTML but with special directives for dynamic behavior.
+
+### Text Interpolation
+
+Display reactive data with double curly braces:
+
+```vue
+
+
Message: {{ message }}
+
Count + 1: {{ count + 1 }}
+
Uppercase: {{ message.toUpperCase() }}
+
{{ isActive ? 'Active' : 'Inactive' }}
+
+```
+
+### Attribute Binding (v-bind / :)
+
+Bind reactive data to HTML attributes:
+
+```vue
+
+
+
+
+
+
+
+
+```
+
+**v-show** - Elements stay in DOM, just toggle `display`:
+
+```vue
+
+
+
+ This toggles display: none
+
+
+```
+
+### List Rendering (v-for)
+
+Loop through arrays or objects:
+
+```vue
+
+
+
+
+ {{ user.name }}
+
+
+
+
+
+
+ {{ index + 1 }}. {{ user.name }}
+
+
+
+
+
+
+ {{ key }}: {{ value }}
+
+
+
+```
+
+> [!IMPORTANT]
+> Always provide a unique `:key` when using `v-for`. This helps Vue track elements efficiently.
+
+### Two-Way Binding (v-model)
+
+Synchronize form inputs with state:
+
+```vue
+
+
+
+
+
+
+
+```
+
+### Emits (Child → Parent)
+
+Send events from child to parent:
+
+**Child.vue**:
+```vue
+
+
+
+
+
+```
+
+**Parent.vue**:
+```vue
+
+
+
+
+
+```
+
+## Lifecycle Hooks
+
+Run code at specific points in a component's life:
+
+```vue
+
+```
+
+**Most commonly used**:
+- `onMounted` - Fetch data, initialize libraries
+- `onUnmounted` - Cleanup (timers, listeners, subscriptions)
+
+## Using Components in UserFrosting
+
+### Step 1: Create the Component
+
+**app/assets/components/UserGreeting.vue**:
+```vue
+
+
+
Hello, {{ username }}!
+
You have {{ messageCount }} new messages
+
+
+
+
+
+
+
+```
+
+### Step 2: Register in Entry Point
+
+**app/assets/main.ts**:
+```typescript
+import { createApp } from 'vue'
+import UserGreeting from './components/UserGreeting.vue'
+
+const app = createApp({})
+
+// Register component globally
+app.component('UserGreeting', UserGreeting)
+
+// Mount to DOM
+app.mount('#app')
+```
+
+### Step 3: Use in Twig Template
+
+```twig
+{# Make sure you have a mount point #}
+
+
+```
+
+## TypeScript Best Practices
+
+UserFrosting components use TypeScript for better developer experience:
+
+```vue
+
+```
+
+## Best Practices
+
+### 1. Keep Components Focused
+
+Each component should have a single, clear purpose:
+
+✅ **Good**:
+- `UserCard.vue` - Display user info
+- `UserForm.vue` - Edit user
+- `UserList.vue` - List users
+
+❌ **Bad**:
+- `UserEverything.vue` - Does all user-related things
+
+### 2. Use Scoped Styles
+
+Always scope styles to avoid global conflicts:
+
+```vue
+
+```
+
+### 3. Props Down, Events Up
+
+Follow unidirectional data flow:
+- Parent passes data to child via props
+- Child notifies parent via events
+- Never mutate props directly
+
+```vue
+
+
+
+
+
+```
+
+### 4. Extract Reusable Logic
+
+Move shared logic to composables:
+
+```typescript
+// composables/useFetch.ts
+export function useFetch(url: string) {
+ const data = ref(null)
+ const loading = ref(false)
+ const error = ref(null)
+
+ async function fetch() {
+ loading.value = true
+ try {
+ const response = await axios.get(url)
+ data.value = response.data
+ } catch (e) {
+ error.value = e as Error
+ } finally {
+ loading.value = false
+ }
+ }
+
+ return { data, loading, error, fetch }
+}
+```
+
+## Debugging Vue Components
+
+### Vue DevTools
+
+Install [Vue DevTools](https://devtools.vuejs.org/) browser extension to:
+- Inspect component tree
+- View component state and props
+- Track emitted events
+- Profile component performance
+- Time-travel debug (see state history)
+
+### Console Debugging
+
+```vue
+
+
+
+
+
{{ JSON.stringify(user, null, 2) }}
+
+```
+
+## What's Next?
+
+Now that you understand Vue 3 components, learn how to build specific UI patterns:
+
+- **[Forms](client-side-code/components/forms)**: Build validated, AJAX-powered forms
+- **[Tables](client-side-code/components/tables)**: Create sortable, filterable data tables
+- **[Alerts](client-side-code/components/alerts)**: Display notifications and messages
+- **[Collections](client-side-code/components/collections)**: Manage dynamic lists
+
+## Further Learning
+
+- **[Vue 3 Official Guide](https://vuejs.org/guide/)** - Comprehensive Vue documentation
+- **[TypeScript with Vue](https://vuejs.org/guide/typescript/overview.html)** - TypeScript integration
+- **[Vite Documentation](https://vitejs.dev/guide/)** - Build tool details
+- **[Composition API FAQ](https://vuejs.org/guide/extras/composition-api-faq.html)** - Why Composition API?
+
+> [!TIP]
+> Don't try to learn everything at once. Start with basic components, add reactivity, then gradually explore advanced features like composables and TypeScript as you need them.
From dba1f2e2637aba81a8787f13cd2b0089be30b252 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 31 Jan 2026 23:15:33 +0000
Subject: [PATCH 05/13] Complete Chapter 15 (Client-Side Code) with Vue 3
components
Co-authored-by: lcharette <2566513+lcharette@users.noreply.github.com>
---
.../04.components/01.forms/docs.md | 760 ++++++++++--
.../04.components/02.tables/docs.md | 820 +++++--------
.../04.components/03.collections/docs.md | 1085 +++++++----------
.../04.components/04.alerts/docs.md | 641 +++++++++-
.../15.client-side-code/04.components/docs.md | 295 ++++-
5 files changed, 2253 insertions(+), 1348 deletions(-)
diff --git a/app/pages/6.0/15.client-side-code/04.components/01.forms/docs.md b/app/pages/6.0/15.client-side-code/04.components/01.forms/docs.md
index 9bb0df26..d0154e5f 100644
--- a/app/pages/6.0/15.client-side-code/04.components/01.forms/docs.md
+++ b/app/pages/6.0/15.client-side-code/04.components/01.forms/docs.md
@@ -1,166 +1,706 @@
---
-title: Forms
-description: The ufForm widget makes it easy to set up simple forms for validation and AJAX submission.
-obsolete: true
+title: Building Forms with Vue 3
+description: Create validated, AJAX-powered forms using Vue 3 and modern form handling patterns
+wip: true
---
-You may have noticed that in UserFrosting, forms are usually submitted via an AJAX request. By submitting forms with AJAX rather than HTML's native form submission, we can control the behavior of the page before submission (client-side validation, transforming form data) and after submission (deciding whether to reload the page, redirect, display messages, etc).
-
-UserFrosting's `ufForm` widget makes it easy to handle many form-submission tasks automatically. Simply create your usual form markup:
-
-```html
-