Reference

Developer Architecture

6 min read

Internal architecture reference for TallCMS core developers.

TallCMS Developer Architecture Guide


Overview

TallCMS v2.0 uses a monorepo architecture where the package (tallcms/cms) lives inside the standalone application (tallcms/tallcms).

Two Distribution Modes

AspectStandalone ModePlugin Mode
Packagetallcms/tallcmstallcms/cms
Installationcomposer create-projectcomposer require
Target UserNew projectsExisting Filament apps
FeaturesFull CMS + themes + pluginsCMS core
Marker File.tallcms-standalone presentNo marker file

Monorepo Structure

tallcms/tallcms (Standalone Application)
├── app/                          # Standalone-specific code
│   ├── Models/                   # Wrapper classes
│   ├── Http/Controllers/         # Wrapper controllers
│   ├── Filament/                 # Wrapper resources
│   └── Providers/                # App-specific providers
├── config/
│   └── tallcms.php               # App-level overrides
├── routes/
│   └── web.php                   # Standalone routes
├── resources/views/              # Standalone views
├── themes/                       # Installed themes
├── plugins/                      # Installed plugins
├── .tallcms-standalone           # MODE MARKER FILE
│
└── packages/tallcms/cms/         # THE PACKAGE (Source of Truth)
    ├── src/
    │   ├── Models/               # Base models
    │   ├── Services/             # Core logic
    │   ├── Filament/             # Resources, Blocks
    │   ├── Http/Controllers/     # Base controllers
    │   └── TallCmsServiceProvider.php
    ├── config/
    │   └── tallcms.php           # MASTER CONFIG
    ├── database/migrations/      # ALL migrations
    ├── resources/views/          # Package views
    └── routes/
        └── frontend.php          # Frontend routes

Single Source of Truth Principle

The package is the single source of truth for:

ComponentLocation
Modelspackages/.../src/Models/
Servicespackages/.../src/Services/
Filament Blockspackages/.../src/Filament/Blocks/
Filament Resourcespackages/.../src/Filament/Resources/
Migrationspackages/.../database/migrations/
Configpackages/.../config/tallcms.php
Package Viewspackages/.../resources/views/

Standalone Provides

  1. Wrapper Classes - Thin extensions for compatibility
  2. Standalone Features - Themes, plugins, updates
  3. Config Overrides - Minimal environment-specific changes
  4. Additional Views - Welcome page, theme layouts

Mode Detection

// In TallCmsServiceProvider
protected function detectMode(): string
{
    if (file_exists(base_path('.tallcms-standalone'))) {
        return 'standalone';
    }
    return 'plugin';
}

Helper Function

tallcms_mode(): string  // 'standalone' or 'plugin'
tallcms_is_standalone(): bool
tallcms_is_plugin(): bool

Class Alias System

Standalone wrappers extend package classes:

// app/Models/CmsPage.php (Standalone)
namespace App\Models;

use TallCms\Cms\Models\CmsPage as BaseCmsPage;

class CmsPage extends BaseCmsPage
{
    // Standalone-specific additions
}

The service provider registers aliases:

$this->app->alias(
    \App\Models\CmsPage::class,
    \TallCms\Cms\Models\CmsPage::class
);

Extension Pattern

Adding Standalone Features

// In standalone service provider
if (tallcms_is_standalone()) {
    $this->registerThemeManager();
    $this->registerPluginManager();
    $this->registerUpdateService();
}

Conditional Routes

// routes/web.php (Standalone)
if (tallcms_is_standalone()) {
    Route::get('/themes', ThemeController::class);
}

Configuration Management

Package Config (Master)

packages/tallcms/cms/config/tallcms.php:

return [
    'mode' => env('TALLCMS_MODE'),  // null = auto-detect
    'version' => '2.5.0',

    'plugin_mode' => [
        'routes_enabled' => env('TALLCMS_ROUTES_ENABLED', false),
        'routes_prefix' => env('TALLCMS_ROUTES_PREFIX', ''),
    ],

    // Comprehensive defaults...
];

App Config (Overrides)

config/tallcms.php (Standalone):

return [
    // Only override what's different
    'mode' => 'standalone',
];

View Architecture

View Namespaces

NamespacePathPriority
(none)resources/views/1 (highest)
tallcmspackages/.../views/2
themethemes/{slug}/views/0 (with theme)

Resolution Order

  1. Active theme views
  2. Application views
  3. Package views (fallback)
// Always falls back correctly
return view('tallcms::cms.blocks.hero');

Route Architecture

Package Routes

// TallCmsServiceProvider
$this->loadRoutesFrom(__DIR__.'/../routes/frontend.php');

Route Groups

GroupMiddlewarePrefix
Frontendweb(configurable)
Adminweb, auth/admin
APIapi/api/tallcms

Plugin Mode Routes

if (config('tallcms.plugin_mode.routes_enabled')) {
    Route::middleware('web')
        ->prefix(config('tallcms.plugin_mode.routes_prefix'))
        ->group(function () {
            // CMS routes
        });
}

Development Workflow

Working on Package

cd packages/tallcms/cms
# Make changes
# Test immediately in standalone app

Testing Both Modes

# Standalone mode
php artisan test

# Plugin mode simulation
rm .tallcms-standalone
php artisan test
touch .tallcms-standalone

Testing Strategy

Package Tests

cd packages/tallcms/cms
./vendor/bin/phpunit

Test Isolation

// Base test case ensures clean state
protected function setUp(): void
{
    parent::setUp();
    config(['tallcms.mode' => null]);  // Auto-detect
}

Release Process

  1. Update version in packages/tallcms/cms/config/tallcms.php
  2. Update version in packages/tallcms/cms/composer.json
  3. Tag monorepo
  4. GitHub Action splits to tallcms/cms
  5. Packagist picks up new tag

Common Pitfalls

DO NOT

  • Duplicate code between standalone and package
  • Put business logic in standalone app/
  • Reference standalone classes from package
  • Hard-code paths without mode awareness

DO

  • Extend package classes in standalone
  • Use config for mode-specific behavior
  • Keep package self-contained
  • Test both modes

Key Files Reference

PurposePackage LocationStandalone Override
Service Providersrc/TallCmsServiceProvider.phpapp/Providers/TallCmsProvider.php
Configconfig/tallcms.phpconfig/tallcms.php
Routesroutes/frontend.phproutes/web.php
Base Modelssrc/Models/app/Models/
Viewsresources/views/resources/views/

Next Steps

Choose Theme