Advanced — Overview
This section covers the extension layer of the Tagixo builder: how to add new capabilities beyond what the built-in catalog provides, how those capabilities are packaged and distributed, and what contracts the framework guarantees across releases.
1. Extension Points
Tagixo exposes four primary surfaces you can extend.
Props
A Prop is a single typed value stored in a module's payload (e.g. a colour hex, a string, a boolean). Props do not render anything on their own — they are the atomic unit of data that PropTypes and Modules consume.
Base class: Ccast\Tagixo\Props\AbstractProp
Role: declare a keyed value, its default, and its PHP-side coercion.
PropTypes
A PropType bundles one or more Props into a reusable design control. It owns the drawer UI (Vue component), the CSS generation logic, and any server-side rendering helpers (e.g. font link generation). Examples from the core catalog: ColorPropType, TypographyPropType, BorderPropType.
Base class: Ccast\Tagixo\PropTypes\AbstractPropType
Role: turn structured payload data into CSS rules and editor UI.
Modules
A Module is a renderable content block — the primary building block users drag onto the canvas. It declares its Props/PropTypes, provides a Blade template for the frontend, and optionally a Vue component for the builder canvas preview.
Base class: Ccast\Tagixo\Modules\AbstractModule
Role: define structure, defaults, and both rendering paths (frontend Blade + builder Vue).
Form Fields and Form Wrappers
Form Fields extend the form builder's input palette (text, select, file upload, etc.). Form Wrappers group fields into structural containers inside a form.
Base classes: Ccast\Tagixo\Forms\Fields\AbstractFormField, Ccast\Tagixo\Forms\Wrappers\AbstractFormWrapper
Role: add new input types or layout containers to the drag-and-drop form builder.
2. When to Extend
Consider writing a custom extension when:
- Catalog gap — the built-in module or field catalog does not cover a UI pattern your project requires (e.g. a pricing table, a multi-step wizard, a signature pad).
- Custom design control — you need a site-specific design token (e.g. a brand-specific border style or a proprietary animation control) that does not map cleanly to an existing PropType.
- Redistributable plugin — you are building a Composer package that ships new modules, PropTypes, or form fields to multiple Tagixo-powered sites.
For one-off content needs, prefer authoring inside the builder (custom CSS field, Global Variables, or a seeded layout). Reach for the extension layer only when you need reusable, type-safe, programmatically configurable behaviour.
3. Extension Hierarchy
Extensions are layered. Each layer builds on the one below.
Props
└── PropTypes (compose one or more Props; own CSS generation + editor UI)
└── Modules (declare PropTypes; own Blade template + canvas preview)
Props layer — responsible for: key naming, PHP-side type coercion, scalar default values. No CSS, no rendering.
PropTypes layer — responsible for: grouping related Props into a logical control, generating CSS from prop values (toCss(), toInlineCss()), providing the Vue drawer component name, and any server-side rendering helpers. A PropType must not assume any particular module context — it is reusable across modules.
Modules layer — responsible for: declaring which PropTypes (and plain Props) appear in the Design/Content/Advanced tabs, providing the Blade render() method, registering the Vue component used in the builder canvas, and optionally defining sub-elements and repeaters. A module must not duplicate CSS logic that belongs in a PropType.
Form Fields and Form Wrappers sit alongside this hierarchy rather than inside it — they extend the form builder subsystem and do not interact with the module rendering pipeline.
4. Artisan Scaffold Commands
Tagixo ships scaffold generators so you do not have to write boilerplate by hand.
| Command | What it generates |
|---|---|
artisan tagixo:make-module {Name} |
Module class, Blade template, Vue canvas component stub |
artisan tagixo:make-proptype {Name} |
PropType class with toCss() stub and Vue drawer component stub |
artisan tagixo:make-prop {Name} |
Bare Prop class |
artisan tagixo:make-form-field {Name} |
Form Field class with render stub |
artisan tagixo:make-form-wrapper {Name} |
Form Wrapper class |
Output path and namespace
By default scaffolds land in app/Tagixo/ with the namespace App\Tagixo\. Override globally in config/tagixo.php:
'scaffolding' => [
'path' => app_path('Tagixo'),
'namespace' => 'App\\Tagixo',
],
Pass --path and --namespace on any individual command to override for that one invocation.
Plugin (package) mode
When building a redistributable plugin, pass --package=vendor/package-name. The generator resolves the path from your Composer path-repository and uses the package's declared namespace:
artisan tagixo:make-module HeroSection --package=acme/tagixo-hero
5. Stability Guarantees
The following contracts are stable across minor releases (i.e. a 1.x → 1.y upgrade will not break them). They may change across major releases with a deprecation notice in the changelog.
- JSON storage format — the shape of
tgx_pages.contentandtgx_layouts.content. Prop keys you register today will be read correctly by future versions of the renderer. - Rendering pipeline variables — the PHP variables injected into module Blade templates (
$module,$props,$styles,$attrs). Adding new variables is backwards-compatible; removing or renaming one is a major-version change. - PropType CSS method signatures —
toCss(array $props, string $selector): stringandtoInlineCss(array $props): string. Argument order and return type are frozen. - Module interface methods —
render(),defaultProps(),propTypes(),label(),icon(),category(). Adding optional methods with defaults is backwards-compatible.
Type-ID stability warning — A module's or PropType's type identifier (the string returned by typeId()) is stored verbatim in the database. Renaming typeId() on an existing extension will orphan all pages that contain that module. If you must rename, provide a legacyTypeIds(): array method listing the old identifiers so the renderer can migrate them transparently.
6. Composer Plugin Packaging
To ship Tagixo extensions as a reusable Composer package:
Directory layout
src/
Modules/
PropTypes/
Props/
Forms/
resources/
views/modules/
js/
MyPluginServiceProvider.php
MyPlugin.php ← extends TagixoPluginBase
composer.json
Plugin class
Extend Ccast\Tagixo\Plugins\TagixoPluginBase and declare your extensions:
class MyPlugin extends TagixoPluginBase
{
public function modules(): array
{
return [HeroModule::class, PricingTableModule::class];
}
public function propTypes(): array
{
return [GradientPropType::class];
}
}
Service provider wiring
Register the plugin inside your ServiceProvider::boot():
Tagixo::registerPlugin(new MyPlugin());
Panel integration (Primix)
If your package also ships Primix resources (admin pages, settings screens), implement HasPlugin on your plugin class and register it with the Primix panel provider:
PrimixPanel::registerPlugin(new MyPlugin());
Frontend assets
Publish Vue components and compiled JS via the standard Laravel asset publishing tag. Declare the tag in your service provider:
$this->publishes([
__DIR__.'/../dist/' => public_path('vendor/my-plugin'),
], 'my-plugin-assets');
The Tagixo builder will auto-discover published Vue components if the component name matches the string returned by Module::vueComponent().
SemVer rule for breaking changes
- Renaming a type ID, changing a CSS method signature, or removing a public module method — major version bump.
- Adding new modules, PropTypes, or optional methods — minor version bump.
- Bug fixes with no API surface change — patch version bump.
7. Recommended Reading Order
If you are new to Tagixo extension development, work through the topics in this order:
- Props — understand the atomic data unit before anything else.
- PropTypes — learn how Props are grouped into design controls and how CSS is generated.
- Sub-elements — understand how modules expose nested styleable regions before you write your first module.
- Modules — build your first renderable block, combining what you learned above.
- Custom Form Modules — if you need form builder extensions, read this after Modules (the concepts mirror each other).
- Custom Props — only if you need a prop type with coercion logic the core does not provide.
- Custom PropTypes — extend the design control layer once you are comfortable with the rendering pipeline.
- Plugin packaging — wrap everything into a redistributable Composer package.
If you are jumping straight to packaging an existing set of extensions, read step 8 first, then circle back to whichever of steps 1-7 cover the extension types your package contains.