area17/twill
46.5
Weak · 19 September 2026
51.5k
lines of production code
PHP
with JavaScript
1
measurement over time
What this system is
This system is a Laravel-based content management framework, now branded as Twill, that provides a modular architecture for building admin interfaces and managing content. It enables developers to define content models with features like versioning, translations, and nested hierarchies, while offering a modern, Vue-driven frontend for block-based page building and media management. The platform supports granular permission controls, multi-subdomain routing, and cloud storage integration, serving as a comprehensive toolkit for creating custom CMS solutions.
How it got here
2016–2017 — Twill rebranding and Vue.js migration
74 changes.
The project underwent a comprehensive rebranding from CmsToolkit to Twill, restructuring the codebase architecture and configuration systems. This period focused on migrating the admin interface from legacy server-rendered Blade templates to a modern, component-driven Vue.js frontend with Vuex state management. Additionally, core backend services were refactored to support modular capsules, granular permissions, and multi-cloud storage backends.
2018–2022 — Twill 3.0 architecture and testing
85 changes.
This period focused on the comprehensive refactoring of the codebase to support the Twill 3.0 architecture, introducing a component-based block system, fluent form builders, and object-oriented listing filters. It also established a robust testing infrastructure with extensive PHPUnit integration and unit tests, while modernizing the frontend with Vue components and Tailwind CSS.
2023–2026 — Integration testing and form service refactoring
9 changes.
This period focused on expanding test coverage across the Capsule, User, Block, and Tag subsystems while introducing integration tests for exception handling. Concurrently, the codebase underwent structural improvements through the addition of block component stubs and the implementation of standardized traits for block rendering and subfield registration within the form services layer.
Features
Add AWS S3 and Glide cloud storage integration
The application now supports AWS S3 as a cloud storage source. A new \Aws\ service class in \src/Services/Cloud\ handles S3 client configuration and filesystem creation, reading credentials and settings from environment variables or config. The \Glide\ service has been updated to route image processing requests to this new AWS backend when the source is set to 's3' or 'aws'. An \Azure\ placeholder class is also added, though it currently throws an exception indicating it is not yet implemented.
src/Services/Cloud · high confidence
Add Azure Storage support and refactor S3 uploader configuration
The Uploader service now supports Azure Blob Storage in addition to S3. A new SignAzureUpload class handles Azure-specific SAS URL generation, while the existing SignS3Upload class has been refactored to accept a Config repository and use dynamic disk configuration (e.g., \filesystems.disks.{disk}.bucket\) instead of hardcoded S3-specific config keys. This allows the uploader to work with different storage disks defined in the application's filesystem configuration.
src/Services/Uploader · high confidence
Add Contact Page singleton module example
The tests-singleton example now includes a complete Contact Page singleton module, featuring a controller extending SingletonModuleController, a repository with behaviors for blocks, translations, slugs, media, files, and revisions, and a database migration creating the necessary tables. The module is configured in twill-navigation as a singleton, routed via the TwillRoutes facade, and includes a seeder to populate initial data. The form view integrates a custom Vue component (HelloWorld) to demonstrate custom frontend integration within the admin interface.
examples/tests-singleton · high confidence
Add Doctum-based API documentation generation setup
The docs-api directory now includes a complete setup for generating static API documentation using Doctum. This includes a configuration file that scans PHP files in the src directory, supports versioning for main, 2.x, and 3.x branches, and outputs built documentation to version-specific build directories. A README provides instructions for installing dependencies, building the documentation, and serving it locally, while a .gitignore file excludes generated cache, build, and vendor directories.
docs-api · high confidence
Add admin controllers and request handlers for Authors and Categories modules
This change introduces the HTTP layer for the new Authors and Categories modules within the test suite. It adds AuthorController and CategoryController classes extending ModuleController to define index options, table columns (including sorting and image variants for authors, and nested tree structures for categories), and routing prefixes. It also adds corresponding AuthorRequest and CategoryRequest classes to handle form validation rules for creating and updating these resources.
examples/tests-modules/app/Http · high confidence
Add block component stubs for form and view generation
New stub files have been added to the \src/Commands/stubs/blockComponent\ directory to support the generation of block components. The \component.php.stub\ provides a PHP class template that extends \TwillBlockComponent\, including a \render\ method and a \getForm\ method pre-configured with an \Input\ field for 'title' and a \Wysiwyg\ field for 'text'. The \view.blade.php.stub\ provides the corresponding Blade template, rendering the title in an \\<h2\>\ tag and the text content using the \$input\ helper.
src/Commands/stubs/blockComponent · high confidence
Add browser relationship example application
The examples/tests-browsers directory now contains a complete reference application demonstrating Twill's browser (relationship) features. It includes database migrations for Writers, Letters, Bios, and Books with revision support, along with the corresponding controllers, repositories, and form requests. The example showcases various browser configurations, such as single-select relationships (Bios linked to Writers) and multi-select relationships (Letters and Books linked to multiple Writers), using the new TwillRoutes facade for route registration.
examples/tests-browsers · high confidence
Add configuration files for translation, navigation, and Twill modules
Added three new configuration files to the examples/tests-modules area: translatable.php defines localization settings (locales, fallbacks, and property fallback behavior); twill-navigation.php configures the admin panel's primary navigation structure for Personnel and Categories; and twill.php sets up the dashboard modules for Authors and Categories, including their labels, route prefixes, and feature flags like search and drafts, alongside block editor and icon directory mappings.
examples/tests-modules/config · high confidence
Add deep-nested module example (Clients \> Projects \> Applications)
The \examples/tests-deep-nested\ location now includes a complete, deeply nested module structure demonstrating how to manage hierarchical data in Twill. This example adds three levels of modules—Clients, Projects, and Applications—each with their own controllers, repositories, form requests, database migrations, and site preview views. The controllers configure parent-child relationships using \getParentModuleForeignKey\ and \setModuleName\, while the navigation config registers the nested module paths (\clients\, \clients.projects\, \clients.projects.applications\) in the admin sidebar.
examples/tests-deep-nested · high confidence
Add example implementation for a Postings module with permissions and settings
This change introduces a complete, minimal example of a Twill-based application within the examples/tests-permissions directory. It adds a new 'Postings' content module, including the necessary controller, request validation, repository, database migration, and form view. The example is configured to use the new TwillRoutes facade for route registration and includes a settings page for SEO configuration. Additionally, the twill.php config file explicitly enables the 'postings' module and defines it in the permissions list, demonstrating how to restrict access to this new feature.
examples/tests-permissions · high confidence
Add nested 'nodes' module example with modern Twill conventions
The tests-nestedmodules example now includes a complete 'nodes' module demonstrating nested content management. This addition introduces a controller that enforces parent-only browsing in browsers, a repository utilizing the HandleNesting behavior, and a database migration defining the nodes table with nested set fields. The module is registered via the TwillRoutes facade instead of route macros, and the form view uses the modern x-twill::input component, reflecting an update to current framework conventions.
examples/tests-nestedmodules · high confidence
Add specific exception classes for filter configuration errors
Two new exception classes, FilterOptionsMissingException and MissingModelForFilterException, have been added to the listings filter service. These allow the application to throw distinct, typed errors when filter options are missing or when a model is not provided for a filter, improving error handling clarity for developers using the filtering system.
src/Services/Listings/Filters/Exceptions · high confidence
Added AppServiceProvider for the tests-modules example
A new AppServiceProvider has been added to the examples/tests-modules application. This file provides the standard Laravel service provider structure with empty register and boot methods, importing the TwillConfig facade, serving as the foundational service provider for this specific example module.
examples/tests-modules/app/Providers · high confidence
Added CapsuleSeeder class
A new CapsuleSeeder class has been introduced in the Capsules service, extending the Laravel Illuminate Seeder. This provides a dedicated entry point for seeding database data related to capsules.
src/Services/Capsules · high confidence
Added Twill form views for Authors and Categories
New Blade templates have been added to define the content entry forms for Authors and Categories within the Twill admin interface. The Author form now includes fields for an avatar, description, birthday, bio, and a block editor, while the Category form provides a single translated description field. These views extend the standard Twill form layout to structure how these specific content types are edited by administrators.
examples/tests-modules/resources · high confidence
Added background jobs for revision cleanup and nested item reordering
Two new queueable jobs have been introduced to handle asynchronous tasks. The CleanupRevisions job manages the deletion of old revisions for models implementing HasRevisions, respecting either a model-specific limit or a global configuration setting. The ReorderNestedModuleItems job handles the reordering of nested module items by saving the tree structure based on a provided list of IDs, ensuring these operations are performed within database transactions to maintain data integrity.
src/Jobs · high confidence
Added block builder template and icons listing page
The views/blocks area now includes a new builder template that renders block content with ESLint disabled for generated code, and a dedicated icons listing page that displays available icons in a responsive grid layout with their names and URLs.
views/blocks · high confidence
Added database migrations for pages and menu links in the basic page builder example
The basic page builder example now includes database migration files to set up the necessary schema. A new migration creates the 'pages' table along with associated 'page\_translations', 'page\_slugs', and 'page\_revisions' tables to support content management features like soft deletes, timestamps, and versioning. Another migration introduces the 'menu\_links' table, which utilizes a nested set structure to manage hierarchical menu items, along with fields for title, description, and position.
examples/basic-page-builder/database · high confidence
Added demo and test settings views for the Twill admin interface
The examples/tests-settings area now includes Blade templates for configuring demo and test settings within the Twill admin panel. Specifically, new views have been added for a 'Demo' setting (containing a single input field) and a 'Test' setting (containing translated and non-translated input fields alongside a block editor). Additionally, a site-level text block view and a corresponding Twill block configuration view for text content have been introduced to support rendering and editing these content types.
examples/tests-settings · high confidence
Added new block and repeater stubs for Twill content management
New stub files have been added to the \src/Commands/stubs/blocks\ and \src/Commands/stubs/repeaters\ directories to support the creation of specific content blocks. These include stubs for Carousel, Footnote, Gallery, Image, Quote, and Body text blocks, along with a corresponding Carousel item repeater. These stubs define the form fields and UI components (such as WYSIWYG editors, media pickers, and variation selectors) that developers can use as templates when generating new block types in the application.
src/Commands/stubs/blocks · high confidence
Added placeholder for customs components directory
A .keep file was added to the frontend/js/components/customs directory to ensure the folder is tracked by version control, establishing a location for future custom component implementations.
frontend/js/components/customs · high confidence
Basic page builder example adds route definitions
The basic-page-builder example now includes explicit route definitions in \routes/twill.php\ and \routes/web.php\. The Twill routes are registered for the 'pages' and 'menuLinks' modules using the \TwillRoutes\ facade, and web routes are added to handle frontend display for the home page and individual pages via the \PageDisplayController\.
examples/basic-page-builder/routes · high confidence
Expanded example models and new core setting/block models
The Twill package now includes a comprehensive set of new example models across multiple test scenarios (basic-page-builder, portfolio, tests-browsers, tests-capsules, tests-deep-nested, tests-modules, tests-nestedmodules, tests-permissions, tests-singleton, and tests-subdomain-routing), demonstrating advanced features such as nested blocks, capsules, subdomain routing, and custom presenters. Additionally, core models for AppSetting, Block, Feature, Group, and Permission have been introduced or significantly expanded to support new capabilities like settings block registration, granular permission scoping (global, module, item), and starred items in buckets.
area17/twill · high confidence
Expanded language support with new localization files
The application now includes new language files for Arabic (ar), Bosnian (bs), Czech (cs), and German (de), providing translated strings for authentication, dashboard, editor, and media library interfaces. Additionally, placeholder files have been added for numerous other languages (such as aa, ab, af, am, an, as, ay, az, ba, be, bg, bh, bi, bn, bo, br, ca, co, cy, da, dz, el, eo) to support future translation efforts, ensuring the localization infrastructure is ready for these regions.
lang · high confidence
Extended VSelect component with new props and logic
The VSelect component now includes an ExtendedVSelect variant that adds support for disabling the select field, enforcing required values, and toggling option selection via double-click. It also introduces logic to handle deletion of values when the search input is empty and ensures proper handling of selected options in multi-select scenarios.
frontend/js/components/VSelect · high confidence
Introduce Buckets component for managing content collections
Adds the core frontend components for the Buckets feature, allowing users to organize content into named collections. The new Bucket.vue component provides a dual-pane interface with a source list for selecting items and target panes for managing bucket contents, supporting drag-and-drop reordering, pagination, and filtering. Users can add items to buckets, move them between buckets (with support for restricted single-bucket or multi-bucket modes), and override bucket limits when configured. The implementation includes BucketItem.vue for individual item controls (including starring/featuring and dropdown selection) and BucketSourceItem.vue for source list display with language information.
frontend/js/components/buckets · high confidence
Introduce Vue-based table components with bulk editing and pagination
The table listing interface has been refactored into a suite of new Vue components (Datatable, TableRow, TableHead, Paginate, BulkEdit, TableFilters, Table) to replace the previous implementation. This change adds a BulkEdit toolbar that allows users to perform bulk actions such as publish, unpublish, feature, unfeature, delete, restore, and destroy on selected items, with actions dynamically enabled based on item status. The Datatable component now includes client-side pagination with configurable rows-per-page, column visibility toggling, and sorting. The UI supports sticky table headers, horizontal scrolling synchronization, and nested row rendering with drag-and-drop reordering capabilities.
frontend/js/components/table · high confidence
Introduce abstract TwillBlockComponent base class for block rendering
A new abstract \TwillBlockComponent\ class has been added to serve as the base for all block components. It provides a standardized factory method (\forRendering\) to instantiate blocks with context, and exposes helper methods for accessing block data such as \image\, \input\, \translatedInput\, and \repeater\ (including fallback logic for dynamic repeaters). The class also defines default behaviors for block identification (\getBlockIdentifier\), titles (\getBlockTitle\, \getBlockTitleField\), icons, validation rules, and form rendering, ensuring consistent structure across block implementations.
src/View/Components/Blocks · high confidence
Introduce nested hierarchical table listings
Adds new Vue components (NestedDatatable, NestedList, NestedItem) that enable users to view and interact with data in a hierarchical, nested structure. This feature supports multi-level indentation (up to a configurable max depth), visual hierarchy indicators (borders and connecting lines), and drag-and-drop reordering of rows within the nested tree.
frontend/js/components/table/nested · high confidence
Introduce traits and contracts for block rendering and subfield registration
This change introduces new contracts (\CanHaveSubfields\, \CanRenderForBlocks\) and corresponding traits (\HasSubFields\, \RenderForBlocks\) within the Forms service layer. These components provide a standardized mechanism for form fields to declare whether they should be rendered in block contexts and to recursively register dynamic repeaters across nested field structures, supporting the refactoring of form service code to reduce duplication.
src/Services/Forms/Traits · high confidence
Introduction of modular repository behavior traits
The repository layer has been refactored to use a set of distinct behavior traits (e.g., \HandleBlocks\, \HandleBrowsers\, \HandleRepeaters\, \HandleRevisions\, \HandlePermissions\) instead of monolithic implementations. This change introduces specific capabilities for managing nested block structures, JSON-based repeaters, browser field synchronization, and granular role/group/item-level permissions, while also adding support for OAuth user linking and nested module slugs.
src/Repositories/Behaviors · high confidence
Introduction of nested breadcrumbs service with route prefix support
A new breadcrumbs service has been added to the application, introducing \BreadcrumbItem\ and \Breadcrumbs\ classes to manage navigation items with specific display contexts (form vs. listing). The \NestedBreadcrumbs\ class extends this foundation to support hierarchical navigation for nested modules, automatically generating a breadcrumb trail that includes the parent module, the active parent record (resolved via a repository), and the current module's index and edit views. This implementation includes support for custom route prefixes, allowing nested breadcrumbs to correctly link to parent resources even when they reside under non-standard URL structures.
src/Services/Breadcrumbs · high confidence
Introduction of new foundational UI components
The frontend component library has been expanded with a suite of new, reusable Vue components to standardize the user interface. This includes an Accordion for collapsible content sections, an Avatar for user representation with fallback initials, and a comprehensive Browser system (Browser, BrowserField, BrowserItem) for selecting and managing media or content items with drag-and-drop support. Additionally, core interaction elements like Button, ButtonBar, Checkbox, CheckboxAccordion, and CheckboxGroup have been introduced to provide consistent styling and behavior across forms and listings.
frontend/js/components · high confidence
Introduction of new model contract interfaces
New PHP interfaces have been added to define specific capabilities for models: TwillLinkableModel for generating full URLs, TwillModelContract for core model behaviors like scoping published or accessible records, and TwillSchedulableModel for managing publish dates and visibility. These contracts standardize how models implement linking, querying, and scheduling features within the application.
src/Models/Contracts · high confidence
Media library image services migrated to Twill namespace with expanded capabilities
The Media Library image service implementations (Glide, Imgix, Local, and the new TwicPics service) have been moved from the \A17\\CmsToolkit\ namespace to \A17\\Twill\. This change introduces a new TwicPics image service with a parameter compatibility layer (\AbstractParamsProcessor\) to support standard image manipulation parameters like width, height, and format. The Glide service now supports signed URLs, configurable source/cache disks, and presets. The Imgix service has been refactored to use dependency injection for configuration, adds support for SVG parameter injection via a new config option, and improves dimension retrieval with fallback logic. The Local service now uses the configured storage disk for URL generation instead of a hardcoded path prefix.
src/Services/MediaLibrary · high confidence
New API store modules for content management operations
This change introduces a new set of API store modules (blocks, buckets, datatable, form, media-library, revision) that centralize HTTP requests for content management features. These modules handle operations such as listing, creating, updating, deleting, and bulk actions for content items, as well as managing media library assets, revisions, and block previews. All requests are routed through Axios and include standardized error handling via a global error utility.
frontend/js/store/api · high confidence
New Blade form field components
The form field rendering logic has been migrated to a new set of dedicated Blade components in the \src/View/Components/Fields\ directory. This introduces a \TwillFormComponent\ base class and specific components for fields such as Input, Select, Wysiwyg, Repeater, and Browser. Users can now utilize these components to render form fields, which support options like \direction\ for text inputs and \clearable\ for select fields, providing a more structured and type-safe approach to form building.
src/View/Components/Fields · high confidence
New CLI commands for block generation, capsule management, and asset building
This update introduces a suite of new Artisan commands to streamline development workflows. Developers can now create new block files with \twill:make:block\ and generate Vue components for blocks via \twill:make:componentBlock\. Module scaffolding is expanded with \twill:make:capsule\ and \twill:make:singleton\ to generate new capsules and singletons, while \twill:capsule:install\ allows installing external capsule packages. Asset management is enhanced with \twill:build\ (supporting \--hot\ and \--watch\ modes for development), \twill:dev\ for hot reloading, and \twill:blocks\ to generate single-file Vue components from Blade views. Additional utilities include \twill:refresh-crops\ for regenerating image crops, \twill:list:blocks\ and \twill:list:icons\ for inspecting available resources, and \twill:make:package\ for scaffolding new Twill extensions.
src/Commands · high confidence
New Media Library UI components
The media library interface has been rebuilt using new Vue components (MediaLibrary, MediaGrid, MediaSidebar, Uploader) to provide a unified modal experience for browsing, uploading, and managing media. Users can now filter by tags and unused status, select multiple items with shift-click, and edit metadata (tags, alt text, caption) in a sidebar that supports bulk editing. The uploader integrates with Fine Uploader to support S3, Azure, and traditional backends, featuring drag-and-drop, progress tracking, and error handling.
frontend/js/components/media-library · high confidence
New NavigationLink component for building navigation items
A new \NavigationLink\ component has been introduced in the navigation view components to provide a structured, fluent API for defining navigation entries. This component supports linking to specific routes, module actions, or external URLs, and allows for conditional rendering via a closure. It also handles hierarchical navigation by automatically including the parent item as the first child when sub-items are present, and respects the \twill.admin\_route\_name\_prefix\ configuration for generating module-specific route names.
src/View/Components/Navigation · high confidence
New SCSS mixin library for UI components and layout
The frontend styling system now includes a comprehensive set of new SCSS mixins in the \frontend/scss/setup/mixins\ directory to standardize component styling and layout. These additions provide reusable styles for accordions (trigger and icon handling), buttons (reset styles), form fields (placeholders, resets, and state management), and typography (font sizes, smoothing, and feature settings). Additionally, new grid and breakpoint mixins enable responsive column spanning and media query generation, while utility mixins support drag-and-drop grid visuals, link coloring, and background/keyline fills.
frontend/scss/setup/mixins · high confidence
New SCSS styles for Block and Box components
Added new SCSS files for the 'Block' and 'Box' molecule components to define their visual structure and spacing. The Block styles manage margins for headers, paragraphs, and separators within content editor blocks, while the Box styles define the layout for container elements with headers, footers, and filter links.
frontend/scss/molecules · high confidence
New SettingsGroup class for structured settings management
A new \SettingsGroup\ class has been introduced in the Settings service to provide a structured, object-oriented way to define and manage application settings. This class handles the creation and persistence of \AppSetting\ models, automatically generates database blocks for form sections, and manages route generation using the configured admin route name prefix. It also supports conditional availability via closures and optional menu registration, serving as the foundational component for the refactored settings architecture.
src/Services/Settings · high confidence
New asset resolution service with dev-mode and manifest fallback support
A new \Twill\ service class has been introduced in \src/Services/Assets\ to manage asset path resolution. It prioritizes development mode assets by fetching a manifest from a configured dev server URL (defaulting to \http://localhost:8080\), falling back to the vendor-published \twill-manifest.json\ if the public directory manifest is missing, and finally defaulting to a static path based on the \twill.public\_directory\ configuration. The service caches the manifest reading logic and handles SSL verification settings for JSON reads.
src/Services/Assets · high confidence
New basic-page-builder example for Twill 3.0
The \examples/basic-page-builder\ directory now provides a complete, standalone example application demonstrating a page builder setup for Twill 3.0. This example includes a page module with block editor support, a navigation module with nested menu links, and a homepage setting configuration. It features a blade-based frontend styled with Tailwind CSS and compiled via Vite, along with the necessary controllers, repositories, and service providers to wire these components together. A README is included to guide users through the Laravel and Twill installation process.
examples/basic-page-builder · high confidence
New command traits for Twill CLI operations
Added four new command traits to the \src/Commands/Traits\ directory to support internal CLI logic: \ExecutesInTwillDir\ for running shell commands within the Twill directory, \HandlesPotentialBreakingChangesWarnings\ to detect and prompt users to add missing database migrations introduced in version 3.5.0, \HandlesPresets\ to manage the installation and updating of example presets, and \HandlesStubs\ to provide utilities for replacing variables and conditionals in code stubs.
src/Commands/Traits · high confidence
New dashboard widgets for activity, statistics, and content feeds
The dashboard now includes dedicated Vue components for displaying activity logs, statistical trends, and content lists. The Activity Feed allows users to filter and paginate recent actions, while the Stats Feed visualizes metrics with trendlines and period selectors (today, yesterday, week, month). Additionally, a Generic Feed displays content items with optional thumbnails and view counts, and a Shortcut Creator provides quick links to create new entities and view item counts.
frontend/js/components/dashboard · high confidence
New field configuration traits for form inputs
A suite of new traits has been added to the form field builder to provide granular control over input behavior and appearance. Users can now configure layout and display options such as column counts, grid unpacking, inline display, borders, and button placement. Input constraints including minimum/maximum item counts, character length limits, and read-only states are now available. Additional capabilities include setting placeholders, defining field direction (LTR/RTL), adding field notes, and attaching JavaScript change handlers. Options management has also been enhanced with support for closures and individual option addition.
src/Services/Forms/Fields/Traits · high confidence
New file selection field with drag-and-drop and extension-based icons
A new FileField component has been introduced for selecting and managing files within forms. It supports reordering items via drag-and-drop (enabled when multiple items are present) and displays specific icons for files based on their extension, utilizing a new Extensions mapping file. The field allows configuration of a maximum item count, optional placement of the 'Add' button at the top, and integrates with the existing media library store for state management.
frontend/js/components/files · high confidence
New file-type, block, and WYSIWYG editor icon sets
The icon system now includes dedicated SVG sprite files for file-type indicators (e.g., ae, ai, doc, pdf, xls), block editor components (e.g., b-accordion, b-button, b-carousel, b-table), and WYSIWYG editor actions (e.g., wysiwyg\_bold, wysiwyg\_link, wysiwyg\_table). These are aggregated into a single sprite via \svg-sprite.blade.php\, ensuring consistent styling and availability across the interface.
views/partials/icons · high confidence
New form builder service classes for structured layouts and components
This change introduces a new set of service classes in src/Services/Forms to support a more structured form definition API. Key additions include BladePartial for rendering custom Blade views with shared form context, Columns for defining multi-column field layouts, and Fieldset/Fieldsets for grouping fields into collapsible sections. The Form class now supports side forms and fieldset-based rendering, while InlineRepeater gains new configuration options like max items, button-as-link styling, and connected field support. Additionally, Option and Options classes provide a typed way to define select options with selectable states.
src/Services/Forms · high confidence
New form utility partials for blocks, connected fields, and layout
Added a suite of new Blade partials in the form utils directory to enhance form builder capabilities. These include \\_block\_editor\_store\ and \\_blocks\_templates\ for managing block editor state and inline templates, \\_connected\_fields\ for conditional field visibility based on other field values, \\_columns\ for multi-column layouts, \\_fieldset\ and \\_collapsed\_fields\ for grouping and toggling field sections, \\_inline\_checkboxes\ for compact checkbox groups, and \\_selector\_input\_store\/\\_translatable\_input\_store\ for improved handling of selector and translatable field data in the JavaScript store.
views/partials/form/utils · high confidence
New frontend mixins for form, block, and table management
This change introduces a comprehensive set of new Vue mixins in the frontend to standardize and simplify component logic. The \formStore\ mixin centralizes form field state management with the Vuex store, supporting both modal and standard form contexts. New \block\, \blockEditor\, and \blockEditorItem\ mixins provide shared methods for managing block lifecycle events (add, edit, save, cancel, delete, clone) and UI state within the visual editor. Table-related mixins (\datatable\, \datatableRow\, \tableCell\) handle bulk actions, row editing, and column rendering logic. Additional mixins like \buckets\, \checkboxes\, \confirmationMixin\, \cropper\, \draggable\, \locale\, \maxlength\, \mediaField\, \retrySubmit\, and \toggleVisibility\ offer reusable functionality for specific UI patterns, while \addAttributes\ and \formatPermalink\ handle dynamic option merging and URL slug generation.
frontend/js/mixins · high confidence
New frontend utility library for CMS editing features
The frontend utility module has been expanded with a comprehensive set of new helper functions and components to support the CMS editor. This includes a robust form data processor (\getFormData\) that correctly structures block, repeater, and media selections for backend submission, and a cropper utility that fixes rounding errors in square image crops. Date handling is improved with locale-aware formatting filters and 24-hour time detection, while a new global error handler provides specific user notifications for session expiration (401) and permission denied (403) states. Additional utilities include a sticky navigation controller, a tooltip system, SVG injection helpers, and local storage management that gracefully falls back to cookies when necessary.
frontend/js/utils · high confidence
New global UI component styles for navigation, forms, and layout
This update introduces a comprehensive set of new global SCSS files that define the visual structure and behavior of core interface elements. Users will see styled components for the main header and mobile navigation overlays, including responsive layouts and scrollable navigation lists. The update also adds styles for breadcrumb trails, secondary navigation tabs, and a new three-dot loader animation. Additionally, it establishes base styling for form inputs (including search and number fields), draggable list items with transition effects, and Vue.js-based transitions for modals, dropdowns, and search overlays.
frontend/scss/globals · high confidence
New navigation partial view components
Added a set of new Laravel view components in the navigation partials directory to render specific UI sections: Breadcrumbs, Overlay, Primary, Secondary, Tertiary, Title, and User. These components delegate rendering to their respective Blade templates (e.g., \_breadcrumb, \_overlay\_navigation, \_primary\_navigation) and, where applicable, fetch data from the TwillNavigation facade to populate the UI with link groups, active titles, and hierarchical link structures.
src/View/Components/Partials · high confidence
New package generator command with updated stubs
A new command has been added to generate Twill CMS packages, supported by new stub files for instructions, composer.json, and the service provider. The generated composer.json now targets Twill version ^3.4, and the instructions guide users on how to integrate the package via path repositories and create their first capsule using the twill:make:capsule command.
src/Commands/stubs/package · high confidence
New repository implementations for Author, Category, and RevisionLimited modules
Added new repository classes for the Author, Category, and RevisionLimited modules within the tests-modules example. The AuthorRepository explicitly orders the HandleSlugs trait before HandleTranslations to prevent errors, addressing issue \#94. The CategoryRepository includes a custom setNewOrder method to handle tree structure updates via database transactions. The RevisionLimitedRepository provides a basic implementation using the HandleRevisions behavior.
examples/tests-modules/app/Repositories · high confidence
New role editing interface with granular permission controls
A new form view for editing roles has been introduced, providing users with a structured interface to manage permissions. This includes general permissions such as managing users, user roles, user groups, and media library access (view and upload). Additionally, users can configure content-specific permissions for individual modules, allowing them to assign view, edit, or manage access levels, with the 'manage' option available for specific role group items. The form also includes a setting to include the role in the 'Everyone' group.
views/roles · high confidence
New service providers and facades for Capsules, Blocks, and Settings
This release introduces a set of new service providers and facades to better structure the Twill core. The \CapsulesServiceProvider\ now handles capsule configuration and loading, while \TwillCapsules\ provides the logic for registering and discovering project and package capsules. New facades (\TwillBlocks\, \TwillAppSettings\, \TwillNavigation\, \TwillConfig\, \TwillPermissions\, \TwillRoutes\, \TwillUtil\) are added to expose their respective services. The \PermissionAuthServiceProvider\ centralizes gate definitions for user and module permissions, and \TwillBlocks\ manages block and repeater discovery. Additionally, the abandoned \cartalyst/tags\ package is internalized via \TaggableInterface\, \TaggableTrait\, and \TagsServiceProvider\ to support Laravel 13 compatibility.
src · high confidence
New specialized column types for listings
The listings table now supports a set of new, specialized column types that simplify displaying common data patterns. You can use the Boolean column to show checkmarks or crosses, the Image column to render thumbnails with configurable roles, crops, and rounded corners, and the Link column to display custom URLs with optional new-window behavior. The Relation and Browser columns allow displaying related model data (such as associated tags or media) directly in the table, while the NestedData column automatically counts and displays the number of related items. Additional columns include Presenter for using model presenter methods, and dedicated status columns for Publish, Scheduled, and Featured states, which are rendered on the frontend.
src/Services/Listings/Columns · high confidence
Optional migrations for permissions, roles, 2FA, and OAuth
This change introduces a new set of optional database migrations that allow users to enable granular permissions management, role-based access control, two-factor authentication, and OAuth integration. The \permissions-management\ migration creates tables for permissions, roles, and groups, seeds default roles (Owner, Administrator, Team, Guest), and migrates legacy string-based user roles to the new relational structure. The \users-2fa\ migration adds two-factor authentication columns to the users table when the feature is enabled. The \users-oauth\ migration creates a table to store OAuth provider tokens and user associations when OAuth is enabled. These migrations are optional and can be enabled via configuration flags.
migrations/optional · high confidence
Redesigned admin interface with Vue-based layouts and components
The admin interface has been completely overhauled to use a modern Vue.js architecture. The previous static Blade-based layouts (including the old main, head, and flash partials) have been replaced with new, specialized layout files for the dashboard, forms, listings, buckets, settings, and custom pages. These new layouts integrate Vue components for core interactions such as the title editor, publisher, media library, search, and data tables, and they initialize a centralized Vuex store to manage application state. This change shifts the CMS from a server-rendered template model to a dynamic, component-driven single-page application experience for the admin area.
views/layouts · high confidence
Redesigned authentication UI with two-factor and OAuth support
The authentication views have been completely rewritten to use a new shared layout (\views/auth/layout.blade.php\) that displays the application name, environment label, and branding. The login page now supports two-factor authentication via a dedicated \2fa.blade.php\ view and integrates optional OAuth providers (such as Google) using inline SVG icons and configuration-driven links. The interface also includes improved accessibility with proper tab indices, localized strings via \twillTrans\, and a new OAuth linking flow (\oauth-link.blade.php\) for associating social accounts.
views/auth · high confidence
Visual block editor with drag-and-drop and live preview
The editor now supports a visual interface where users can drag blocks from the sidebar into a live preview area, reorder them via drag handles or dropdown menus, and edit block content in a side panel. The preview renders blocks in sandboxed iframes that automatically resize to fit their content, and the sidebar provides controls to clone, delete, and move blocks while showing a loading state during updates.
frontend/js/components/editor · high confidence
Removals
Removal of SPF request handling trait
The \HandleSpfRequests\ trait, previously located in \src/Http/Controllers/Front/Behaviors\, has been removed from the codebase. This deletion eliminates the built-in support for handling Server Page Fragment (SPF) requests, including the logic for detecting navigation/prefetch states and generating the corresponding JSON responses for partial page loads.
src/Http/Controllers/Front/Behaviors · high confidence
Removal of legacy Blade templates for the file library UI
The legacy Blade view files for the file library interface have been deleted. This includes the main index page, the file form, the list template, the insert template, and the helper link for opening the file library modal. These changes remove the old server-rendered UI components, likely as part of a migration to a new frontend architecture (such as Vue.js components) or a different rendering strategy.
views/files · high confidence
Removal of legacy PHP block implementations
The legacy PHP-based block rendering classes (BaseBlock, ImageBlock, SeparatorBlock, and TextBlock) have been removed from the BlockEditor service. This change eliminates the previous PHP-side logic for rendering block types such as images, text, and separators, indicating a shift away from this server-side rendering approach for these components.
src/Services/BlockEditor/Blocks · high confidence
Removal of legacy block rendering service
The \RenderBlocks\ class in the BlockEditor service has been removed. This class previously handled the conversion of block JSON data into HTML and metadata, including methods for processing full JSON structures, single blocks, and extracting images for sitemaps. Its removal indicates a shift in how block content is rendered, likely moving this logic to a different component or service within the application.
src/Services/BlockEditor · high confidence
Removal of legacy files and fileables database migrations
The migration file responsible for creating the 'files' and 'fileables' database tables has been removed from the codebase. This change eliminates the automatic creation of these specific schema structures during database setup, indicating that these tables are no longer part of the current application's data model or are managed through a different mechanism.
migrations · high confidence
Removal of legacy media library views
The legacy Blade templates for the media library interface have been removed. This includes the modal link opener, the main index/list views, the media form, the uploader component, and the crop and insert templates. These files are no longer part of the application, indicating a shift away from the previous server-rendered media management UI.
views/medias · high confidence
Removal of legacy navigation view partials
The legacy Blade view partials for the site's navigation structure have been removed. Specifically, the breadcrumb, global, primary, and secondary navigation components located in views/layouts/navigation are no longer present. This change eliminates the previous server-side rendering logic for these menu sections, indicating a shift away from the older navigation implementation.
views/layouts/navigation · high confidence
Architecture
Centralized SCSS import structure
The frontend styles are now consolidated through a new \\_imports.scss\ manifest file, which is included by \app.scss\. This single entry point organizes and loads all atomic, molecular, and organism-level styles, global layout and navigation components, vendor overrides, and utility classes, providing a unified and maintainable structure for the application's CSS.
frontend/scss · high confidence
Refactored frontend into modular Vue entry points with vendor component support
The frontend JavaScript structure has been reorganized from a monolithic entry point into distinct, purpose-specific Vue applications (main, dashboard, form, listing, buckets, free, and search). This change introduces a new \custom-components.js\ module that dynamically registers custom and vendor-provided Vue components, enabling third-party extensions to inject UI elements into the admin interface. Additionally, the global initialization script now integrates Alpine.js for lightweight DOM interactions alongside the existing Vue apps.
frontend/js · high confidence
Refactored frontend store into modular Vuex architecture
The frontend state management has been restructured from a monolithic store into a modular Vuex architecture, introducing dedicated modules for distinct content areas: blocks (visual editor), buckets (bulk management), browser (resource selection), form (submission and validation), media library, publication (publishing workflow), and revisions. This change centralizes state handling for these features, enabling better organization and reactivity for the content editor interface.
frontend/js/store/modules · high confidence
Store mutations are modularized into domain-specific files
The store mutation definitions have been reorganized from a single location into separate modules for each domain (attributes, blocks, browser, buckets, datatable, form, language, media-library, modal-edition, notification, parents, preview, publication, revision, and subscribers). This structure centralizes mutation constants and logic within their respective areas, improving maintainability and clarity for developers working on specific features like forms, media, or browser interactions.
frontend/js/store/mutations · high confidence
Behavioural changes
Added placeholder for twill-assets directory
A .gitkeep file was added to the twill-assets directory to ensure the folder is tracked by version control, preserving the directory structure even if it remains empty of other files.
twill-assets · medium confidence
Admin controllers refactored to use dependency injection and new service abstractions
The admin controllers (AppSettings, Dashboard, Featured, Group, Icons, Role, Setting, Singleton, and Blocks) have been rewritten to replace static facade calls (such as config(), request(), view(), and redirect()) with explicit constructor injection of their corresponding service interfaces (Config, Request, ViewFactory, Redirector, etc.). This change improves testability and aligns the controllers with modern Laravel service-container practices. Additionally, the BlocksController has been moved from the CmsToolkit namespace to the core Twill namespace and now uses the new BlockRenderer service for preview rendering.
src/Http/Controllers/Admin · high confidence
Admin password reset and welcome notifications now respect the admin route name prefix
The notification classes in src/Notifications (PasswordResetByAdmin, Reset, TemporaryPassword, and Welcome) have been updated to construct their email action URLs using the \twill.admin\_route\_name\_prefix\ configuration value. This ensures that password reset and welcome emails generated by administrators correctly link to the admin-specific login or reset forms when a custom route prefix is configured, rather than relying on default or public routes.
src/Notifications · high confidence
Automated upgrade rules for route and view namespace changes
New Rector rules have been added to automatically refactor code during upgrades: \RenameRoutes\ updates \route()\ calls from the \admin.\ prefix to \twill.\, and \RenameViews\ updates \view()\ calls from \admin.\ to \twill.\. These rules rely on a new \LaravelAwareRectorRule\ base class that bootstraps the Laravel application to dynamically load current route definitions, ensuring the refactoring targets the correct legacy-to-new mappings. A \LegacyTableConfig\ rule is also included to manage legacy table configuration entries.
src/Rector · high confidence
Backend authentication and routing behavior updates
The backend authentication flow now respects the \twill.admin\_route\_name\_prefix\ configuration for all internal routes, including login redirects and guest redirections. Unauthenticated or unpublished users are explicitly logged out and redirected to the login form instead of receiving errors. A new \ValidateBackHistory\ middleware prevents the browser back button from accessing authenticated pages after logout by adding cache-control headers. User language preferences are now applied via the \Localization\ middleware, and subdomain-based routing is supported through the \SupportSubdomainRouting\ middleware, which dynamically adjusts app configuration and navigation per subdomain. The \Permission\ middleware enforces subdomain access restrictions for non-super-admin users. Additionally, the \Impersonate\ and \RedirectIfAuthenticated\ middleware have been refactored to use dependency injection and the specific \twill\_users\ guard, replacing facade usage for better testability and consistency.
src/Http/Middleware · high confidence
Basic page builder example now uses Tailwind CSS and Quill editor
The basic page builder example has been updated to use Tailwind CSS for styling, with a new \app.css\ file importing Tailwind utilities and a responsive navigation menu component. The text block editor in the admin interface now uses the Quill WYSIWYG editor instead of the previous default, and the frontend page layout supports cover images and block rendering with improved typography and spacing.
examples/basic-page-builder/resources · high confidence
Centralized UI configuration and notification system
The frontend now registers a comprehensive set of UI components (such as text fields, media libraries, and date pickers) and directives globally via the new A17Config plugin, eliminating the need for individual imports in views. Additionally, a new A17Notif plugin introduces a global \notif\ method and an \a17-notif\ component, allowing any part of the application to trigger notifications by committing to the store.
frontend/js/plugins · high confidence
CloudFront cache invalidation now supports specific paths
The CloudFront cache service has been updated to allow invalidating specific URL paths rather than only the entire distribution. The \invalidate\ method now accepts an optional array of URLs (defaulting to \\['/\*'\]\), enabling users to clear only targeted content. Additionally, AWS SDK configuration (region and version) has been moved to the application config file (\services.cloudfront\), with hardcoded defaults retained for backwards compatibility, and the service now relies on dependency injection for configuration access.
src/Services/Cache · high confidence
Configuration system restructured and renamed from CmsToolkit to Twill
The package's configuration has been reorganized into a modular structure, replacing the legacy \config/cms-toolkit.php\ with a comprehensive set of dedicated configuration files (e.g., \config/twill.php\, \config/media\_library.php\, \config/oauth.php\, \config/glide.php\). This change introduces new configuration options for features such as the Block Editor, Capsules, and OAuth providers, while removing the previous \config/laravel-env-validator.php\ and renaming \config/cms-toolkit-publish.php\ to \config/twill-publish.php\. Users must update their configuration to align with the new file structure and keys.
config · high confidence
Custom HTML and Markdown email templates with environment labels
The CMS now ships with custom email view templates for both HTML and Markdown formats. The HTML templates feature a redesigned layout that includes a new header component displaying a colored environment label (e.g., green for local/dev, blue for staging, red for production) to help users identify the source of notifications. The templates also utilize the Inter font family and include standard components for buttons, panels, and footers, ensuring consistent styling across system-generated emails.
views/emails · high confidence
Default database migrations refactored for configurability and compatibility
The default database migrations have been restructured to support configurable table names via application config (e.g., \twill.users\_table\, \twill.blocks\_table\) rather than hardcoding table names like \users\ or \medias\. This includes renaming the original migration files into the \migrations/default\ directory to prevent conflicts with existing codebases. The schema definitions have been updated to use \bigIncrements\ for primary keys and \text\ columns for UUIDs and filenames to improve compatibility with larger datasets and MySQL. Additionally, new migrations have been added to introduce \editor\_name\ to blocks, \language\ to users, \position\ to mediables and fileables, and \event\/\batch\_uuid\ to the activity log, while also fixing foreign key constraints on password resets and ensuring safe migration resets.
migrations/default · high confidence
Deprecation of custom Exception Handler and addition of specific exception classes
The custom \src/Exceptions/Handler\ class is now deprecated (triggering a deprecation notice) and will be removed in v4, encouraging users to extend Laravel's default \ExceptionHandler\ instead. Additionally, new specific exception classes have been introduced to improve error handling granularity: \MediaCropNotFoundException\ for missing media crops, \ModuleNotFoundException\, \NoCapsuleFoundException\, \NoNavigationForSubdomainException\, and \ColumnMissingPropertyException\ (renamed from a previous S3 upload listener interface).
src/Exceptions · high confidence
FileLibrary service refactored to use dependency injection and updated namespace
The FileLibrary service has been moved from the CmsToolkit package to the Twill core namespace (A17\\Twill\\Services\\FileLibrary). The Disk class no longer relies on the global Storage facade or the config() helper; instead, it now accepts FilesystemManager and Config repository instances via constructor injection, using the configuration key twill.file\_library.disk instead of cms-toolkit.file\_library.disk. Additionally, PHPDoc blocks with type hints have been added to the Disk, FileService, and FileServiceInterface classes to improve static analysis support.
src/Services/FileLibrary · high confidence
Form field partials rewritten as Vue components with Vuex store integration
The form field partials in views/partials/form have been completely rewritten to use new Vue components (such as a17-textfield, a17-browserfield, a17-blocks, and a17-wysiwyg-tiptap) instead of previous implementations. These partials now pass configuration via props and attributes to the Vue components and push initial field values into the global Vuex store (window.TWILL.STORE) to ensure state consistency. The update introduces support for new field options including direction, mask, maxlength, and prefix for text inputs; activeCrop and videoUrl toggles for media fields; and connectedBrowserField for browser fields. It also adds a new block editor partial that registers available blocks and editor names in the store, and standardizes how default values, disabled states, and required indicators are handled across all form fields.
views/partials/form · high confidence
Interactive linked cells with edit capability in listings
Listings now render linked cells as interactive anchor tags that support an inline edit mode. When the edit link feature is enabled, clicking the link triggers a modal edit interface, allowing users to modify the linked content directly from the table view without navigating away.
views/listings · medium confidence
Introduce new block rendering infrastructure and component support
The block service layer has been refactored to support a new component-based architecture alongside the existing Blade-based approach. A new \BladeCompiler\ class now handles the compilation and rendering of Blade strings, while the \Block\ class has been expanded to include properties for component classes, icons, and title prefixes, enabling blocks to be defined via PHP classes rather than just view files. The \BlockCollection\ now provides specific methods to retrieve blocks, settings, and repeaters, and includes logic to filter duplicates and prioritize app-defined blocks over vendor ones. Additionally, a \RenderData\ DTO has been introduced to manage the context and children of blocks during rendering, facilitating better handling of nested blocks and editor previews.
src/Services/Blocks · high confidence
Introduces object-oriented filter classes for listings
The listing filter system has been refactored from a procedural or array-based approach to a structured, object-oriented API. New classes including BasicFilter, BelongsToFilter, BooleanFilter, FieldSelectFilter, FreeTextSearch, and QuickFilter provide a fluent interface for defining filter logic, options, and query application. This change allows developers to configure filters with greater type safety and reusability, supporting features like automatic label generation, query string handling, and specific database query scopes (e.g., filtering by related models or boolean fields).
src/Services/Listings/Filters · high confidence
Major refactor of model behaviors to Twill namespace and architecture
This change restructures the core model behaviors by moving them from the legacy \A17\\CmsToolkit\ namespace to \A17\\Twill\\Models\\Behaviors\. It introduces new traits for modular capabilities: \HasBlocks\ for content block rendering, \HasNesting\ for hierarchical content with nested slugs, \HasOauth\ for social login linking, \HasPermissions\ for granular role-based access control, \HasRelated\ for browser field associations, \HasRevisions\ for version control, and \IsTranslatable\ for translation checks. Existing traits like \HasFiles\, \HasMedias\, \HasPresenter\, \HasSlug\, and \HasTranslation\ are updated to use the new namespace, configuration-driven table names, and improved logic (e.g., \HasMedias\ now supports custom metadatas and crop parameters). The \Sorts\ trait is renamed to \HasPosition\ for consistency.
src/Models/Behaviors · high confidence
Migrate route definitions to TwillRoutes facade
Route definitions for the tests-modules example have been consolidated into a dedicated \twill.php\ file, replacing previous macro-based approaches with the \TwillRoutes\ facade. This change explicitly registers the 'authors' module under the 'personnel' prefix and the 'categories' module, providing a standardized way to define module routes within the Twill ecosystem.
examples/tests-modules/routes · high confidence
Namespace migration and PHP 8.1+ constant visibility update for UserRole enum
The UserRole enum has been moved from the A17\\CmsToolkit namespace to A17\\Twill, reflecting a rebranding or structural consolidation of the toolkit into the main Twill package. Additionally, the enum constants (VIEWONLY, PUBLISHER, ADMIN) have been updated to use the explicit public const syntax, ensuring compatibility with modern PHP versions (8.1+) and aligning with current coding standards.
src/Models/Enums · high confidence
New SCSS state modules for UI interactions
Added new SCSS partials in the frontend state directory to manage specific UI states: a loader with fade-in animation for page loads, an environment bar that slides in on scroll, and styles to prevent body scrolling when modals or overlays are active. Additionally, mobile navigation styles were updated to handle the hamburger menu state at medium breakpoints and above.
frontend/scss/state · high confidence
New SCSS styles for login and dashboard search components
Added new SCSS files to the organisms directory to style the login interface and the dashboard search area. The login styles define the layout, input fields, buttons, and social login links, while the dashboard search styles set the background and minimum height for the search bar.
frontend/scss/organisms · high confidence
New SCSS utility classes for accessibility and layout
A new \\_utilities.scss\ file has been added to the frontend styles, introducing two utility classes. The \.visually-hidden\ class provides an accessible method to hide content visually while keeping it available for screen readers, and \.create-fieldset-margin\ applies a specific top margin to support the layout of fieldsets within the create modal.
frontend/scss/utilities · high confidence
New admin UI partials for layout, creation forms, and notifications
The admin interface now uses a set of new Blade partials to render core layout and interaction elements. The head partial enforces noindex/nofollow on CMS pages, configures the Inter font family, and manages CSS/JS preloading. The create partial introduces a customizable title input (supporting custom keys and labels) and an optional permalink field with prefix support. The footer partial displays a version number pulled from configuration and a 'Made with Twill' link. Finally, the toaster partial handles the display of validation errors, status messages, and restore notifications.
views/partials · high confidence
New atomic design styles for UI components
The frontend styling system now includes a new set of atomic SCSS modules in the \frontend/scss/atoms\ directory. These changes introduce dedicated styles for environment labels (\\_envlabel.scss\), external link indicators (\\_external.scss\), and responsive typography (\\_fonts-styles.scss\). Additionally, new styles are added for the mobile hamburger navigation (\\_ham.scss\), self-destructing notifications (\\_notif.scss\), tags (\\_tag.scss\), tooltips (\\_tooltip.scss\), and underlined text variants (\\_underlined.scss\). Utility classes for hiding elements at specific breakpoints (\\_hide.scss\) and general resets (\\_general-styles.scss\) are also included to support the new component structure.
frontend/scss/atoms · high confidence
New fluent field builder API for form fields
The form field definitions in src/Services/Forms/Fields have been refactored to use a new fluent builder pattern. Each field (such as Input, Select, Medias, and Wysiwyg) now extends a new BaseFormField class, which standardizes how field properties like name, label, and default values are set and how they render to view components. This change introduces new capabilities including connected fields support (allowing one field to conditionally show based on another), explicit configuration for the BlockEditor and Browser fields, and specific options like clearable selects, searchable multi-selects, and 24-hour time formats for date pickers.
src/Services/Forms/Fields · high confidence
New frontend SCSS design system foundation
The frontend styling foundation has been restructured into a modular SCSS setup under \frontend/scss/setup\. This introduces a comprehensive color palette with semantic variables for UI states (buttons, forms, tags, notifications), a responsive grid system with configurable breakpoints and gutters, and a unified typography setup using the Inter font family with \font-display: swap\ for improved loading performance. Additionally, a design-grid overlay tool is now available for visual layout debugging, and global resets and mixins are standardized to support consistent component styling across the application.
frontend/scss/setup · high confidence
New frontend behavior modules for navigation, logout, media library, and environment indicators
This change introduces four new JavaScript behavior modules in the frontend to handle specific UI interactions. The logout button now uses a POST request via a hidden form for security, replacing previous methods. A new mobile navigation toggle manages the opening and closing of the menu with scroll-position awareness. Users can now open the media library directly from the header in free mode via a dedicated button. Additionally, a colored environment indicator line is shown or hidden based on scroll position to provide visual context. These behaviors are implemented as reusable, exported functions that attach event listeners to specific DOM elements.
frontend/js/behaviors · high confidence
New layout system with column utilities and form styling
The layout styling has been restructured into modular SCSS files, introducing a new grid system with specific column span configurations for primary, aside, and even layouts across breakpoints. New utility classes like .col--double and .col--third allow for flexible two- and three-column arrangements in forms and dashboards, while dedicated styles for .field-rows enable 2-column and 3-column layouts for form inputs and selectors. Additionally, new styles define the appearance of the main application container, error pages, and custom admin pages, ensuring consistent spacing and background colors across different view types.
frontend/scss/layout · high confidence
New navigation structure with breadcrumbs, secondary/tertiary links, and mobile overlay
The admin interface now features a multi-level navigation system. A new breadcrumb trail is displayed above content, while secondary and tertiary navigation bars support request-specific links injected by controllers. The mobile experience uses an overlay menu that includes user profile and logout options, with the user dropdown menu conditionally hidden if user management is disabled. The header title now displays a shorthand environment label (e.g., 'prod') for production sites.
views/partials/navigation · high confidence
New specialized table cell components for listings
The table listing UI now uses dedicated Vue components for specific column types, replacing the previous monolithic implementation. This change introduces specialized cells for actions (dropdown menu with edit, publish, feature, duplicate, delete, and destroy options), bulk selection checkboxes, publication dates (with expired/scheduled status logic), draggable row handles, featured status toggles, language tags (showing the first 4 with a 'more' link), nested list indentation, publish state indicators, and thumbnails (supporting rounded avatars). These components are registered in the table cell index and rely on a shared mixin for common row data and event handling.
frontend/js/components/table/tableCell · high confidence
New table column configuration and model browser data formatting
This change introduces the \TableColumn\ class, allowing columns to be configured with specific properties such as \shrink\, \sortKey\, and \linkToEdit\, alongside a new \TableColumns\ collection that formats model data for the CMS. Specifically, the model browser now retrieves the \adminEditUrl\ and \titleInBrowser\ accessors from models to populate edit links and display names, ensuring the browser UI correctly reflects these model-level attributes.
src/Services/Listings · high confidence
Portfolio example updated to use modern Twill APIs and Blade components
The portfolio example has been refactored to align with current Twill best practices. Controllers now extend the base ModuleController and use the TwillRoutes facade for registration instead of route macros. Repository logic has been updated to use the new HandleRepeater behaviors (updateRepeaterMorphMany, updateRepeaterWithPivot) and form field getters, replacing older manual morph handling. Additionally, admin form views have been migrated from the legacy @formField directive to modern Blade components (e.g., \<x-twill::input\>), and database migrations now utilize anonymous class syntax.
examples/portfolio · high confidence
Quill editor configuration and customization
The Quill editor library has been reconfigured to support new formatting options and improved link handling. Users can now insert horizontal dividers (hr) and use Shift+Enter for soft line breaks within the editor. Link behavior has been updated so that relative URLs and those starting with the application's base URL no longer open in a new tab, while external links continue to open in a new tab by default. Additionally, the editor now supports custom anchor formatting and uses custom SVG icons for toolbar buttons.
frontend/js/libs/Quill · high confidence
Redesign password reset and choose-password forms to use Twill's auth layout
The password reset (email.blade.php) and choose-password (reset.blade.php) views have been rewritten to extend the standard Twill authentication layout instead of using a standalone HTML structure. This change updates the UI to match the rest of the Twill admin interface, applies consistent styling classes (e.g., login\_\fieldset, login\\_input), and ensures the form submission routes respect the configured admin route name prefix. Additionally, the choose-password form now automatically pre-fills the user's email address and dynamically sets the screen title and submit button text based on whether the user is resetting a forgotten password or setting a password for the first time (welcome flow).
views/auth/passwords · high confidence
Redesigned block editor with drag-and-drop, cloning, and new default block types
The block editing interface has been overhauled to support drag-and-drop reordering, block duplication (cloning), and inline expansion/collapse. The new \Blocks.vue\ component integrates \vuedraggable\ for visual reordering and provides action menus for cloning, deleting, and opening blocks in a dedicated editor. Several default block types are now available out-of-the-box, including Image, Table, Title, and Wysiwyg, all utilizing a shared \BlockMixin\. The underlying data management has been refactored into \BlockEditorModel\ and \BlocksList\ components, which handle state mutations for adding, moving, and removing blocks via Vuex, while \BlockEditorItem\ manages the individual block UI and title sanitization.
frontend/js/components/blocks · high confidence
Redesigned user and group management forms with new UI components
The user management interface has been completely rewritten to use the modern Twill component system (e.g., \x-twill::input\, \x-twill::browser\) instead of the legacy form helpers. This update introduces several new capabilities: users can now select their preferred language from available locales, and administrators can manage two-factor authentication settings, including the ability to force-disable 2FA for stuck users. Additionally, a new 'Groups' feature allows admins to assign users to groups and configure granular content permissions per module. The user listing view has been removed in favor of the standard resource index layout, and user profile images are now disabled by default.
views/users · high confidence
Refactor frontend controllers to use explicit service injection and update namespace
The frontend controller layer has been refactored to replace global helper functions (such as \config()\, \app()\, \Str::endsWith()\) with explicit dependency injection of their corresponding service classes (e.g., \Illuminate\\Config\\Repository\, \Illuminate\\Foundation\\Application\, \Illuminate\\Support\\Str\). This change is applied across the new \GlideController\ and \ShowWithPreview\ trait, as well as the base \Controller\ class, which also updates its namespace from \A17\\CmsToolkit\ to \A17\\Twill\ and uses the injected \Config\ repository for SEO settings. Users benefit from more testable and decoupled controller logic, while the \ShowWithPreview\ trait now explicitly handles preview routing and view rendering through injected services.
src/Http/Controllers/Front · high confidence
Refactor view composers to support multi-cloud storage and modernize Laravel dependencies
The view composers in the Http layer have been restructured to support Azure and S3 storage backends for both file and media libraries, in addition to local storage. New composers (FilesUploaderConfig, MediasUploaderConfig, Localization) inject configuration and session data to expose storage endpoints, access keys, and localization strings to the frontend, while the existing CurrentUser composer now uses the AuthFactory instead of the auth() helper. The old ActiveNavigation composer was removed, and namespaces were updated from CmsToolkit to Twill.
src/Http/ViewComposers · high confidence
Refactored Vue directives for tooltips, SVGs, and sticky positioning
The frontend directive system has been updated to improve stability and consistency. The tooltip directive now explicitly disposes and recreates the tooltip instance on component updates, preventing issues with duplicated or stale tooltips. The SVG directive has been rewritten to handle element creation and removal via utility functions during updates. Additionally, a new sticky directive has been introduced to manage sticky positioning behavior for elements.
frontend/js/directives · high confidence
Refactored block rendering, capsule loading, and migration helpers
The \src/Helpers\ area has been significantly restructured to support new architectural capabilities. A new \BlockRenderer\ class now handles the rendering of nested block components, replacing previous inline logic. The \Capsule\ helper class has been introduced to manage the bootstrapping of isolated modules (capsules), including their service providers, views, migrations, and routes. Migration helpers (\migrations\_helpers.php\) have been updated to use \bigIncrements\ by default and now include new functions for creating relationship and revision tables. Additionally, frontend asset helpers (\frontend\_helpers.php\) have been refactored to support configurable asset paths and capsule-specific view names, while the \FlashNotifier\ class was removed and \FlashLevel\ constants were updated.
src/Helpers · high confidence
Refactored form request validation and added Azure storage support
The form request classes in src/Http/Requests/Admin have been migrated from the CmsToolkit namespace to Twill and refactored to support separate validation rules for create and update operations via new rulesForCreate and rulesForUpdate methods. Validation for translated fields now uses dot-notation keys (e.g., field.locale) instead of underscores, and correctly handles locale activation status by removing required constraints when a locale is inactive. File and media upload requests now explicitly support Azure Blob storage in addition to local and S3 endpoints, requiring a 'blob' field for Azure uploads. User validation has been enhanced to include password strength checks, two-factor authentication (2FA) verification for enabling/disabling 2FA, and privilege checks for super admins forcing 2FA disable on other users.
src/Http/Requests · high confidence
Refactored media library logic into reusable mixins
The media library functionality has been restructured by extracting common logic into two new mixins: \mediaItems\ and \mediaLibrary\. The \mediaItems\ mixin centralizes item selection, usage tracking, and replacement state management, while the \mediaLibrary\ mixin standardizes how the media connector is opened and configured via Vuex store mutations. This change improves code maintainability and ensures consistent behavior across components that interact with the media library.
frontend/js/mixins/mediaLibrary · high confidence
Refactored modal creation and validation components
The modal creation workflow has been refactored to improve reliability and user experience. A new ModalAdd component handles simple additions, while ModalCreate now manages both creation and updates with proper state management for publication toggles and form fields. The ModalValidationButtons component has been rewritten to dynamically enable/disable submit buttons based on required field validation, preventing accidental submissions. Additionally, a retrySubmitMixin has been introduced to prevent multiple simultaneous submit events, fixing issues where users could accidentally trigger duplicate submissions, particularly in Safari and Firefox.
frontend/js/components/modals · high confidence
Removal of custom paginator presenter and button renderer trait
The custom \PaginatorPresenter\ and its associated \PaginatorNextPreviousButtonRendererTrait\ have been removed from the admin presenters. This eliminates the application's custom implementation for rendering pagination links (including previous/next buttons and page wrappers) that previously extended Laravel's \BootstrapThreePresenter\, effectively reverting pagination rendering to the framework's default behavior or a different mechanism not present in this scope.
src/Presenters · high confidence
Removal of legacy A17 CMS stylesheet
The \assets/a17cms.css\ file, which contained the global styles for the A17 CMS (version 1.7.8), has been deleted. This removes the legacy CSS rules for the CMS interface, including the datetime picker, color swatches, and markItUp editor, from the application assets.
assets · high confidence
Removal of legacy Blade view templates for CMS resource listings
The legacy Blade view files for CMS resource management have been removed from the codebase. This includes the main layout templates for index listings (index.blade.php), forms (form.blade.php), and media browsers (browser.blade.php), as well as the partials used to render table columns, action buttons (edit, delete, publish, sort), and pagination. Users relying on these specific view paths for customizing the CMS interface will need to update their overrides to use the new view structure.
views/layouts/resources · high confidence
Removal of legacy form field partials
The legacy Blade view partials for form fields (including \_block\_editor, \_date\_picker, \_files, \_input, \_medias, \_publish\_status, \_rich\_textarea, \_select, \_slug\_input, \_textarea, and language/locale variants) have been removed from the views/layouts/form\_partials directory. This cleanup eliminates the old SirTrevor-based block editor implementation and the previous multi-locale input rendering logic, indicating a migration to a new form rendering system or Vue-based components.
_views/layouts/form\partials · high confidence
Repository layer migrated from CmsToolkit to Twill with new settings and block handling
The repository classes in src/Repositories have been moved from the A17\\CmsToolkit namespace to A17\\Twill, reflecting a broader platform rebranding. New repositories have been introduced for AppSettings, Blocks, Groups, Roles, and Settings, providing dedicated data access for these core CMS entities. The existing File and Media repositories now use the Twill namespace and configuration keys (e.g., twill.file\_library instead of cms-toolkit.file\_library), and the Media repository adds a configuration option to disable automatic alt-text generation from filenames. The ModuleRepository has been significantly expanded with new behaviors (browsers, repeaters, permissions, fields groups) and methods (firstOrCreate, cmsSearch, getCountByStatusSlug), while the UserRepository now integrates OAuth, 2FA management, and permission-based filtering.
src/Repositories · high confidence
Restored fonts directory placeholder
The frontend/fonts directory has been restored by adding a .keep file, ensuring the folder persists in the repository structure.
frontend/fonts · high confidence
Rewritten module generator stubs and simplified route registration
The module generator stubs have been completely rewritten to align with the new Twill architecture, replacing the legacy CmsToolkit-based templates with modern equivalents. Controllers now extend a configurable base class and utilize the new TableColumns and Form services instead of legacy blade-based layouts. Route registration has been simplified to use the \TwillRoutes\ facade, and migrations now leverage anonymous classes. Additionally, the generator now supports optional features such as module nesting, revisions, and slugs, and automatically configures translated attributes for models.
src/Commands/Stubs · high confidence
Route definitions are now feature-gated and restructured
The admin and auth route files have been refactored to wrap specific capabilities in feature flags (e.g., \twill.enabled.media-library\, \twill.enabled.buckets\, \twill.enabled.users-2fa\). This means routes for media/file libraries, buckets, two-factor authentication, and OAuth login are only registered when their respective features are enabled in the configuration. Additionally, the media and file library routes now support Azure storage signing alongside S3, and the user management routes are conditionally loaded based on the \users-management\ and \permissions-management\ flags.
routes · high confidence
SEO helper now preserves default values when setters receive empty input
The Seo helper class in the front-end controllers now includes setter methods for title and description that only update the property if a non-empty value is provided. This change ensures that existing default values are retained when these setters are called with empty strings, preventing accidental overwrites of SEO metadata.
src/Http/Controllers/Front/Helpers · high confidence
Standardized development tooling and configuration files
The project now includes explicit configuration files for its build and code quality toolchain, replacing implicit or missing setups. This introduces ESLint and Prettier for JavaScript/Vue formatting, PHP-CS-Fixer and PHP\_CodeSniffer for PHP standards, and Babel for transpilation. It also adds a PHPUnit 11 configuration, PHPStan static analysis setup, and Rector scripts to automate code upgrades and namespace migrations (e.g., Admin to Twill). Additionally, a Code of Conduct, Security policy, and Upgrade guide are provided to standardize community interaction and migration paths.
(repo-wide) · high confidence
Standardized error page views and layout inheritance
The error page views in the \views/errors\ directory have been updated to inherit from the \twill::layouts.errors\ layout instead of the previous \cms-toolkit::layouts.errors\ layout. Several new error pages have been added for HTTP 403 (Forbidden), 419 (Page Expired), and 429 (Too Many Requests) statuses, providing specific user-facing messages for these conditions. Existing error pages (401, 404, 500, 503) have been refactored to use consistent paragraph-based content structures and include links back to the homepage where appropriate. Additionally, new views have been introduced to handle developer-facing errors for missing block previews, block layouts, and module previews, offering clear instructions on how to resolve these issues in development environments.
views/errors · high confidence
Styled and interactive HTML table cells
A new component for rendering raw HTML content within table cells now applies consistent link styling (using the defined link color) and ensures links appear as clickable pointers without underlines. Additionally, any links within the cell content that carry the data-edit attribute are now handled to prevent in-place editing when clicked.
frontend/js/components/table/tableCell/generic · high confidence
Support for fieldsets and block-specific form rendering
The form rendering pipeline now supports grouping fields into fieldsets and handling block-specific forms. In the base form view, content fields are optionally wrapped in a fieldset, and additional fieldsets defined in $renderFieldsets are rendered with configurable open states and margins in create mode. A new block\_form view ensures fields are correctly flagged for block rendering when applicable, allowing mixed fieldset and block content to be displayed correctly in forms.
views/partials/form/renderer · high confidence
Support for multi-subdomain admin routing in Twill
The example application now supports managing content across multiple subdomains (e.g., 'subdomain1' and 'subdomain2') within a single Twill installation. This is enabled by setting \support\_subdomain\_admin\_routing\ to true in the Twill configuration and defining distinct navigation menus and app names for each subdomain. The routing layer has been updated to use the \TwillRoutes\ facade instead of route macros, allowing the 'pages' module to be accessible and configured independently per subdomain.
examples/tests-subdomain-routing · high confidence
Updated compiled frontend assets for release 3.5.3
This release updates the compiled CSS assets in the \twill-assets\ directory, including the new \chunk-common.eea3635b.css\ file. The changes reflect the latest frontend build, incorporating styles for the design grid toggle, navigation, form fields, and various UI components, consistent with the version bump to 3.5.3.
twill-assets/assets · high confidence
Updated database migrations to use anonymous classes
The database migration files in the tests-modules example have been refactored to use PHP anonymous classes (e.g., \return new class extends Migration\) instead of named classes. This change modernizes the migration syntax while preserving the existing schema definitions for categories, authors, and revision-limited contents.
examples/tests-modules/database · high confidence
Updated example capsules to use modern Twill conventions
The example application's Posts and Homepages capsules have been rewritten to align with current Twill best practices. The Homepage singleton now uses the \TwillRoutes\ facade for routing, disables permalinks, and defines its form fields and table columns programmatically via the controller instead of relying on Blade templates. The Posts module has been updated to use anonymous class syntax for its database migrations and includes a dedicated capsule service provider. These changes ensure the example code reflects the latest architectural patterns for module and singleton configuration.
examples/tests-capsules · high confidence
User model refactored for role-based permissions and two-factor authentication
The User model has been significantly updated to support role-based access control and enhanced security features. It now includes behaviors for OAuth login, two-factor authentication (Google 2FA), and translatable attributes, while switching from a string-based role field to a \role\_id\ foreign key when permissions management is enabled. The model introduces new scopes (\accessible\, \activated\, \pending\, \draft\, \onlyTrashed\) to filter users based on their status and permissions, and adds casts for boolean and datetime fields to ensure correct data handling. Additionally, the model now implements \TwillModelContract\ and uses a configurable table name, improving extensibility and integration with the CMS.
src/Models · high confidence
Vendor style overrides for image cropping, date picking, and selection components
This change introduces dedicated SCSS files in the vendor folder to customize the appearance and behavior of third-party UI libraries. For the image cropper, hit areas for cropping points are increased to improve touch usability. The flatpickr date picker is styled to match the application's design system, including specific height and font adjustments. Vue-select components receive extensive styling updates, such as expanding dropdown menus to fit content, adjusting spinner and clear button positions, and refining single-select and multi-select layouts.
frontend/scss/vendor · high confidence
Fixes
Added placeholder to preserve customs blocks directory
A .keep file was added to the frontend/js/components/blocks/customs directory to ensure the folder persists in the repository and build process, preventing missing folder errors during CI builds.
frontend/js/components/blocks/customs · high confidence
Test coverage
Added TestPresenter for testing model presentation; Added browser tests for Twill's block editor, media handling, and date/time features; Added integration test helper traits for file and block operations; Added integration tests for Capsule system; Added integration tests for Twill Artisan commands; Added integration tests for block browser clearing and nested block sorting; Added integration tests for controller index option setters; Added integration tests for core Twill features; Added integration tests for exception handling; Added integration tests for media/file deletion and module repository slugs; Added integration tests for navigation and settings visibility; Added integration tests for repository duplication, repeaters, and tag slugs; Added integration tests for revisions and draft revisions; Added integration tests for table filters and search functionality; Added integration tests for the Admin Dashboard activity feed; Added integration tests for the AnonymousModule testing utility; Added integration tests for the Cartalyst Tags package; Added integration tests for the Settings system; Added integration tests for translated model queries; Added integration tests for user management and email functionality; Added unit tests for MediaLibrary parameter processors; Added unit tests for form field components; Added unit tests for form services and translation utilities; Added unit tests for helper and model functions; Added unit tests for validation rules; Initial PHPUnit test infrastructure and helpers; Integration tests added for table listing columns and sorting.
Dependencies
Twill 3.6.0 release with updated dependencies and new build tooling
This release updates the core frontend dependencies, including Alpine.js to 3.15.11, TipTap to 2.2.1, and Vue to 2.7.16, while also introducing a new Vite-based build configuration for the basic page builder example. The package metadata has been updated to version 3.6.0, and the documentation API now uses Doctum 5.4 for generating API docs.
(dependencies) · high confidence
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
How this codebase got here
Baseline
- First survey — no prior run to compare against. CAI 46.
Lenses
- Code Health 62
- Architecture 59
- Maturity 62
- Readiness 50
- Security 66
- Accessibility 36
Changes since last survey
- 300 commits — 209 feature/other, 91 fixes
By area
- (root) — 69 commits
- .github/workflows — 34 commits
- frontend/js — 25 commits
- docs/content — 22 commits
- src/Repositories — 17 commits
- src/Http — 16 commits
- src/Services — 16 commits
- tests/Browser — 13 commits
- src/Models — 11 commits
- tests/integration — 11 commits
- twill-assets/assets — 11 commits
- src/Commands — 9 commits
- src/Helpers — 7 commits
- (repo) — 3 commits
- frontend/scss — 3 commits
- migrations/default — 3 commits
- src/DuskServiceProvider.php — 3 commits
- tests/unit — 3 commits
- config/twill.php — 2 commits
- src/TwillBlocks.php — 2 commits
Notable commits
- fix: Add @mixin to facades to fix phpstan issue
- fix: Add empty customs folder for blocks to fix build in CI
- fix: CS fix
- fix: Disable heading extension if it's not in the toolbar Fix #2489
- fix: Fix #2674
- fix: Fix BlockRepository setting relation of an object and improve amount of queries during saves
- fix: Fix CI release messages
- fix: Fix GitHub Actions upload artefact v4 usage
- fix: Fix GitHub Actions upload artefact v4 usage
- fix: Fix GitHub Actions upload artefact v4 usage
- fix: Fix L9 tests due to Dusk 7 not supporting Chrome > 126
- fix: Fix L9 tests due to Dusk 7 not supporting Chrome > 126
- fix: Fix L9 tests due to Dusk 7 not supporting Chrome > 126
- fix: Fix L9 tests due to Dusk 7 not supporting Chrome > 126
- fix: Fix alt text stripping accents and single quotes (#2514)
- fix: Fix avoid recursive reference in relation
- fix: Fix build in release workflow
- fix: Fix created at is null in slug table (#2588)
- fix: Fix dbal 4 conflict (#2596)
- fix: Fix deleted users causes error 500
- …and 280 more
Architecture
- 0 containers · 1 bounded contexts · 0 dependency edges (baseline)
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
Survey your own repository
area17/twill was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.
About this page
- The score is its most recent published measurement, taken on 19 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
- Measured at commit d763dee5b60109ee38f83806e478e9c4a2ac36d5 — the exact code this score is about.
- Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
- Measured by watchdog.canine.dev using codehealth-analyzer preprod-13a154b7f5d1.