AdminKitDocs
Frameworks

Symfony

Add AdminKit to a Symfony web application with AssetMapper's importmap:require, a Twig base layout and Turbo navigation.

The Symfony webapp pack uses AssetMapper with an import map, so AdminKit is added with importmap:require and imported from assets/app.js. No Node build step is needed.

Install

composer create-project symfony/skeleton my-app
cd my-app
composer require webapp
php bin/console importmap:require @adminkit/core

importmap:require downloads app.js into assets/vendor/ and adds it to importmap.php, pinned to the version it resolved.

AdminKit PRO is not published to npm. Copy dist/ from the download into assets/adminkit/, import ./adminkit/css/app.css and ./adminkit/js/app.js with relative paths instead of the CDN link and @adminkit/core, and load head.js with {{ asset('adminkit/js/head.js') }}.

Import the CSS and JavaScript

Import app.js from the app entry point, which {{ importmap('app') }} in base.html.twig already loads. Turbo Drive replaces <body> on every visit while the script keeps running, and app.js sets up the icons and the sidebar in each new body.

assets/app.js
import './stimulus_bootstrap.js';
import '@adminkit/core';

importmap:require downloads single files, and the stylesheet's fonts are separate files next to it, so link the stylesheet from the CDN in <head>, before the import map:

templates/base.html.twig
<link href="https://unpkg.com/@adminkit/core/dist/css/app.css" rel="stylesheet">

Optional: avoid a color mode flash

Without head.js, app.js applies the stored color mode once it runs, so a visitor who picked the mode opposite to their operating system briefly sees the other one. head.js applies it before the first paint. Load it as a plain script in <head>, before the stylesheet:

<script src="https://unpkg.com/@adminkit/core/dist/js/head.js"></script>

Minimal layout

templates/base.html.twig
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <title>{% block title %}Dashboard{% endblock %}</title>
        <link href="https://unpkg.com/@adminkit/core/dist/css/app.css" rel="stylesheet">
        {% block stylesheets %}{% endblock %}
        {% block javascripts %}
            {% block importmap %}{{ importmap('app') }}{% endblock %}
        {% endblock %}
    </head>
    <body>
        <div class="wrapper">
            <nav id="sidebar" class="sidebar js-sidebar offcanvas-lg offcanvas-start" tabindex="-1" aria-label="Sidebar">
                <div class="sidebar-content js-simplebar">
                    <a class="sidebar-brand" href="{{ path('app_dashboard') }}">
                        <span class="align-middle">AdminKit</span>
                    </a>
                    <ul class="sidebar-nav">
                        <li class="sidebar-header">Pages</li>
                        <li class="sidebar-item {{ app.current_route == 'app_dashboard' ? 'active' }}">
                            <a class="sidebar-link" href="{{ path('app_dashboard') }}">
                                <i class="align-middle" data-lucide="sliders-vertical"></i> <span class="align-middle">Dashboard</span>
                            </a>
                        </li>
                        <li class="sidebar-item {{ app.current_route == 'app_profile' ? 'active' }}">
                            <a class="sidebar-link" href="/profile">
                                <i class="align-middle" data-lucide="user"></i> <span class="align-middle">Profile</span>
                            </a>
                        </li>
                    </ul>
                </div>
            </nav>

            <div class="main">
                <nav class="navbar navbar-expand navbar-light navbar-bg">
                    <button type="button" class="sidebar-toggle js-sidebar-toggle" aria-controls="sidebar" aria-expanded="true" aria-label="Collapse sidebar">
                        <i class="hamburger align-self-center"></i>
                    </button>
                </nav>
                <main class="content">
                    <div class="container-fluid p-0">
                        {% block body %}{% endblock %}
                    </div>
                </main>
            </div>
        </div>
    </body>
</html>
src/Controller/DashboardController.php
<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;

class DashboardController extends AbstractController
{
    #[Route('/', name: 'app_dashboard')]
    public function index(): Response
    {
        return $this->render('dashboard/index.html.twig');
    }
}
templates/dashboard/index.html.twig
{% extends 'base.html.twig' %}

{% block body %}
    <h1 class="h3 mb-3">Dashboard</h1>
    <div class="card">
        <div class="card-body">Hello from AdminKit.</div>
    </div>
{% endblock %}

Run

php -S localhost:8000 -t public

Open http://localhost:8000. You should see the dark sidebar, the navbar with the hamburger toggle and the card, with the Symfony debug toolbar at the bottom. With the Symfony CLI installed, symfony server:start serves the same app.

Notes

  • assets/app.js in the generated project also imports ./styles/app.css and logs a welcome message. Keep the stylesheet import for your own CSS, which loads after the AdminKit stylesheet, or remove it.
  • AssetMapper serves the files directly in the dev environment. For production, run php bin/console asset-map:compile.
  • The CDN URLs above are unpinned and serve the latest published version. Pin the version importmap:require reports, for example https://unpkg.com/@adminkit/core@<version>/dist/css/app.css.

Last updated on

On this page