PHPackages                             symfonicat/core - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. symfonicat/core

ActiveProject

symfonicat/core
===============

Symfonicat Symfony application with admin, routing, module runtime, Electron tooling, and FrankenPHP starter infrastructure.

v0.1.0(yesterday)03↑2900%proprietarySCSSPHP &gt;=8.4

Since Dec 14Pushed todayCompare

[ Source](https://github.com/symfonicat/core)[ Packagist](https://packagist.org/packages/symfonicat/core)[ RSS](/packages/symfonicat-core/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (32)Versions (4)Used By (0)

Symfonicat
==========

[](#symfonicat)

`symfonicat/core` is the full Symfonicat Symfony application: admin, public runtime, webpack, Electron, and the FrankenPHP-oriented starter shell all live here

Install
-------

[](#install)

```
composer create-project symfonicat/core symfonicat
cd symfonicat
docker compose up -d
npm install
npm run dev
```

You don't need to run `doctrine:schema:create` to get the UI up locally. On first container boot, the `php` service bootstraps the local stack:

- synchronizes the Doctrine schema
- seeds a `localhost` domain row
- seeds and enables the `analytics` module for `localhost`

After the containers are up, create an admin:

```
docker exec php bin/console symfonicat:admin:create
```

Philosophy
----------

[](#philosophy)

- only supports one subdomain layer
- a subdomain (`Project`) is usually a second-tier section of a site, so Symfonicat treats it as a first-class runtime shell
- `Project` entities exist in the database for Symfony-native referencing, modularity, extension, and tracking
- `Project` entities can be prepared for Electron applications
- when a `Project` is active, the public runtime uses a catch-all route so the rest of the URL can be client-side routed
- if no `Project` is active, the `Domain` runtime is loaded
- if you are on a `Domain` and there is a path, Symfony handles it
- if you are on a `Domain`, there is a path, and a matching `RoutingRule` exists for the first path segment, Symfonicat can redirect to the correct `Domain` and let Symfony continue from there

Included
--------

[](#included)

- the public frontend runtime for domains, projects, modules, and routing rules
- the separate `/admin` runtime and admin templates
- the internal `SymfonicatBundle` service/entity/template organization
- shared frontend assets under `assets`
- the webpack helper [webpack.symfonicat.js](webpack.symfonicat.js)
- the Electron desktop shell under [electron](electron)
- drop-in FrankenPHP infrastructure files such as [compose.yaml](compose.yaml) and [Caddyfile](Caddyfile)

Runtime Model
-------------

[](#runtime-model)

Symfonicat resolves requests in layers.

1. A request arrives on the base domain or a subdomain.
2. Subscribers resolve the active `Domain`, `Project`, and `RoutingRule`.
3. The public controller decides whether to render a domain shell or a project shell.
4. If there is no resolved project and the domain request has a path, the request continues through the normal Symfony application routes.
5. Encore entrypoints are selected from the current database-backed domain, project, and module state.

The public entry routes live in [MainController.php](src/Symfonicat/Controller/MainController.php):

- `/` renders the domain shell when there is no resolved project.
- `/{path}` renders the project shell when a project is resolved onto the request.
- domain paths without a resolved project are left for the Symfony app route table, such as `/admin`, `/m/{slug}`, or other application routes.

Resolution is driven primarily by subdomain and routing-rule context. The key runtime pieces are:

- [ProjectService.php](src/Symfonicat/Service/ProjectService.php)
- [ProjectSubscriber.php](src/Symfonicat/EventSubscriber/ProjectSubscriber.php)
- [RoutingRuleSubscriber.php](src/Symfonicat/EventSubscriber/RoutingRuleSubscriber.php)
- [DomainRedirectSubscriber.php](src/Symfonicat/EventSubscriber/DomainRedirectSubscriber.php)

Module System
-------------

[](#module-system)

The module system is database-backed and route-aware.

- A `Module` record is identified by slug.
- Modules can be attached to a `Project` or a `Domain`.
- Backend module endpoints live under `/m/{slug}`.
- Frontend module entrypoints build under `modules/{slug}`.

The runtime guard is in [AbstractModuleController.php](src/Symfonicat/Controller/AbstractModuleController.php). A module controller only runs when the current request context actually has that module attached.

That gives you a clean rule:

- attach a module to a project when it should run only inside that project
- attach a module to a domain when it should run at the domain level without a project

The current concrete server example is [AnalyticsController.php](src/Symfonicat/Controller/Module/AnalyticsController.php), which exposes `POST /m/analytics`.

Client-Side Routing and Assets
------------------------------

[](#client-side-routing-and-assets)

Symfonicat keeps frontend routing simple: the server resolves the page shell, then project/module entrypoints attach behavior.

The project shell in [project/main.html.twig](templates/project/main.html.twig) loads:

- a project entrypoint named `projects/{project.slug}`
- zero or more module entrypoints named `modules/{module.slug}`

The shared webpack helper [webpack.symfonicat.js](webpack.symfonicat.js) discovers entries from:

- `symfonicat:data:webpack`
- or, if that command is unavailable during build time, the filesystem under `assets/domains`, `assets/projects`, and `assets/modules`

Frontend bootstrap is split into a few small pieces:

- [app.js](assets/app.js) is the shared app entry
- [stimulus.js](assets/stimulus.js) starts Stimulus through `@symfony/stimulus-bridge`
- [controllers.json](assets/controllers.json) enables Symfony UX controllers
- Turbo is started through the `symfony--ux-turbo--turbo-core` controller mounted on the `` in the base layouts

Browser-side module requests are intentionally simple and live in [module.js](assets/module.js). The conventions are:

- all module requests are `POST`
- all module requests begin with `/m/{module}`
- if a path is provided, the final URL becomes `/m/{module}/{path}`
- `.json(...)` expects a JSON response body
- `.html(...)` expects a raw HTML response body

Examples:

```
const parsedJson = await 'analytics'.json({ working: true });
const parsedJsonWithPath = await 'analytics'.json('path/secondpath', { working: true });

const parsedHtml = await 'frame'.html({ working: true });
const parsedHtmlWithPath = await 'frame'.html('path/secondpath', { working: true });
```

Those helpers are available through the shared [app.js](assets/app.js) bootstrap. Module entrypoints do not need to import `./module` themselves.

Admin Area
----------

[](#admin-area)

`` The admin runtime is separate from any public app user system.

- admin auth is HTTP basic
- admin credentials live in the separate `symfonicat_admin` table

Redis
-----

[](#redis)

The Docker stack provides Redis at the standard `REDIS_URL` environment variable:

```
REDIS_URL=redis://redis:6379
MESSENGER_TRANSPORT_DSN=redis://redis:6379/symfonicat_messages
MESSENGER_FAILED_TRANSPORT_DSN=redis://redis:6379/symfonicat_failed_messages
MESSENGER_CONSUMER_NAME=symfonicat
```

Symfony uses Redis for shared runtime infrastructure:

- `cache.app` uses `cache.adapter.redis_tag_aware`
- `cache.system` stays on Symfony's default local adapter for container and warmup data
- sessions use `RedisSessionHandler` with a `symfonicat_session:` key prefix
- `cache.symfonicat` is available as a one-hour application cache pool for Symfonicat runtime data
- Messenger uses Redis streams for the `async` and `failed` transports
- `Symfony\Component\Mercure\Update` messages dispatched through Messenger are routed to `async`

Run a Redis-backed Messenger worker when you need async message consumption:

```
docker exec php bin/console messenger:consume async
docker exec php bin/console messenger:stats
docker exec php bin/console messenger:failed:show
```

Key console commands
--------------------

[](#key-console-commands)

Scaffolding:

- `bin/console make:module  ` creates a module controller, module service, and `assets/modules/{slug}/index.js` entrypoint

Admin management:

- `symfonicat:admin:create` creates or updates an admin account
- `symfonicat:admin:delete` deletes an admin account by email
- `symfonicat:bootstrap` waits for PostgreSQL, synchronizes the schema, and seeds `localhost` for local development

Runtime data export:

- `symfonicat:data:webpack` outputs domain, project, and module data for Encore entry discovery
- `symfonicat:data:electron` outputs project metadata for the Electron layer
- `symfonicat:data:dns` outputs project/domain data for DNS-related workflows

Electron support:

- `symfonicat:electron:prepare` prepares Electron project directories
- `symfonicat:electron:dev` prepares Electron directories for local development
- `symfonicat:electron:build` runs the Electron build flow
- `symfonicat:electron:package` packages Electron bundles

Ops and diagnostics:

- `symfonicat:public-suffix:refresh` downloads `public_suffix_list.dat`
- `symfonicat:test:mercure` publishes a Turbo Stream test event
- `symfonicat:test:redis` checks Redis connectivity

Infrastructure
--------------

[](#infrastructure)

This repo ships app-level infrastructure files directly:

- [compose.yaml](compose.yaml) for FrankenPHP, Mercure, PostgreSQL, and Redis
- [Caddyfile](Caddyfile) for the FrankenPHP/Caddy setup
- [electron.js](electron.js) plus the [electron](electron) directory for desktop packaging

###  Health Score

40

—

FairBetter than 87% of packages

Maintenance100

Actively maintained with recent releases

Popularity4

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity44

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

1d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/39426653?v=4)[Tayp](/maintainers/taypme)[@taypme](https://github.com/taypme)

---

Top Contributors

[![taypme](https://avatars.githubusercontent.com/u/39426653?v=4)](https://github.com/taypme "taypme (2 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/symfonicat-core/health.svg)

```
[![Health](https://phpackages.com/badges/symfonicat-core/health.svg)](https://phpackages.com/packages/symfonicat-core)
```

###  Alternatives

[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.4k5.6M643](/packages/sylius-sylius)[prestashop/prestashop

PrestaShop is an Open Source e-commerce platform, committed to providing the best shopping cart experience for both merchants and customers.

9.0k15.4k](/packages/prestashop-prestashop)[easycorp/easyadmin-demo

EasyAdmin Demo Application

145.7k](/packages/easycorp-easyadmin-demo)[kimai/kimai

Kimai - Time Tracking

4.6k7.4k1](/packages/kimai-kimai)[contao/core-bundle

Contao Open Source CMS

1231.6M2.3k](/packages/contao-core-bundle)[forumify/forumify-platform

121.8k11](/packages/forumify-forumify-platform)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
