Backend API for the tyto.chat platform. Built with Symfony 7.4 LTS and API Platform 4, it exposes a JSON-LD REST API consumed by the standalone React SPA (client).
This document will be most useful for developers working on the codebase. If you just want to install and run your own Tyto server, tyto.chat has you covered — see below.
Production runs prebuilt images (ghcr.io/tyto-chat/tyto-core) with Docker
Compose — three env values, auto-generated secrets, auto-HTTPS. Follow the
Quick Start; operational guides (reverse
proxy, backups, updates, troubleshooting) are in the
documentation.
lexik/jwt-authentication-bundle (+ refresh tokens)All of the above (MariaDB, Mercure, Meilisearch, Valkey, LiveKit) run as DDEV sidecars — nothing to install locally.
That's it — PHP, Composer and MariaDB are all provided by DDEV.
# 1. Clone the repository into a directory named "core"
git clone https://github.com/tyto-chat/core.git core
cd core
# 2. Start DDEV (first run will pull Docker images)
ddev start
# 3. Install dependencies, run migrations, generate JWT + Mercure keys, create an admin user
ddev init
ddev init will prompt you for the admin user's email and password.
The API is now available at https://core.ddev.site/api.
The project name is derived from the directory name. Clone into
coreto match the URLs above and to ensure the client's Mercure proxy connects to the right container.
The platform is two repos. Bring up the backend first, then the SPA:
# Backend
git clone https://github.com/tyto-chat/core.git core && cd core
ddev start && ddev init # deps, DB, keys, admin user, bot
# Frontend (sibling directory)
git clone https://github.com/tyto-chat/client.git client && cd ../client
ddev start && ddev setup # deps, .env.local (points VITE at core), Playwright
App: https://client.ddev.site · API: https://core.ddev.site/api.
| Command | Description |
|---|---|
ddev start | Start the development environment |
ddev stop | Stop containers |
ddev init | First-time setup (safe to re-run — skips steps already done) |
ddev reset-db | Drop the database, recreate it and replay the migrations |
ddev composer <cmd> | Run Composer inside the container |
ddev php <cmd> | Run PHP inside the container |
ddev mysql | Open a MariaDB shell |
ddev logs | Tail container logs |
Use the ddev test command, which handles test database setup automatically (creates the database, runs migrations, and generates JWT keys on the first run):
# Run all tests
ddev test
# Run only functional tests
ddev test tests/Functional/
# Run only unit tests
ddev test tests/Unit/
# Run a specific test file
ddev test tests/Functional/Api/MessageTest.php
# Run a specific test method
ddev test tests/Functional/Api/MessageTest.php --filter=testSendMessageAsMember
Any options after ddev test are passed directly to PHPUnit.
The test suite has three suites (--testsuite <name> to run one):
tests/Unit/) — isolated tests for entities, services, validators and state processorstests/Functional/) — API integration tests that hit real endpoints against the MariaDB test database; each test runs inside a transaction that is rolled back afterwards (via the DAMA Doctrine test bundle) for isolation without re-seedingtests/Integration/) — tests that deliberately hit the real Redis sidecar (presence, voice participants, health probes); Unit + Functional stub Redis and Meilisearch and need only MariaDB# Static analysis
ddev composer phpstan
# Check code style
ddev composer checkcs
# Fix code style
ddev composer fixcs
The .env file documents all available variables. Local overrides go in .env.local (git-ignored). ddev init creates .env.local automatically with the correct DDEV database URL.
Notable variables:
| Variable | Description |
|---|---|
DATABASE_URL | Doctrine connection string |
MAILER_DSN | Transport for outgoing emails (default: null://null in dev) |
MERCURE_URL | Internal Mercure hub URL (used by the Symfony publisher) |
MERCURE_PUBLIC_URL | Public Mercure hub URL (sent to clients) |
MERCURE_JWT_SECRET | Shared secret for signing Mercure JWTs |
The full production environment reference lives in
.env.prod.example and the
advanced configuration docs.
See the contribution guide for the fork-PR workflow and the code guidelines this codebase is written by. CI runs the full gate (tests, PHPStan, code style) on every pull request.
MIT.
PHP
96.9%
Shell
1.9%
Backend API for the tyto.chat platform. Built with Symfony 7.4 LTS and API Platform 4, it exposes a JSON-LD REST API consumed by the standalone React SPA (client).
This document will be most useful for developers working on the codebase. If you just want to install and run your own Tyto server, tyto.chat has you covered — see below.
Production runs prebuilt images (ghcr.io/tyto-chat/tyto-core) with Docker
Compose — three env values, auto-generated secrets, auto-HTTPS. Follow the
Quick Start; operational guides (reverse
proxy, backups, updates, troubleshooting) are in the
documentation.
lexik/jwt-authentication-bundle (+ refresh tokens)All of the above (MariaDB, Mercure, Meilisearch, Valkey, LiveKit) run as DDEV sidecars — nothing to install locally.
That's it — PHP, Composer and MariaDB are all provided by DDEV.
# 1. Clone the repository into a directory named "core"
git clone https://github.com/tyto-chat/core.git core
cd core
# 2. Start DDEV (first run will pull Docker images)
ddev start
# 3. Install dependencies, run migrations, generate JWT + Mercure keys, create an admin user
ddev init
ddev init will prompt you for the admin user's email and password.
The API is now available at https://core.ddev.site/api.
The project name is derived from the directory name. Clone into
coreto match the URLs above and to ensure the client's Mercure proxy connects to the right container.
The platform is two repos. Bring up the backend first, then the SPA:
# Backend
git clone https://github.com/tyto-chat/core.git core && cd core
ddev start && ddev init # deps, DB, keys, admin user, bot
# Frontend (sibling directory)
git clone https://github.com/tyto-chat/client.git client && cd ../client
ddev start && ddev setup # deps, .env.local (points VITE at core), Playwright
App: https://client.ddev.site · API: https://core.ddev.site/api.
| Command | Description |
|---|---|
ddev start | Start the development environment |
ddev stop | Stop containers |
ddev init | First-time setup (safe to re-run — skips steps already done) |
ddev reset-db | Drop the database, recreate it and replay the migrations |
ddev composer <cmd> | Run Composer inside the container |
ddev php <cmd> | Run PHP inside the container |
ddev mysql | Open a MariaDB shell |
ddev logs | Tail container logs |
Use the ddev test command, which handles test database setup automatically (creates the database, runs migrations, and generates JWT keys on the first run):
# Run all tests
ddev test
# Run only functional tests
ddev test tests/Functional/
# Run only unit tests
ddev test tests/Unit/
# Run a specific test file
ddev test tests/Functional/Api/MessageTest.php
# Run a specific test method
ddev test tests/Functional/Api/MessageTest.php --filter=testSendMessageAsMember
Any options after ddev test are passed directly to PHPUnit.
The test suite has three suites (--testsuite <name> to run one):
tests/Unit/) — isolated tests for entities, services, validators and state processorstests/Functional/) — API integration tests that hit real endpoints against the MariaDB test database; each test runs inside a transaction that is rolled back afterwards (via the DAMA Doctrine test bundle) for isolation without re-seedingtests/Integration/) — tests that deliberately hit the real Redis sidecar (presence, voice participants, health probes); Unit + Functional stub Redis and Meilisearch and need only MariaDB# Static analysis
ddev composer phpstan
# Check code style
ddev composer checkcs
# Fix code style
ddev composer fixcs
The .env file documents all available variables. Local overrides go in .env.local (git-ignored). ddev init creates .env.local automatically with the correct DDEV database URL.
Notable variables:
| Variable | Description |
|---|---|
DATABASE_URL | Doctrine connection string |
MAILER_DSN | Transport for outgoing emails (default: null://null in dev) |
MERCURE_URL | Internal Mercure hub URL (used by the Symfony publisher) |
MERCURE_PUBLIC_URL | Public Mercure hub URL (sent to clients) |
MERCURE_JWT_SECRET | Shared secret for signing Mercure JWTs |
The full production environment reference lives in
.env.prod.example and the
advanced configuration docs.
See the contribution guide for the fork-PR workflow and the code guidelines this codebase is written by. CI runs the full gate (tests, PHPStan, code style) on every pull request.
MIT.
PHP
96.9%
Shell
1.9%