diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index ff68f1b2..260d076c 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -90,60 +90,60 @@ curl -v http://127.0.0.1:8080/phpinfo.php
1. Configure Git to always use `lf` line endings
- ```powershell
- git config --global core.autocrlf false
- git config --global core.eol lf
- ```
+ ```powershell
+ git config --global core.autocrlf false
+ git config --global core.eol lf
+ ```
2. Install Visual Studio, Git, and Go:
- ```powershell
- winget install -e --id Microsoft.VisualStudio.2022.Community --override "--passive --wait --add Microsoft.VisualStudio.Workload.NativeDesktop --add Microsoft.VisualStudio.Component.VC.Llvm.Clang --includeRecommended"
- winget install -e --id GoLang.Go
- winget install -e --id Git.Git
- ```
+ ```powershell
+ winget install -e --id Microsoft.VisualStudio.2022.Community --override "--passive --wait --add Microsoft.VisualStudio.Workload.NativeDesktop --add Microsoft.VisualStudio.Component.VC.Llvm.Clang --includeRecommended"
+ winget install -e --id GoLang.Go
+ winget install -e --id Git.Git
+ ```
3. Install vcpkg:
- ```powershell
- cd C:\
- git clone https://github.com/microsoft/vcpkg
- .\vcpkg\bootstrap-vcpkg.bat
- ```
+ ```powershell
+ cd C:\
+ git clone https://github.com/microsoft/vcpkg
+ .\vcpkg\bootstrap-vcpkg.bat
+ ```
4. [Download the latest version of the watcher library for Windows](https://github.com/e-dant/watcher/releases) and extract it to a directory named `C:\watcher`
5. [Download the latest **Thread Safe** version of PHP and of the PHP SDK for Windows](https://windows.php.net/download/), extract them in directories named `C:\php` and `C:\php-devel`
6. Clone the FrankenPHP Git repository:
- ```powershell
- git clone https://github.com/php/frankenphp C:\frankenphp
- cd C:\frankenphp
- ```
+ ```powershell
+ git clone https://github.com/php/frankenphp C:\frankenphp
+ cd C:\frankenphp
+ ```
7. Install the dependencies:
- ```powershell
- C:\vcpkg\vcpkg.exe install
- ```
+ ```powershell
+ C:\vcpkg\vcpkg.exe install
+ ```
8. Configure the needed environment variables (PowerShell):
- ```powershell
- $env:PATH += ';C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\Llvm\bin'
- $env:CC = 'clang'
- $env:CXX = 'clang++'
- $env:CGO_CFLAGS = "-O0 -g -IC:\frankenphp\vcpkg_installed\x64-windows\include -IC:\watcher -IC:\php-devel\include -IC:\php-devel\include\main -IC:\php-devel\include\TSRM -IC:\php-devel\include\Zend -IC:\php-devel\include\ext"
- $env:CGO_LDFLAGS = '-LC:\frankenphp\vcpkg_installed\x64-windows\lib -lbrotlienc -LC:\watcher -llibwatcher-c -LC:\php -LC:\php-devel\lib -lphp8ts -lphp8embed'
- ```
+ ```powershell
+ $env:PATH += ';C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\Llvm\bin'
+ $env:CC = 'clang'
+ $env:CXX = 'clang++'
+ $env:CGO_CFLAGS = "-O0 -g -IC:\frankenphp\vcpkg_installed\x64-windows\include -IC:\watcher -IC:\php-devel\include -IC:\php-devel\include\main -IC:\php-devel\include\TSRM -IC:\php-devel\include\Zend -IC:\php-devel\include\ext"
+ $env:CGO_LDFLAGS = '-LC:\frankenphp\vcpkg_installed\x64-windows\lib -lbrotlienc -LC:\watcher -llibwatcher-c -LC:\php -LC:\php-devel\lib -lphp8ts -lphp8embed'
+ ```
9. Run the tests:
- ```powershell
- go test -race -ldflags '-extldflags="-fuse-ld=lld"' ./...
- cd caddy
- go test -race -ldflags '-extldflags="-fuse-ld=lld"' -tags nobadger,nomysql,nopgx ./...
- cd ..
- ```
+ ```powershell
+ go test -race -ldflags '-extldflags="-fuse-ld=lld"' ./...
+ cd caddy
+ go test -race -ldflags '-extldflags="-fuse-ld=lld"' -tags nobadger,nomysql,nopgx ./...
+ cd ..
+ ```
10. Build the binary:
diff --git a/README.md b/README.md
index a2010a78..0ee36253 100644
--- a/README.md
+++ b/README.md
@@ -90,8 +90,8 @@ Our maintainers offer apk packages for all systems using `apk`. To install, run:
VERSION=85 # 82-85 available
echo "https://pkg.henderkes.com/api/packages/${VERSION}/alpine/main/php-zts" | sudo tee -a /etc/apk/repositories
KEYFILE=$(curl -sJOw '%{filename_effective}' https://pkg.henderkes.com/api/packages/${VERSION}/alpine/key)
-sudo mv ${KEYFILE} /etc/apk/keys/ &&
-sudo apk update &&
+sudo mv ${KEYFILE} /etc/apk/keys/ &&
+sudo apk update &&
sudo apk add frankenphp
```
@@ -170,6 +170,7 @@ Go to `https://localhost`, and enjoy!
- [Compile from sources](https://frankenphp.dev/docs/compile/)
- [Monitoring FrankenPHP](https://frankenphp.dev/docs/metrics/)
- [WordPress integration](https://frankenphp.dev/docs/wordpress/)
+- [Symfony integration](https://frankenphp.dev/docs/symfony/)
- [Laravel integration](https://frankenphp.dev/docs/laravel/)
- [Known issues](https://frankenphp.dev/docs/known-issues/)
- [Demo app (Symfony) and benchmarks](https://github.com/dunglas/frankenphp-demo)
@@ -178,7 +179,7 @@ Go to `https://localhost`, and enjoy!
## Examples and Skeletons
-- [Symfony](https://github.com/dunglas/symfony-docker)
+- [Symfony](https://frankenphp.dev/docs/symfony/)
- [API Platform](https://api-platform.com/docs/symfony)
- [Laravel](https://frankenphp.dev/docs/laravel/)
- [Sulu](https://sulu.io/blog/running-sulu-with-frankenphp)
diff --git a/docs/symfony.md b/docs/symfony.md
new file mode 100644
index 00000000..54acb5ce
--- /dev/null
+++ b/docs/symfony.md
@@ -0,0 +1,197 @@
+# Symfony
+
+## Docker
+
+For [Symfony](https://symfony.com) projects, we recommend using [Symfony Docker](https://github.com/dunglas/symfony-docker), the official Symfony Docker setup maintained by FrankenPHP's author. It provides a complete Docker-based environment with FrankenPHP, automatic HTTPS, HTTP/2, HTTP/3, and worker mode support out of the box.
+
+## Local Installation
+
+Alternatively, you can run your Symfony projects with FrankenPHP from your local machine:
+
+1. [Install FrankenPHP](../#getting-started)
+2. Add the following configuration to a file named `Caddyfile` in the root directory of your Symfony project:
+
+ ```caddyfile
+ # The domain name of your server
+ localhost
+
+ root public/
+ php_server {
+ # Optional: Enable worker mode for better performance
+ worker ./public/index.php
+ }
+ ```
+
+ See the [performance documentation](performance.md) for further optimizations.
+
+3. Start FrankenPHP from the root directory of your Symfony project: `frankenphp run`
+
+## Worker Mode
+
+Since Symfony 7.4, FrankenPHP worker mode is natively supported.
+
+For older versions, install the FrankenPHP package of [PHP Runtime](https://github.com/php-runtime/runtime):
+
+```console
+composer require runtime/frankenphp-symfony
+```
+
+Start your app server by defining the `APP_RUNTIME` environment variable to use the FrankenPHP Symfony Runtime:
+
+```console
+docker run \
+ -e FRANKENPHP_CONFIG="worker ./public/index.php" \
+ -e APP_RUNTIME=Runtime\\FrankenPhpSymfony\\Runtime \
+ -v $PWD:/app \
+ -p 80:80 -p 443:443 -p 443:443/udp \
+ dunglas/frankenphp
+```
+
+Learn more about [the worker mode](worker.md).
+
+## Hot Reload
+
+Hot reloading is enabled by default in [Symfony Docker](https://github.com/dunglas/symfony-docker).
+
+To use the [hot reload](hot-reload.md) feature without Symfony Docker, enable [Mercure](mercure.md) and add the `hot_reload` sub-directive to the `php_server` directive in your `Caddyfile`:
+
+```caddyfile
+localhost
+
+mercure {
+ anonymous
+}
+
+root public/
+php_server {
+ hot_reload
+ worker ./public/index.php
+}
+```
+
+Then, add the following code to your `templates/base.html.twig` file:
+
+```twig
+{% if app.request.server.has('FRANKENPHP_HOT_RELOAD') %}
+
+
+
+{% endif %}
+```
+
+Finally, run `frankenphp run` from the root directory of your Symfony project.
+
+## Pre-Compressing Assets
+
+Symfony's [AssetMapper component](https://symfony.com/doc/current/frontend/asset_mapper.html) can pre-compress assets with Brotli and Zstandard during deployment. FrankenPHP (through Caddy's `file_server`) can serve these pre-compressed files directly, avoiding on-the-fly compression overhead.
+
+1. Compile and compress your assets:
+
+ ```console
+ php bin/console asset-map:compile
+ ```
+
+2. Update your `Caddyfile` to serve pre-compressed assets:
+
+ ```caddyfile
+ localhost
+
+ @assets path /assets/*
+ file_server @assets {
+ precompressed zstd br gzip
+ }
+
+ root public/
+ php_server {
+ worker ./public/index.php
+ }
+ ```
+
+The `precompressed` directive tells Caddy to look for pre-compressed versions of the requested file (e.g., `app.css.zst`, `app.css.br`) and serve them directly if the client supports it.
+
+## Serving Large Static Files (`X-Sendfile`)
+
+FrankenPHP supports [efficiently serving large static files](x-sendfile.md) after executing PHP code (for access control, statistics, etc.).
+
+Symfony HttpFoundation [natively supports this feature](https://symfony.com/doc/current/components/http_foundation.html#serving-files).
+After [configuring your `Caddyfile`](x-sendfile.md#configuration), it will automatically determine the correct value for the `X-Accel-Redirect` header and add it to the response:
+
+```php
+use Symfony\Component\HttpFoundation\BinaryFileResponse;
+
+BinaryFileResponse::trustXSendfileTypeHeader();
+$response = new BinaryFileResponse(__DIR__.'/../private-files/file.txt');
+
+// ...
+```
+
+## Symfony Apps As Standalone Binaries
+
+Using [FrankenPHP's application embedding feature](embed.md), it's possible to distribute Symfony
+apps as standalone binaries.
+
+Follow these steps to prepare and package your Symfony app:
+
+1. Prepare your app:
+
+ ```console
+ # Export the project to get rid of .git/, etc
+ mkdir $TMPDIR/my-prepared-app
+ git archive HEAD | tar -x -C $TMPDIR/my-prepared-app
+ cd $TMPDIR/my-prepared-app
+
+ # Set proper environment variables
+ echo APP_ENV=prod > .env.local
+ echo APP_DEBUG=0 >> .env.local
+
+ # Remove the tests and other unneeded files to save space
+ # Alternatively, add these files with the export-ignore attribute in your .gitattributes file
+ rm -Rf tests/
+
+ # Install the dependencies
+ composer install --ignore-platform-reqs --no-dev -a
+
+ # Optimize .env
+ composer dump-env prod
+ ```
+
+2. Create a file named `static-build.Dockerfile` in the repository of your app:
+
+ ```dockerfile
+ FROM --platform=linux/amd64 dunglas/frankenphp:static-builder-gnu
+ # If you intend to run the binary on musl-libc systems, use static-builder-musl instead
+
+ # Copy your app
+ WORKDIR /go/src/app/dist/app
+ COPY . .
+
+ # Build the static binary
+ WORKDIR /go/src/app/
+ RUN EMBED=dist/app/ ./build-static.sh
+ ```
+
+ > [!CAUTION]
+ >
+ > Some `.dockerignore` files (e.g. default [Symfony Docker `.dockerignore`](https://github.com/dunglas/symfony-docker/blob/main/.dockerignore))
+ > will ignore the `vendor/` directory and `.env` files. Be sure to adjust or remove the `.dockerignore` file before the build.
+
+3. Build:
+
+ ```console
+ docker build -t static-symfony-app -f static-build.Dockerfile .
+ ```
+
+4. Extract the binary:
+
+ ```console
+ docker cp $(docker create --name static-symfony-app-tmp static-symfony-app):/go/src/app/dist/frankenphp-linux-x86_64 my-app ; docker rm static-symfony-app-tmp
+ ```
+
+5. Start the server:
+
+ ```console
+ ./my-app php-server
+ ```
+
+Learn more about the options available and how to build binaries for other OSes in the [applications embedding](embed.md)
+documentation.
diff --git a/docs/worker.md b/docs/worker.md
index f952c305..65e7e3b0 100644
--- a/docs/worker.md
+++ b/docs/worker.md
@@ -37,28 +37,9 @@ frankenphp php-server --worker /path/to/your/worker/script.php --watch="/path/to
This feature is often used in combination with [hot reloading](hot-reload.md).
-## Symfony Runtime
+## Symfony
-> [!TIP]
-> The following section is only necessary prior to Symfony 7.4, where native support for FrankenPHP worker mode was introduced.
-
-The worker mode of FrankenPHP is supported by the [Symfony Runtime Component](https://symfony.com/doc/current/components/runtime.html).
-To start any Symfony application in a worker, install the FrankenPHP package of [PHP Runtime](https://github.com/php-runtime/runtime):
-
-```console
-composer require runtime/frankenphp-symfony
-```
-
-Start your app server by defining the `APP_RUNTIME` environment variable to use the FrankenPHP Symfony Runtime:
-
-```console
-docker run \
- -e FRANKENPHP_CONFIG="worker ./public/index.php" \
- -e APP_RUNTIME=Runtime\\FrankenPhpSymfony\\Runtime \
- -v $PWD:/app \
- -p 80:80 -p 443:443 -p 443:443/udp \
- dunglas/frankenphp
-```
+See [the dedicated documentation](symfony.md#worker-mode).
## Laravel Octane
diff --git a/docs/x-sendfile.md b/docs/x-sendfile.md
index 8017f3d5..f9513c34 100644
--- a/docs/x-sendfile.md
+++ b/docs/x-sendfile.md
@@ -58,14 +58,4 @@ header('X-Accel-Redirect: file.txt');
## Projects using the Symfony HttpFoundation component (Symfony, Laravel, Drupal...)
-Symfony HttpFoundation [natively supports this feature](https://symfony.com/doc/current/components/http_foundation.html#serving-files).
-It will automatically determine the correct value for the `X-Accel-Redirect` header and add it to the response.
-
-```php
-use Symfony\Component\HttpFoundation\BinaryFileResponse;
-
-BinaryFileResponse::trustXSendfileTypeHeader();
-$response = new BinaryFileResponse(__DIR__.'/../private-files/file.txt');
-
-// ...
-```
+See [the Symfony documentation](symfony.md#serving-large-static-files-x-sendfile) for details on using this feature with Symfony HttpFoundation.