Theme Structure

Understanding theme directory structure is essential for effective customization.

Directory Layout

themes/
└── my-theme/
    ├── template.json              # Required: Theme metadata
    ├── bundles/
    │   ├── EasyAdminBundle/      # Global EasyAdmin template overrides
    │   │   ├── layout.html.twig
    │   │   ├── crud/
    │   │   │   ├── index.html.twig
    │   │   │   ├── detail.html.twig
    │   │   │   ├── edit.html.twig
    │   │   │   └── new.html.twig
    │   │   ├── menu.html.twig
    │   │   └── page/
    │   │       └── content.html.twig
    │   └── TwigBundle/           # Exception/error pages
    │       └── Exception/
    │           ├── error.html.twig
    │           └── error404.html.twig
    ├── components/               # Reusable components
    │   └── header/
    │       └── navbar.html.twig
    ├── email/                    # Email templates
    │   ├── base.html.twig
    │   ├── registration.html.twig
    │   ├── password_reset.html.twig
    │   └── payment_confirmation.html.twig
    └── panel/                    # Panel templates
        ├── base.html.twig        # Base layout
        ├── crud/                 # Per-CRUD overrides
        │   ├── product/
        │   │   ├── edit.html.twig
        │   │   └── index.html.twig
        │   ├── user/
        │   │   └── detail.html.twig
        │   └── server/
        │       └── show.html.twig
        ├── dashboard/            # Dashboard pages
        │   └── index.html.twig
        ├── servers/              # Server pages
        │   ├── index.html.twig
        │   └── show.html.twig
        └── cart/                 # Shopping cart pages
            └── index.html.twig

Assets Structure

Theme assets are stored separately in the public directory:

Template Categories

1. Global Templates (bundles/EasyAdminBundle/)

  • Override templates for ALL CRUD interfaces

  • Affects entire admin panel

  • Use sparingly - changes apply everywhere

Example use cases:

  • Custom admin layout for all pages

  • Global sidebar modifications

  • Consistent header/footer across admin

2. Exception/Error Templates (bundles/TwigBundle/)

  • Override error pages shown to users

  • Located in bundles/TwigBundle/Exception/

  • Customize how errors are displayed

Example templates:

  • error.html.twig - Generic error page

  • error404.html.twig - Page not found

  • error403.html.twig - Access denied

  • error500.html.twig - Server error

Example use cases:

  • Branded error pages matching your theme

  • Custom 404 page with helpful navigation

  • Maintenance mode error page

3. Reusable Components (components/)

  • Small, reusable UI components

  • Included from other templates

  • Promotes consistency and DRY principle

Example use cases:

  • Header/navbar component

  • Footer component

  • Alert/notification components

4. Per-CRUD Templates (panel/crud/{entity}/)

  • Override templates for specific CRUD only

  • More targeted, safer to customize

  • Example: panel/crud/product/edit.html.twig only affects product editing

Example use cases:

  • Custom product edit page

  • Specialized user detail view

  • Unique server management interface

5. Panel Templates (panel/)

  • Non-CRUD pages (dashboard, servers, cart, profile)

  • Custom page layouts

  • Email templates

Example use cases:

  • Dashboard customization

  • Server list and detail pages

  • Shopping cart page

  • User profile page

File Organization Best Practices

  1. Override only what you need - Don't copy entire default theme

  2. Use descriptive names - Clear file and folder naming

  3. Group related files - Keep components together

  4. Separate concerns - CSS, JS, and templates in appropriate directories

  5. Document custom templates - Add comments explaining changes

Template Resolution

PteroCA looks for templates in this order:

  1. Your theme (themes/my-theme/)

  2. Default theme (themes/default/)

  3. Bundle templates (vendor/easycorp/easyadmin-bundle/)

If a template exists in your theme, it's used. Otherwise, PteroCA falls back to the default.

Last updated