diff --git a/.gitattributes b/.gitattributes
index 7bb3d8153..f18431d9f 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -9,7 +9,6 @@ website/ export-ignore
.gitattributes export-ignore
.gitignore export-ignore
.phpcs.xml export-ignore
-couscous.yml export-ignore
docker-compose.yml export-ignore
Makefile export-ignore
phpstan.neon export-ignore
diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml
new file mode 100644
index 000000000..dd532ddf7
--- /dev/null
+++ b/.github/workflows/website.yml
@@ -0,0 +1,37 @@
+name: Website
+
+on:
+ push:
+ branches: [ 'website-v3' ]
+
+env:
+ VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
+ VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
+
+jobs:
+
+ deploy:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ defaults:
+ run:
+ working-directory: ./website
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ fetch-depth: 0 # fetch all history for "latest modified time"
+ - run: npm install --global vercel@latest
+ - run: make src/pages/docs
+ - name: Pull Vercel Environment Information
+ run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
+ - name: Build
+ run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
+ env:
+ # CUSTOM_GITHUB_TOKEN_READ is a manually created GitHub token with appropriate permissions:
+ # - allowed to list contributors
+ # - allowed to list sponsors
+ # It wouldn't be possible to use the default GITHUB_TOKEN because it doesn't have the required permissions.
+ GITHUB_TOKEN: ${{ secrets.CUSTOM_GITHUB_TOKEN_READ }}
+ - name: Deploy
+ run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }}
diff --git a/Makefile b/Makefile
index a2bdaf022..4ccc30d97 100644
--- a/Makefile
+++ b/Makefile
@@ -6,25 +6,6 @@ trigger_runtimes:
runtime_build_status:
aws codepipeline get-pipeline-state --name=bref-php-binary | jq ".stageStates[1].latestExecution.status"
-# Generate and deploy the production version of the website using http://couscous.io
-website:
- # See http://couscous.io/
- couscous generate
- netlify deploy --prod --dir=.couscous/generated
-website-staging:
- couscous generate
- netlify deploy --dir=.couscous/generated
-
-# Run a local preview of the website using http://couscous.io
-website-preview:
- couscous preview
-
-website-assets: website/template/output.css
-website/template/output.css: website/node_modules website/template/styles.css website/tailwind.config.js
- cd website && NODE_ENV=production npx tailwind build template/styles.css -o template/output.css
-website/node_modules: website/package.json website/package-lock.json
- cd website && npm install
-
# Deploy the demo functions
demo:
serverless deploy
@@ -35,4 +16,4 @@ layers.json:
test-stack:
serverless deploy -c tests/serverless.tests.yml
-.PHONY: website website-preview website-assets demo layers.json test-stack
+.PHONY: demo layers.json test-stack
diff --git a/SECURITY.md b/SECURITY.md
index 49719927b..7d21f003a 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -12,7 +12,7 @@ Version 1.7.x will only receive critical bug fixes and security fixes, as well P
You are encouraged to upgrade to v2.
-If you prefer to stay on v1 and need long term support for v1 (or need help upgrading), get in touch for enterprise support: https://bref.sh/#enterprise
+If you prefer to stay on v1 and need long term support for v1 (or need help upgrading), get in touch for enterprise support: https://bref.sh/support
## Reporting a Vulnerability
diff --git a/bref b/bref
index 493d6f74f..f72b17f1d 100755
--- a/bref
+++ b/bref
@@ -21,7 +21,7 @@ switch ($argv[1] ?? '') {
break;
case 'cli':
cliWarning();
- error('Since Bref 2.0, the "bref cli" command has been moved. Read https://bref.sh/docs/runtimes/console.html#usage');
+ error('Since Bref 2.0, the "bref cli" command has been moved. Read https://bref.sh/docs/runtimes/console#usage');
case 'layers':
cliWarning();
echo "Bref layer ARNs can be found here: https://runtimes.bref.sh/\n\n";
@@ -29,7 +29,7 @@ switch ($argv[1] ?? '') {
exit(1);
case 'local':
cliWarning();
- error('Since Bref 2.0, the "bref local" command has been moved. Read https://bref.sh/docs/function/local-development.html\n');
+ error('Since Bref 2.0, the "bref local" command has been moved. Read https://bref.sh/docs/local-development/event-driven-functions\n');
case 'dashboard':
cliWarning();
echo "The Bref Dashboard is now available as a desktop application.\n\n";
diff --git a/couscous.yml b/couscous.yml
deleted file mode 100644
index 02fe7bc4a..000000000
--- a/couscous.yml
+++ /dev/null
@@ -1,172 +0,0 @@
-template:
- # Name of the directory containing the website template (default is "website")
- directory: website/template
-
-exclude:
- - demo
- - runtime
- - src
- - template
- - tests
- - vendor
- - website
- # This special entry will ask Couscous to read the excluded directories from your ".gitignore" file
- - "%gitignore%"
-
-scripts:
- # Scripts to execute before generating the website
- before:
- - make website-assets
-
-menu:
- intro:
- - section: Getting started
- items:
- what-is-bref:
- text: What is Bref and serverless?
- url: /docs/
- installation:
- text: Installation
- url: /docs/installation.html
- first-steps:
- text: First steps
- url: /docs/first-steps.html
- runtimes-introduction:
- text: Introduction to PHP runtimes
- url: /docs/runtimes/
-
- webHosting:
- - section: 'Bref for web apps'
- items:
- web-apps:
- text: Web apps on AWS Lambda
- url: /docs/runtimes/http.html
- websites:
- text: Website assets
- url: /docs/websites.html
- title: Building complete websites with Bref
- console-applications:
- text: Console commands
- url: /docs/runtimes/console.html
- web-cron:
- text: Cron commands
- url: /docs/web-apps/cron.html
- title: CLI cron tasks
- web-local-development:
- text: Local development
- url: /docs/web-apps/local-development.html
- web-docker:
- text: Docker
- url: /docs/web-apps/docker.html
- - section: Frameworks
- items:
- laravel:
- text: Laravel
- url: /docs/frameworks/laravel.html
- title: Learn how to deploy serverless Laravel applications
- symfony:
- text: Symfony
- url: /docs/frameworks/symfony.html
- title: Learn how to deploy serverless Symfony applications
-
- functions:
- - section: 'Bref for event-driven functions'
- items:
- php-functions:
- text: PHP functions on AWS Lambda
- url: /docs/runtimes/function.html
- typed-handlers:
- text: Typed handlers
- url: /docs/function/handlers.html
- function-local-development:
- text: Local development
- url: /docs/function/local-development.html
- cron-function:
- text: Cron functions
- url: /docs/function/cron.html
-
- other:
- - section: Workflow
- items:
- deploy:
- text: Deployment
- url: /docs/deploy.html
- monitoring:
- text: Monitoring
- url: /docs/monitoring.html
- - section: Environment
- items:
- serverless-yml:
- text: serverless.yml
- url: /docs/environment/serverless-yml.html
- title: Configure your application with the serverless.yml file
- variables:
- text: Variables
- url: /docs/environment/variables.html
- title: Configuring environment variables with Bref
- php:
- text: PHP
- url: /docs/environment/php.html
- title: Configuring PHP versions and options with Bref
- storage:
- text: Storage
- url: /docs/environment/storage.html
- title: Storing files and data with Bref on AWS Lambda
- logs:
- text: Logs
- url: /docs/environment/logs.html
- title: Managing logs with Bref on AWS Lambda
- database:
- text: Databases
- url: /docs/environment/database.html
- title: Using a database from AWS Lambda
- database-planetscale:
- text: Databases - PlanetScale
- url: /docs/environment/database-planetscale.html
- title: Using PlanetScale from AWS Lambda
- custom-domains:
- text: Custom domains
- url: /docs/environment/custom-domains.html
- title: Configuring custom domain names
- performances:
- text: Performance
- url: /docs/environment/performances.html
- title: Performance tuning and optimizations
- - section: Upgrading
- items:
- v2:
- text: Upgrading to v2
- url: /docs/upgrading/v2.html
- title: Upgrading Bref applications to Bref v2
- - section: Learning
- items:
- course:
- text: Course
- url: https://serverless-visually-explained.com/?ref=bref-menu
- title: Serverless Visually Explained
- case-studies:
- text: Case studies
- url: /docs/case-studies.html
- title: A collection of case studies of serverless PHP applications built using Bref.
- community:
- text: Community
- url: /docs/community.html
- title: Places where to learn and exchange about Bref.
- - section: Ecosystem
- items:
- github:
- text: GitHub
- url: https://github.com/brefphp
- title: Bref on GitHub
- twitter:
- text: Twitter
- url: https://twitter.com/brefphp
- title: Bref on Twitter
- slack:
- text: Slack
- url: https://join.slack.com/t/brefworkspace/shared_invite/enQtNTcwMjU2NTcxNjAxLTIxYmM2MmRjMDkzYjdjYTNkMmE5NGI3YTcyZjc2ZGRjNTFmNjFmYzk5NWQ1YmVhMDkwNzExNzhjZThkZWM0ODE
- title: Join the Slack community
- dashboard:
- text: Bref Dashboard
- url: https://dashboard.bref.sh/?ref=bref
- title: Bref Dashboard
diff --git a/docs/README.md b/docs/README.md
deleted file mode 100644
index 31e20fa59..000000000
--- a/docs/README.md
+++ /dev/null
@@ -1,188 +0,0 @@
----
-title: What is Bref and serverless?
-current_menu: what-is-bref
-introduction: An introduction to what serverless and Bref can offer for PHP applications.
-next:
- link: /docs/installation.html
- title: Installation
----
-
-Serverless means using cloud services that manage the servers for us.
-
-## Why serverless?
-
-When running PHP on a server, we must:
-
-- setup, configure and maintain that server,
-- pay a fixed price for the server,
-- scale the server(s) if we get more traffic.
-
-When running PHP serverless:
-
-- We do not need to set up servers, the cloud provider takes care of that.
-- We pay only for what we use.
-- Our application scales automatically.
-
-**Serverless provides more scalable, affordable and reliable architectures for less effort.**
-
-Serverless includes services like storage as a service, database as a service, message queue as a service, etc. One service in particular is interesting for us developers: *Function as a Service* (FaaS).
-
-FaaS is a way to run code where the hosting provider takes care of setting up everything, keeping the application available 24/7, scaling it up and down and we are only charged *while the code is actually executing*.
-
-## Why Bref?
-
-
-Bref aims to make running PHP applications simple.
-
-
-To reach that goal, Bref takes advantage of serverless technologies. However, while serverless is promising, there are many choices to make, tools to build and best practices to figure out.
-
-Bref's approach is to:
-
-- **simplify problems by removing choices**
-
- *instead of trying to address every need*
-- **provide simple and familiar solutions**
-
- *instead of aiming for powerful custom solutions*
-- **empower by sharing knowledge**
-
- *instead of hiding too much behind leaky abstractions*
-
-### What is Bref
-
-Bref (which means "brief" in french) comes as an open source Composer package and helps you deploy PHP applications to [AWS](https://aws.amazon.com) and run them on [AWS Lambda](https://aws.amazon.com/lambda/).
-
-Bref provides:
-
-- documentation
-- PHP runtimes for AWS Lambda
-- deployment tooling
-- PHP frameworks integration
-
-The choice of AWS as serverless provider is deliberate: at the moment AWS is the leading hosting provider, it is ahead in the serverless space in terms of features, performance and reliability.
-
-Bref uses [the Serverless framework](https://serverless.com/) to configure and deploy serverless applications. Being the most popular tool, Serverless comes with a huge community, a lot of examples online and a simple configuration format.
-
-## Use cases
-
-Bref and AWS Lambda can be used to run many kind of PHP application, for example:
-
-- APIs
-- workers
-- batch processes/scripts
-- websites
-
-Bref aims to support any PHP framework as well.
-
-If you are interested in real-world examples as well as cost analyses head over to the [**Case Studies** page](case-studies.md).
-
-## Maturity matrix
-
-The matrix below provides an overview of the "maturity level" for common PHP applications.
-
-This maturity level is a vague metric, however it can be useful to anticipate the effort and the limitations to expect for each scenario. While a green note doesn't mean that Bref and Lambda are silver bullets for the use case (there are no silver bullets), a red note doesn't mean this is impossible or advised against.
-
-This matrix will be updated as Bref and AWS services evolve over time.
-
-
-
-
-
Simplicity
-
Performance
-
Reliability
-
-
-
- Jobs, Cron
-
-
-
-
-
-
-
-
-
-
-
-
-
API
-
-
-
-
-
-
-
-
-
-
-
-
Website
-
-
-
-
-
-
-
-
-
-
-
-
Legacy application
-
-
-
-
-
-
-
-
-
-
-
-
-
- Is this documented and simple to achieve?
-
-
- Is performance acceptable?
-
-
- Is this scenario production-ready?
-
-
-
-
-
- Legend:
- Good use case
- Some drawbacks
- Strong limitations
-
-
-- **Jobs, Cron**
-
- Jobs, cron tasks and batch processes are very good candidates for FaaS. The scaling model of AWS Lambda can lead to very high throughput in queue processing, and the pay-per-use billing model can sometimes result in drastic costs reduction.
-
- Using Bref, it is possible to implement cron jobs and queue workers using PHP. Bref also provides integration with popular queue libraries, like Laravel Queues and Symfony Messenger.
-
-- **API**
-
- APIs run on AWS Lambda without problems. Performance is now similar to what you could expect on traditional VPS.
-
-- **Website**
-
- Websites can run on AWS Lambda. Assets can be stored in S3 and served via Cloudfront. This is documented in the ["Websites" documentation](/docs/websites.md). Performance is as good as any server.
-
-- **Legacy application**
-
- Migrating a legacy PHP application to Bref and Lambda can be a challenge. One could expect to rewrite some parts of the code to make the application fit for Lambda (or running in containers in general). For example, file uploads and sessions often need to be adapted to work with the read-only filesystem. Cron tasks, scripts or asynchronous jobs must be made compatible with Lambda and SQS.
-
- Not impossible, but definitely not the easiest place to start. As a first step, you can follow the guidelines of [The Twelve-Factor App](https://12factor.net).
-
-## Getting started
-
-Get started with Bref by reading the [installation documentation](installation.md).
diff --git a/docs/_meta.json b/docs/_meta.json
new file mode 100644
index 000000000..88a96bb6b
--- /dev/null
+++ b/docs/_meta.json
@@ -0,0 +1,41 @@
+{
+ "index": "What is Bref and serverless?",
+ "-- Getting started": {
+ "type": "separator",
+ "title": "Getting started"
+ },
+ "setup": "",
+ "laravel": "Laravel",
+ "symfony": "Symfony",
+ "default": "Other frameworks",
+ "-- How it works": {
+ "type": "separator",
+ "title": "How it works"
+ },
+ "runtimes": "PHP runtimes for Lambda",
+ "serverless-costs": "Serverless costs",
+ "-- Workflow": {
+ "type": "separator",
+ "title": "Workflow"
+ },
+ "deploy": "Deployment",
+ "local-development": "Local development",
+ "monitoring": "",
+ "-- Learn more": {
+ "type": "separator",
+ "title": "Learn more"
+ },
+ "use-cases": "Use cases",
+ "environment": "Environment",
+ "upgrading": "Upgrading",
+ "-- Resources": {
+ "type": "separator",
+ "title": "Resources"
+ },
+ "course": {
+ "title": "Serverless course",
+ "href": "https://serverless-visually-explained.com/?ref=bref-menu"
+ },
+ "community": "",
+ "case-studies": ""
+}
\ No newline at end of file
diff --git a/docs/case-studies.md b/docs/case-studies.md
index 90890eb47..900385fec 100644
--- a/docs/case-studies.md
+++ b/docs/case-studies.md
@@ -1,9 +1,9 @@
---
-title: Case studies
-current_menu: case-studies
introduction: A collection of case studies of serverless PHP applications built using Bref. Learn about performance, costs and migrations from existing projects.
---
+# Case studies
+
This page collects case studies of serverless PHP applications built with or migrated to Bref.
These help learn for real use cases about costs, performance and migration efforts.
diff --git a/docs/community.md b/docs/community.mdx
similarity index 54%
rename from docs/community.md
rename to docs/community.mdx
index da50de736..3e8f90076 100644
--- a/docs/community.md
+++ b/docs/community.mdx
@@ -1,14 +1,14 @@
----
-title: Community
-current_menu: community
-introduction: A collection of links to places where to discuss and learn about Bref.
----
+import { NextSeo } from 'next-seo';
+
+
+
+# Community
To report bugs you can head over to the [GitHub Bref repository](https://github.com/brefphp/bref).
-For support and general discussions, [open a GitHub discussion](https://github.com/brefphp/bref/discussions).
+For community support and general discussions, [open a GitHub discussion](https://github.com/brefphp/bref/discussions).
-You can also join the [Slack community](https://join.slack.com/t/brefworkspace/shared_invite/enQtNTcwMjU2NTcxNjAxLTIxYmM2MmRjMDkzYjdjYTNkMmE5NGI3YTcyZjc2ZGRjNTFmNjFmYzk5NWQ1YmVhMDkwNzExNzhjZThkZWM0ODE) to discuss Bref and exchange with the community (please open an issue if the link doesn't work).
+You can also join the [Slack community](https://bref.sh/slack) to discuss Bref and exchange with the community (please open an issue if the link doesn't work).
On Twitter, follow [@brefphp](https://twitter.com/brefphp) to get news about Bref.
@@ -24,7 +24,7 @@ You can subscribe to these newsletters to keep up to date with what's happening
- [Serverless PHP](https://serverless-php.news/)
- A monthly newsletter about serverless news related to PHP.
+ A newsletter about serverless news related to PHP.
- [Off by None](https://www.jeremydaly.com/newsletter/)
A very packed weekly newsletter about serverless news in general.
diff --git a/docs/default/_meta.json b/docs/default/_meta.json
new file mode 100644
index 000000000..857fc087f
--- /dev/null
+++ b/docs/default/_meta.json
@@ -0,0 +1,4 @@
+{
+ "getting-started": "",
+ "cli-commands": "CLI commands"
+}
\ No newline at end of file
diff --git a/docs/default/cli-commands.mdx b/docs/default/cli-commands.mdx
new file mode 100644
index 000000000..db8b8dc24
--- /dev/null
+++ b/docs/default/cli-commands.mdx
@@ -0,0 +1,28 @@
+# CLI commands
+
+We can run CLI commands and scripts on AWS Lambda by deploying a "console" function with `serverless.yml`.
+
+```yml
+functions:
+ cli:
+ handler: the-php-script-to-run.php
+ runtime: php-81-console
+```
+
+The function uses the [Console runtime](../runtimes/console.mdx).
+
+To execute the script on Lambda, run the command below:
+
+```bash
+serverless bref:cli
+```
+
+We can also pass arguments to the script:
+
+```bash
+serverless bref:cli --args="extra command line arguments and options"
+```
+
+Our script will be invoked inside AWS Lambda and the result will be printed to the console.
+
+To learn more, read [the "Console" guide](../runtimes/console.mdx).
diff --git a/docs/default/getting-started.mdx b/docs/default/getting-started.mdx
new file mode 100644
index 000000000..2948c498c
--- /dev/null
+++ b/docs/default/getting-started.mdx
@@ -0,0 +1,95 @@
+import { Cards, Card } from 'nextra/components';
+// Path relative to the copy in the `website/` folder
+import { LaravelIcon } from '../../../components/icons/LaravelIcon';
+import { SymfonyIcon } from '../../../components/icons/SymfonyIcon';
+import { NextSeo } from 'next-seo';
+
+
+
+# Getting started - Bref with any framework
+
+This guide will help you deploy your first PHP application on AWS Lambda. The instructions below can be adapted to work with any framework.
+
+If you are using Laravel or Symfony, check out the dedicated guides instead:
+
+
+ } title="Get started with Laravel" arrow="true" href="/docs/laravel/getting-started" />
+ } title="Get started with Symfony" arrow="true" href="/docs/symfony/getting-started" />
+
+
+## Setup
+
+First, **follow the [Setup guide](../setup.mdx)** to create an AWS account and install the necessary tools.
+
+Next, in an empty directory, install Bref using Composer:
+
+```bash
+composer require bref/bref
+```
+
+Make sure that the version of Bref that was installed is 1.0 or greater.
+
+Then let's start by initializing a new project by running:
+
+```bash
+vendor/bin/bref init
+```
+
+Accept all the defaults by pressing "Enter". The following files will be created in your project:
+
+- `index.php` contains the code of your application
+- `serverless.yml` contains the configuration for deploying on AWS
+
+You are free to edit `index.php`.
+
+To deploy an existing application, you can delete `index.php` and edit `serverless.yml` to point to your existing index file (for example it may be another file like `public/index.php`). You can also create the `serverless.yml` file manually:
+
+```yml filename="serverless.yml"
+service: app
+provider:
+ name: aws
+ region: us-east-1
+
+functions:
+ web:
+ handler: index.php
+ runtime: php-81-fpm
+ events:
+ - httpApi: '*'
+
+package:
+ patterns: # Exclude files from deployment
+ - '!node_modules/**'
+ - '!tests/**'
+
+plugins:
+ - ./vendor/bref/bref
+```
+
+## Deployment
+
+To deploy, run:
+
+```bash
+serverless deploy
+```
+
+Once the command finishes, it should print a URL like this one:
+
+```sh
+https://3pjp2yiw97.execute-api.us-east-1.amazonaws.com
+```
+
+Open this URL and you should see your application: `index.php` is running on Lambda!
+
+Congrats on creating your first serverless application 🎉
+
+To learn more about deployments, head over the [Deployment guide](../deploy.mdx).
+
+## Troubleshooting
+
+In case your application is showing a blank page after being deployed, [have a look at the logs](../environment/logs.md).
+
+## Website assets
+
+Have a look at the [Website guide](../use-cases/websites.mdx) to learn how to deploy a website with assets.
diff --git a/docs/deploy.md b/docs/deploy.mdx
similarity index 53%
rename from docs/deploy.md
rename to docs/deploy.mdx
index 35af31ee2..6dde9bb39 100644
--- a/docs/deploy.md
+++ b/docs/deploy.mdx
@@ -1,21 +1,24 @@
----
-title: Deployment
-current_menu: deploy
----
+import { Callout } from 'nextra/components';
-Bref recommends using [the Serverless framework](https://serverless.com/) to deploy your serverless application. This page will show you how.
+# Deployment
+
+Bref is designed out of the box to deploy using [the Serverless Framework](https://serverless.com/).
+
+Bref can also work with any other deployment tool: Terraform, CloudFormation, SAM, [AWS CDK](https://github.com/brefphp/constructs), Pulumi… However, the documentation and user experience is optimized for Serverless Framework.
## Deploying manually
-To deploy an application configured with `serverless.yml` to AWS, run:
+To deploy to AWS an application configured with `serverless.yml`, run:
```bash
serverless deploy
```
-> A `.serverless/` directory will be created. You can add it to `.gitignore`.
->
-> Want to get an overview of your deployed application? Check out the [Bref Dashboard](https://dashboard.bref.sh/?ref=bref).
+A `.serverless/` directory will be created. You can add it to `.gitignore`.
+
+
+ Want to get an overview of your deployed application? Check out the [Bref Dashboard](https://dashboard.bref.sh/?ref=bref).
+
## Deploying for production
@@ -57,7 +60,7 @@ It is possible to deploy different stages in different AWS accounts (to lock dow
## Automating deployments
-If you are using Gitlab CI, Travis CI, CircleCI or any tool of the sort you will want to automate the deployment to something like this:
+If you are using GitHub Actions, Gitlab CI, CircleCI, or any tool of the sort you will want to automate the deployment to something like this:
```bash
# Install Composer dependencies optimized for production
@@ -87,7 +90,11 @@ provider:
...
```
-> If you are a first time user, using the `us-east-1` region (the default region) is recommended for the first projects. It simplifies commands and avoids a lot of mistakes when discovering AWS.
+
+ If you are a first time user, using the `us-east-1` region (the default region) is recommended for the first projects. It simplifies commands and avoids a lot of mistakes when discovering AWS.
+
+ I mean really… I can't count how many times a command failed or an AWS page looked empty because I was in the wrong region.
+
## Deletion
@@ -97,23 +104,42 @@ To delete the whole application you can run:
serverless remove
```
+Note that this command, like `serverless deploy`, is for a specific stage. If you want to delete all stages you will have to run the command once per stage.
+
## How it works
### CloudFormation stacks
-The `serverless deploy` command will deploy everything via a **[CloudFormation](https://aws.amazon.com/cloudformation/) stack**. A stack is nothing more than a bunch of things that compose an application:
+The `serverless deploy` command will deploy everything via a **[CloudFormation](https://aws.amazon.com/cloudformation/) stack**. A "stack" is nothing more than a bunch of things that compose an application:
- lambda functions
- S3 buckets
- databases
+- etc.
Stacks make it easy to group those resources together: the whole stack is updated at once on deployments, and if you delete the stack all the resources inside are deleted together too. Clean and simple.
-All of this is great except CloudFormation configuration is complex. This is where *Serverless* helps.
+All of this is great except CloudFormation configuration is complex. This is where Serverless Framework helps.
+
+### Zero-downtime deployments
+
+CloudFormation deploys using the [blue/green deployment strategy](https://docs.aws.amazon.com/whitepapers/latest/overview-deployment-options/bluegreen-deployments.html).
+
+This means that when you deploy, a new version of your code is deployed alongside the old one. Once the new version is ready, the traffic switches to the new version. If the deployment fails at any point, the traffic stays on the old version.
+
+#### Limits to blue/green deployment
+
+As soon as you introduce **asynchronous behaviors** (e.g. background jobs with SQS, event-driven microservices…) you may have in-flight messages (SQS jobs, EventBridge events…) created by the old version of your code that will be processed by the new version of your code.
+
+Code that handles asynchronous events must be able to handle messages created by older versions of the code.
+
+#### Database migrations
+
+Zero-downtime deployments mean that database migrations must run when code is running in production. That means either before or after the deployment (traffic switch) happens, and having a DB migration strategy compatible with that.
### `serverless.yml`
-The *Serverless* framework offers a simple configuration format. This is what you are using if you use Bref. That configuration is written in your project in a `serverless.yml` file.
+Serverless Framework offers a simple configuration format. This is what you are using if you use Bref. That configuration is written in your project in a `serverless.yml` file.
You can [learn more about that configuration format here](environment/serverless-yml.md).
diff --git a/docs/deploy/_meta.json b/docs/deploy/_meta.json
new file mode 100644
index 000000000..ccbea5e52
--- /dev/null
+++ b/docs/deploy/_meta.json
@@ -0,0 +1,4 @@
+{
+ "docker": "Deploying Docker images",
+ "aws-cdk": "Deploying with AWS CDK"
+}
\ No newline at end of file
diff --git a/docs/deploy/aws-cdk.mdx b/docs/deploy/aws-cdk.mdx
new file mode 100644
index 000000000..1a3862784
--- /dev/null
+++ b/docs/deploy/aws-cdk.mdx
@@ -0,0 +1,35 @@
+import { RemoteContent } from 'nextra/data'
+import { buildDynamicMDX, buildDynamicMeta } from 'nextra/remote'
+
+export const getStaticProps = async ({ params }) => {
+ const token = process.env.GITHUB_TEST_REMOTE_MDX
+ const res = await fetch(
+ 'https://api.github.com/repos/brefphp/constructs/contents/README.md',
+ {
+ headers: {
+ Accept: 'application/vnd.github+json',
+ 'X-GitHub-Api-Version': '2022-11-28',
+ ...(token && { Authorization: `Bearer ${token}` })
+ }
+ }
+ )
+ const page = await res.json()
+ if (!page.content) {
+ throw new Error(
+ `Error while fetch data from GitHub.\n${JSON.stringify(page, null, 4)}`
+ )
+ }
+ const content = Buffer.from(page.content, 'base64').toString('utf8');
+ return {
+ props: {
+ ...(await buildDynamicMDX(content, {
+ defaultShowCopyCode: true
+ })),
+ ...(await buildDynamicMeta())
+ },
+ // Don't update the page dynamically
+ revalidate: false,
+ }
+}
+
+
diff --git a/docs/deploy/docker.mdx b/docs/deploy/docker.mdx
new file mode 100644
index 000000000..7d09a5492
--- /dev/null
+++ b/docs/deploy/docker.mdx
@@ -0,0 +1,123 @@
+import { Callout } from 'nextra/components';
+
+# Deploying Docker images
+
+
+ Are you starting with Bref? Deploy **without Docker first**. It's easier and faster. You can always switch to Docker later.
+
+ [Read the "Deployment" guide](../deploy)
+
+
+By default, Bref deploys to AWS Lambda using zip archives, which Lambda will run in an Amazon Linux environment. This is how AWS Lambda works out of the box, and it works great.
+
+However, AWS Lambda also supports **deploying and running Docker container images**.
+
+We recommend Docker **as a last resort**, as it is less practical and usually comes with slightly worse cold starts. Yes, Docker is great and probably sounds familiar, but is often not worth it on Lambda.
+
+You should consider deploying using Docker when:
+
+- Your code size is [larger than the 250MB limit when unzipped](../environment/storage.md)
+- You reached the limit of 5 Lambda layers (e.g. for extra PHP extensions)
+- You need custom binaries/resources installed locally (e.g. mysqldump, wkhtmltopdf)
+
+
+ This documentation page assumes that you have familiarized yourself with Bref first.
+
+
+## Docker Image
+
+Bref helps you deploy using Docker images by offering base images that work on AWS Lambda. Here is an example of a Dockerfile you can use:
+
+```dockerfile filename="Dockerfile"
+FROM bref/php-81-fpm:2
+
+# Copy the source code in the image
+COPY .. /var/task
+
+# Configure the handler file (the entrypoint that receives all HTTP requests)
+CMD ["public/index.php"]
+```
+
+The `CMD` instruction let us specify the entrypoint that will handle all requests. This is the equivalent of the `handler` in the `serverless.yml` file.
+
+
+ Always specify the major version of the Bref image you want to use. That avoids breaking changes when a new major version is released.
+
+ For example `bref/php-81-fpm:2` points to Bref v2.
+
+
+Bref offers the following base images:
+
+- `bref/php-xx-fpm:2`: PHP-FPM to run HTTP applications
+- `bref/php-xx-console:2`: to run PHP CLI commands
+- `bref/php-xx:2`: to run [PHP functions](../runtimes/function.mdx)
+
+### Extra PHP extensions
+
+You can enable additional PHP extensions by pulling them from [Bref Extra Extensions](https://github.com/brefphp/extra-php-extensions):
+
+```dockerfile filename="Dockerfile" {3-4}
+FROM bref/php-81-fpm:2
+
+COPY --from=bref/extra-redis-php-81:1 /opt /opt
+COPY --from=bref/extra-gmp-php-81:1 /opt /opt
+
+COPY . /var/task
+
+CMD ["public/index.php"]
+```
+
+
+ Like the Bref images, always specify the major version of the Bref Extra Extensions images: `bref/extra-*:1` points to Bref Extra Extensions v1.
+
+ Note that Bref v2 is compatible with Bref Extra Extensions v1 (yes that's confusing, sorry about that, we will fix that in Bref v3 to have matching versions).
+
+
+## Deployment
+
+The Serverless Framework supports deploying Docker images to Lambda:
+
+```yml filename="serverless.yml" {5-9,13-14}
+service: bref-with-docker
+
+provider:
+ name: aws
+ ecr:
+ images:
+ hello-world:
+ # Path to the `Dockerfile` file
+ path: ./
+
+functions:
+ hello:
+ image:
+ name: hello-world
+ events:
+ - httpApi: '*'
+```
+
+Instead of having a `handler` and a `runtime`, we'll declare an `image`. In the `provider` block, we'll declare the Docker images that we want to build and deploy.
+
+When running `serverless deploy`, the CLI will:
+
+- Build the Docker images according to their specified `path`
+- Create an AWS ECR repository called `serverless-{service}-{env}`
+- Authenticate against your ECR account
+- Push the newly built Docker image
+- Deploy the Lambda function pointing to the Docker image
+
+Note that you can create multiple images in the same `serverless.yml` file. For example, you can have one image for the HTTP handler and another image for a worker.
+
+## Filesystem
+
+Like with non-Docker deployments, the filesystem for Docker on AWS Lambda is also readonly with a limited disk space under `/tmp` for read/write.
+
+The `/tmp` folder will always be empty on cold starts. Avoid writing content to `/tmp` in your Dockerfile because that content will **not be available** for your Lambda function.
+
+[Read more about file storage in Lambda](../environment/storage.md).
+
+## Docker Registry
+
+AWS Lambda only support AWS ECR as the source location for Docker images.
+
+AWS Lambda will use the image digest as the unique identifier. This means that even if you overwrite the exact same tag on ECR, your lambda will still run the previous image code until you actually redeploy using the new image.
diff --git a/docs/environment/_meta.json b/docs/environment/_meta.json
new file mode 100644
index 000000000..e3804712a
--- /dev/null
+++ b/docs/environment/_meta.json
@@ -0,0 +1,13 @@
+{
+ "serverless-yml": "serverless.yml",
+ "variables": "Environment variables",
+ "php": "",
+ "storage": "",
+ "logs": "",
+ "database": "Databases",
+ "database-planetscale": "Databases - PlanetScale",
+ "database-public": {
+ "display": "hidden"
+ },
+ "performances": "Performance"
+}
\ No newline at end of file
diff --git a/docs/environment/custom-domains.md b/docs/environment/custom-domains.md
deleted file mode 100644
index bd41478b8..000000000
--- a/docs/environment/custom-domains.md
+++ /dev/null
@@ -1,55 +0,0 @@
----
-title: Custom domain names
-current_menu: custom-domains
-introduction: Configure custom domain names for your web applications.
----
-
-API Gateway generates random domain names for our applications:
-
-```
-https://.execute-api..amazonaws.com/
-```
-
-It is possible to replace those URLs by a custom domain.
-
-> These guides assume you already own the domain name you will want to use.
-
-## Custom domains for HTTP lambdas
-
-The first thing to do is register the domain in **ACM** (AWS Certificate Manager) to get a HTTPS certificate. This step is not optional.
-
-- open [this link](https://console.aws.amazon.com/acm/home?region=us-east-1#/wizard/) or manually go in the ACM Console and click "Request a new certificate" in the `us-east-1` region (the region used for global "edge" certificates)
-- add your domain name and click "Next"
-- choose the domain validation of your choice
- - domain validation will require you to add CNAME entries to your DNS configuration
- - email validation will require you to click a link you will receive in an email sent to `admin@your-domain.com`
-
-After validating the domain and the certificate we can now link the custom domain to our application via API Gateway.
-
-- open [API Gateway's "Custom Domain" configuration](https://console.aws.amazon.com/apigateway/main/publish/domain-names)
-- **switch to the region of your application**
-- click "Create"
-- enter your domain name, select the certificate you created above and save
-- edit the domain that was created
-- click "Configure API mappings" to add an "API mapping": select your application and the `$default` stage (or `dev` in some cases), for example:
-
- ![](custom-domains-path-mapping.png)
-- after saving the "API mappings", find the `API Gateway domain name` in the "Configurations" tab
-- create a CNAME entry in your DNS to point your domain name to this domain
-
-After waiting for the DNS change to propagate (sometimes up to several hours) your website is now accessible via your custom domain.
-
-> You can also take a look at the plugin [serverless-domain-manager](https://www.serverless.com/plugins/serverless-domain-manager).
-> It handles the custom domain creation and optionally adds the Route53 record if asked. It is still necessary to create the ACM certificate manually.
->
-> A basic implementation is proposed here : https://www.serverless.com/blog/serverless-api-gateway-domain#create-a-custom-domain-in-api-gateway
-
-
-## Custom domains for static files on S3
-
-Some applications serve static files hosted on AWS S3. You can read the [Websites](/docs/websites.md) documentation to learn more.
-
-If you want to host a fully static website with HTML files or a Single Page Application (eg. built with Vue, React or Angular)
-you may be interested in the Static Website construct of the Lift plugin.
-
-This allows to configure custom domains, root domain to `www` redirects and more. Check out the official documentation for more details.
diff --git a/docs/environment/database-planetscale.md b/docs/environment/database-planetscale.mdx
similarity index 89%
rename from docs/environment/database-planetscale.md
rename to docs/environment/database-planetscale.mdx
index ccd0284e4..f5a7c6444 100644
--- a/docs/environment/database-planetscale.md
+++ b/docs/environment/database-planetscale.mdx
@@ -1,8 +1,9 @@
----
-title: Using PlanetScale with Bref on AWS Lambda
-current_menu: database-planetscale
-introduction: Configure Bref to use a PlanetScale database in your PHP application on AWS Lambda.
----
+import { Callout } from 'nextra/components';
+import { NextSeo } from 'next-seo';
+
+
+
+# Using PlanetScale with Bref on AWS Lambda
[PlanetScale](https://planetscale.com/) is a hosted serverless MySQL database based on the Vitess engine ([learn more](https://planetscale.com/docs/concepts/what-is-planetscale)).
@@ -11,7 +12,7 @@ Amongst other features, it offers the following benefits compared to running a d
- Simple to set up: no VPC (virtual private network) to set up, no instances to configure.
- Runs [the Vitess clustering system](https://planetscale.com/blog/vitess-for-the-rest-of-us), which offers better scalability and supports a lot more concurrent connections [via built-in connection pooling](https://planetscale.com/blog/one-million-connections).
- Offers a [free database in the Hobby plan](https://planetscale.com/pricing), and paid plans are usage-based.
-- Since it does not require a VPC, we do not need to set up and pay [for a NAT Gateway](database.md#accessing-the-internet).
+- Since it does not require a VPC, we do not need to set up and pay [for a NAT Gateway](database.mdx#accessing-the-internet).
One extra feature worth mentioning is [the branching concept](https://planetscale.com/docs/concepts/branching): it enables testing schema changes before deploying them in production without downtime.
@@ -23,7 +24,9 @@ Then, create a database in the same region as your Bref application.
![](./database/planetscale-create.png)
-> The database is created with an initial development branch: `main`. PlanetScale [has a branching concept](https://planetscale.com/docs/concepts/branching) that lets you test schema changes in a development branch, then promote it to production, or even create new branches (isolated copies of the production schema) off of production to use for development.
+
+ The database is created with an initial development branch: `main`. PlanetScale [has a branching concept](https://planetscale.com/docs/concepts/branching) that lets you test schema changes in a development branch, then promote it to production, or even create new branches (isolated copies of the production schema) off of production to use for development.
+
You can now click the **Connect** button and select "Connect with: PHP (PDO)". That will let you retrieve the host, database name, user and password.
@@ -51,13 +54,15 @@ In Bref, the file is located here: `/opt/bref/ssl/cert.pem`.
## Laravel
-_This guide assumes you have already set up a Laravel application by following [the Bref documentation for Laravel](../frameworks/laravel.md)._
+
+ This guide assumes you have already set up a Laravel application by following [the Bref documentation for Laravel](../laravel/getting-started.mdx).
+
To configure Laravel to use the PlanetScale database, you need to set it up via environment variables.
If you deploy a `.env` file, set up the following variables:
-```bash
+```bash filename=".env"
DB_CONNECTION=mysql
DB_HOST=
DB_PORT=3306
@@ -70,7 +75,7 @@ MYSQL_ATTR_SSL_CA=/opt/bref/ssl/cert.pem
If you don't deploy the `.env` file, you can configure the variables in `serverless.yml`:
-```yaml
+```yml filename="serverless.yml"
provider:
# ...
environment:
@@ -82,7 +87,7 @@ provider:
MYSQL_ATTR_SSL_CA: /opt/bref/ssl/cert.pem
```
-Note that the `DB_PASSWORD` value is sensitive and can be set up as a secret via SSM. Read about [Secret variables](./variables.md#secrets) to learn more.
+Note that the `DB_PASSWORD` value is sensitive and can be set up as a secret via SSM. Read about [Secret variables](./variables.mdx#secrets) to learn more.
Don't forget to deploy the changes:
@@ -102,7 +107,9 @@ That's it! Our database is ready to use.
## Symfony
-_This guide assumes you have already set up a Symfony application by following [the Bref documentation for Symfony](../frameworks/symfony.md)._
+
+ This guide assumes you have already set up a Symfony application by following [the Bref documentation for Symfony](../symfony/getting-started.mdx).
+
First, make sure you have installed Doctrine, or [follow these docs to do so](https://symfony.com/doc/current/doctrine.html#installing-doctrine).
@@ -110,24 +117,24 @@ To configure Symfony to use the PlanetScale database, you need to set it up via
If you deploy a `.env` file, set up the following variables:
-```bash
+```bash filename=".env"
DATABASE_URL="mysql://:@:3306/?serverVersion=8.0"
```
If you don't deploy the `.env` file, you can configure the variables in `serverless.yml`:
-```yaml
+```yml filename="serverless.yml"
provider:
# ...
environment:
DATABASE_URL: ${ssm:/my-app/database-url}
```
-Note that the `DATABASE_URL` value is sensitive and can be set up as a secret via SSM. Read about [Secret variables](./variables.md#secrets) to learn more.
+Note that the `DATABASE_URL` value is sensitive and can be set up as a secret via SSM. Read about [Secret variables](./variables.mdx#secrets) to learn more.
Finally, edit the `config/packages/doctrine.yaml` configuration file to set up [the SSL connections](https://planetscale.com/docs/concepts/secure-connections):
-```yaml
+```yml filename="config/packages/doctrine.yaml" {6}
doctrine:
dbal:
url: '%env(resolve:DATABASE_URL)%'
@@ -182,14 +189,14 @@ mysqldump -u -p -h --set-gtid-purged=OFF --no-tables
Next, edit `schema.sql` to remove all foreign key constraints ([learn more](https://planetscale.com/docs/learn/operating-without-foreign-key-constraints)), for example:
-```diff
+```diff filename="schema.sql"
CREATE TABLE products (
id INT NOT NULL,
category_id INT,
PRIMARY KEY (id),
-+ KEY category_id_idx (category_id)
- KEY category_id_idx (category_id),
- CONSTRAINT `category_fk` FOREIGN KEY (category_id) REFERENCES category(id)
++ KEY category_id_idx (category_id)
);
```
@@ -220,7 +227,7 @@ If the production branch has the "Safe Migrations" feature **disabled**, you can
This strategy implies either:
-- accepting downtime on deployment, for example by using [Laravel's maintenance mode](../frameworks/laravel.md#maintenance-mode) (put the app offline, deploy, run migrations, then put the app back online)
+- accepting downtime on deployment, for example by using [Laravel's maintenance mode](../laravel/maintenance-mode.mdx) (put the app offline, deploy, run migrations, then put the app back online)
- or always writing backward-compatible DB migrations
This option works well for applications with low traffic or in early development. For high-traffic applications, using "Safe Migrations" is recommended instead.
@@ -250,7 +257,7 @@ To deploy DB migrations in production, you can work with two environments:
- A **production** environment: our application deployed in the `prod` stage and configured to use the `production` PlanetScale branch.
- A **dev** environment: our application deployed in the `dev` stage and configured to use the `development` PlanetScale branch.
-You can [deploy our applications to different stages](../deploy.md#stages) via the `--stage` option. Each stage is completely isolated from the others.
+You can [deploy our applications to different stages](../deploy.mdx#stages) via the `--stage` option. Each stage is completely isolated from the others.
```bash
# Deploy the "dev" environment:
@@ -262,7 +269,7 @@ serverless deploy --stage=prod
You want each "stage" of our application to connect to a different PlanetScale branch. You can achieve that in `serverless.yml` via [stage parameters](https://www.serverless.com/framework/docs/guides/parameters#stage-parameters):
-```yaml
+```yml filename="serverless.yml"
provider:
# ...
environment:
@@ -293,8 +300,8 @@ Now that the environments are set up, you can apply the following workflow for D
1. Deploy your code changes and migrations in the development stage.
1. Apply DB migrations in the **development** environment (drop a column, add a table, etc.):
- - If you use Laravel, run DB migrations [via the `artisan` function](../frameworks/laravel.md#laravel-artisan): `serverless bref:cli --stage=dev --args="migrate"`
- - If you use Symfony, run DB migrations [via the `console` function](../frameworks/symfony.md#console): `serverless bref:cli --stage=dev --args="doctrine:migrations:migrate"`
+ - If you use Laravel, run DB migrations [via the `artisan` function](../laravel/getting-started.mdx#laravel-artisan): `serverless bref:cli --stage=dev --args="migrate"`
+ - If you use Symfony, run DB migrations [via the `console` function](../symfony/getting-started.mdx#symfony-console): `serverless bref:cli --stage=dev --args="doctrine:migrations:migrate"`
- If you don't use any framework, run DB queries [via the `pscale` CLI](https://planetscale.com/docs/reference/planetscale-cli).
1. Test changes in the development environment to make sure everything works correctly.
1. Create a deploy request.
diff --git a/docs/environment/database-public.md b/docs/environment/database-public.md
index ac37195d0..1dbb34b0f 100644
--- a/docs/environment/database-public.md
+++ b/docs/environment/database-public.md
@@ -1,12 +1,10 @@
---
-title: Exposing a RDS database on the internet
introduction: Configure RDS to expose a RDS database publicly so that you can access it from your computer.
-previous:
- link: /docs/environment/database.html
- title: Databases
---
-[◀ Back to the "Databases" documentation](database.md).
+# Exposing a RDS database on the internet
+
+[◀ Back to the "Databases" documentation](database.mdx).
---
diff --git a/docs/environment/database.md b/docs/environment/database.mdx
similarity index 73%
rename from docs/environment/database.md
rename to docs/environment/database.mdx
index 16f0f134e..ad16fbd1f 100644
--- a/docs/environment/database.md
+++ b/docs/environment/database.mdx
@@ -1,8 +1,9 @@
----
-title: Using a database
-current_menu: database
-introduction: Configure Bref to use a database in your PHP application on AWS Lambda.
----
+import { Callout } from 'nextra/components';
+import { NextSeo } from 'next-seo';
+
+
+
+# Using a database
AWS offers the [RDS](https://aws.amazon.com/rds/) service to run MySQL and PostgreSQL databases.
@@ -13,28 +14,30 @@ Here are some of the database services offered by RDS:
- [Aurora MySQL/PostgreSQL](https://aws.amazon.com/rds/aurora/): closed-source database with MySQL/PostgreSQL compatibility
- [Aurora Serverless MySQL/PostgreSQL](https://aws.amazon.com/rds/aurora/serverless/): similar to Aurora but scales automatically on-demand
-> Aurora Serverless can be configured to scale down to 0 instances when unused (which costs $0), however be careful with this option: the database can take up to 30 seconds to un-pause.
+
+ Aurora Serverless v1 can be configured to scale down to 0 instances when unused (which costs $0), however be careful with this option: the database can take up to 30 seconds to un-pause. Aurora Serverless v2 cannot scale down to 0 instances.
+
All RDS databases can be setup with Lambda in two ways:
1. the database can be made publicly accessible and protected by a username and password
2. the database can be made inaccessible from internet by putting it in a private network (aka [VPC](https://aws.amazon.com/vpc/))
-> Note that Aurora Serverless [cannot be made publicly accessible](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless.html), only the second option is possible.
+
+ Aurora Serverless [cannot be made publicly accessible](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless.html), only the second option is possible.
+
While the first solution is simpler, the second is more secure. Using a VPC also comes with a few limitations that are detailed below.
This page documents how to create databases using VPC (the reliable and secure solution). If you want to skip using a VPC you can read the instructions in the "Accessing the database from your machine" section.
-> If you use Aurora Serverless, you can also use the [RDS Data API](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/data-api.html). SQL queries are executed through an HTTP API instead of the traditional MySQL/PostgreSQL connection. To help you, the [dbal-rds-data](https://github.com/Nemo64/dbal-rds-data) library is a Doctrine DBAL driver. Please note that the library and the API itself are new and experimental.
-
## Accessing the internet
-> ⚠️ WARNING ⚠️
->
-> If your Lambda function has **timeouts**, please read this section.
->
-> If you plan on using a database, please read this section.
+
+ If your Lambda function has **timeouts**, please read this section.
+
+ If you plan on using a database, please read this section.
+
A database inside a [VPC](https://aws.amazon.com/vpc/) is isolated from the internet. Lambda must run in the VPC to access the database, but it will lose access the internet (for example external APIs, and other AWS services).
@@ -46,9 +49,9 @@ Because of that, you may see errors like this:
> Task timed out after 28 seconds
-To restore internet access for a lambda you will need to create a NAT Gateway in the VPC: you can follow [this tutorial](https://medium.com/@philippholly/aws-lambda-enable-outgoing-internet-access-within-vpc-8dd250e11e12), use [the serverless VPC plugin](https://github.com/smoketurner/serverless-vpc-plugin), or use the complete example in [Serverless Visually Explained](https://serverless-visually-explained.com/).
+To restore internet access for a lambda you need to create a NAT Gateway in the VPC. This cannot be solved via security group or subnet configuration, only a NAT Gateway can solve this. You can follow [this tutorial](https://medium.com/@philippholly/aws-lambda-enable-outgoing-internet-access-within-vpc-8dd250e11e12), use [the serverless VPC plugin](https://github.com/smoketurner/serverless-vpc-plugin), or use the complete example in [Serverless Visually Explained](https://serverless-visually-explained.com/).
-Watch out, a NAT Gateway will increase costs (starts at $27 per month). Note that you can use one VPC and one NAT Gateway for multiple projects.
+Watch out, a NAT Gateway will increase costs (starts at $27 per month). Note that you can use one VPC and one NAT Gateway for multiple projects. To reduce costs, you can also use [a NAT instance](https://fck-nat.dev/) (starts at $3 per month).
When possible, an alternative to NAT Gateways is to split the work done by a lambda in 2 lambdas: one in the VPC that accesses the database and one outside that accesses the external API. But that's often hard to implement in practice.
@@ -56,7 +59,7 @@ Finally, another free alternative to NAT Gateway is to access AWS services by cr
## Creating a database
-On the [RDS console](https://console.aws.amazon.com/rds/home):
+In the [RDS console](https://console.aws.amazon.com/rds/home):
- click "Create database"
- select the type of database you want to create and fill in the form
@@ -72,26 +75,28 @@ Tips to better control costs:
To retrieve the information needed to let AWS Lambda access the database go into [the RDS dashboard](https://console.aws.amazon.com/rds/home#databases:) (or the [Bref Dashboard](https://dashboard.bref.sh/?ref=bref)) and open the database you created.
-> It may take some minutes for the database to be created.
+
+ It may take a few minutes for the database to be created.
+
Find:
-- the "endpoint", which is the hostname of the database (this information is available only after the database creation has completed)
+- The "endpoint", which is the hostname of the database (this information is available only after the database creation has completed)
ℹ️ Instead of connecting via a socket, via `localhost` or an IP address, PHP will connect to MySQL via this hostname.
-- the "security group ID" (in the "VPC security groups" section), which looks like `sg-03f68e1100481622b`
+- The "security group ID" (in the "VPC security groups" section), which looks like `sg-03f68e1100481622b`
ℹ️ A [security group](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html) is a firewall that restricts access to/from the VPC using "Inbound rules" and "Outbound rules".
-- the list of "subnets", which look like `subnet-12f4130e` (there are several subnets)
+- The list of "subnets", which look like `subnet-12f4130e` (there are several subnets)
ℹ️ An AWS region is divided in [availability zones](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html) (different data centers): there is usually one subnet per availability zone.
Put these information in `serverless.yml` in your function configuration ([read more about this in the Serverless documentation](https://serverless.com/framework/docs/providers/aws/guide/functions/#vpc-configuration)):
-```yaml
+```yml filename="serverless.yml"
functions:
hello:
- ...
+ # ...
vpc:
securityGroupIds:
- sg-03f68e1100481622b
@@ -117,9 +122,9 @@ For example a PDO connection string could be:
mysql://user:password@dbname.e2sctvp0nqos.us-east-1.rds.amazonaws.com/dbname
```
-To learn how to properly store this connection string in your configuration head over to the ["Secrets" section of the Variables documentation](/docs/environment/variables.md#secrets).
+To learn how to properly store this connection string in your configuration head over to the ["Secrets" section of the Variables documentation](/docs/environment/variables.mdx#secrets).
-Also refer to the [Extensions](/docs/environment/php.md#extensions) section to see if you need to enable any database-specific extensions.
+Also refer to the [Extensions](/docs/environment/php.mdx#extensions) section to see if you need to enable any database-specific extensions.
### Learn more
diff --git a/docs/environment/logs.md b/docs/environment/logs.mdx
similarity index 74%
rename from docs/environment/logs.md
rename to docs/environment/logs.mdx
index cae2783dd..6a433562b 100644
--- a/docs/environment/logs.md
+++ b/docs/environment/logs.mdx
@@ -1,10 +1,10 @@
----
-title: Logs
-current_menu: logs
-introduction: Learn how to write and read PHP logs on AWS Lambda using Bref.
----
+import { NextSeo } from 'next-seo';
-As explained in the [storage documentation](storage.md), the filesystem on AWS Lambda is:
+
+
+# Logs
+
+As explained in the [storage documentation](./storage.mdx), the filesystem on AWS Lambda is:
- read-only, except for `/tmp`
- not shared between lambda instances
@@ -26,8 +26,8 @@ That means that you don't have to configure anything to log errors, warnings or
Your application can write logs to CloudWatch:
-- [Bref for web apps](/docs/runtimes/http.md): write logs to `stderr`
-- [Bref for event-driven functions](/docs/runtimes/function.md): write logs to `stdout` (using `echo` for example) or `stderr`
+- [With the PHP-FPM runtime for web apps](../runtimes/fpm-runtime.mdx): write logs to `stderr`
+- [With the runtime for event-driven functions](../runtimes/function.mdx): write logs to `stdout` (using `echo` for example) or `stderr`
For example with [Monolog](https://github.com/Seldaek/monolog):
diff --git a/docs/environment/performances.md b/docs/environment/performances.mdx
similarity index 84%
rename from docs/environment/performances.md
rename to docs/environment/performances.mdx
index c23204e9e..48b1a09ff 100644
--- a/docs/environment/performances.md
+++ b/docs/environment/performances.mdx
@@ -1,8 +1,9 @@
----
-title: Performance
-current_menu: performances
-introduction: Performance tuning and optimizations for serverless PHP applications on AWS Lambda.
----
+import { Callout } from 'nextra/components';
+import { NextSeo } from 'next-seo';
+
+
+
+# Performance
This article sums up what to expect in terms of performance and how to optimize serverless PHP applications. The benchmarks included in this page can be reproduced via [the code on GitHub](https://github.com/brefphp/benchmarks).
@@ -18,7 +19,7 @@ From 64M to 1,792M, applications run with up to one CPU (1,792M gives 1 full CPU
To customize the amount of memory, set the `memorySize` option in `serverless.yml`:
-```yaml
+```yml filename="serverless.yml" {5}
functions:
foo:
handler: index.php
@@ -28,7 +29,7 @@ functions:
In the benchmark below, we run [PHP's official `bench.php` script](https://github.com/php/php-src/blob/master/Zend/bench.php). This script is CPU-intensive.
-| | 128M | 512M | 1024M | 2048M |
+| | 128M | 512M | 1024M | 2048M |
|------------------|------:|-----:|------:|------:|
| Execution time | 5.7s | 1.4s | 0.65s | 0.33s |
@@ -49,11 +50,11 @@ In general, **use smaller and slower lambdas only when speed is not important at
### Bref for web apps
-The [FPM runtime for web apps](/docs/runtimes/http.md) **does not add overhead to response times**.
+The [FPM runtime for web apps](../runtimes/fpm-runtime.mdx) **does not add overhead to response times**.
Here are execution times for an empty PHP application:
-| | 128M | 512M | 1024M | 2048M |
+| | 128M | 512M | 1024M | 2048M |
|------------------|------:|-----:|------:|------:|
| Execution time | 10ms | 1ms | 1ms | 1ms |
@@ -61,15 +62,15 @@ Unless we use a particularly slow lambda (see the previous section, 128M is not
We can see the same result with a "Hello world" written in Symfony (4ms being the minimum execution time of the framework):
-| | 128M | 512M | 1024M | 2048M |
+| | 128M | 512M | 1024M | 2048M |
|------------------|------:|-----:|------:|------:|
| Execution time | 58ms | 4ms | 4ms | 4ms |
### Bref for event-driven functions
-The [runtime for event-driven functions](/docs/runtimes/function.md) adds a small overhead:
+The [runtime for event-driven functions](/docs/runtimes/function.mdx) adds a small overhead:
-| | 128M | 512M | 1024M | 2048M |
+| | 128M | 512M | 1024M | 2048M |
|------------------|------:|-----:|------:|------:|
| Execution time | 175ms | 35ms | 16ms | 13ms |
@@ -78,7 +79,7 @@ Since this runtime is often used in asynchronous scenarios (for example, process
This overhead is caused by the PHP executable starting for every new invocation.
We can skip that overhead by keeping the PHP process alive:
-```yaml
+```yml filename="serverless.yml" {5}
functions:
hello:
# ...
@@ -90,7 +91,9 @@ In the example above, the PHP process will restart only every 100 invocations, r
In that case, be careful with clearing in-memory data between every event.
-> Note: the PHP process will be restarted in case of a failed invocation (PHP exception thrown in the handler).
+
+ Note: the PHP process will be restarted in case of a failed invocation (PHP exception thrown in the handler).
+
## Cold starts
@@ -104,11 +107,11 @@ On a website with low to medium traffic, you can expect cold starts to happen fo
### Optimizing cold starts
-On small websites, cold starts can be avoided by pinging the application regularly. This keeps the lambda instances warm. [Pingdom](https://www.pingdom.com/) or similar services can be used, but you can also [an automatic ping via `serverless.yml`](/docs/runtimes/http.md#cold-starts).
+On small websites, cold starts can be avoided by pinging the application regularly. This keeps the lambda instances warm. [Pingdom](https://www.pingdom.com/) or similar services can be used, but you can also [an automatic ping via `serverless.yml`](../use-cases/http/advanced-use-cases#cold-starts).
While the memory size has no impact, the codebase size can increase the cold start duration. When deploying, remember to exclude assets, images, tests and any extra file in `serverless.yml`:
-```yaml
+```yml filename="serverless.yml"
package:
patterns:
- '!assets/**'
@@ -117,8 +120,4 @@ package:
- ...
```
-Read more about this [in the serverless.yml documentation](serverless-yml.md#exclusions).
-
-> **A note on VPC cold starts**
->
-> Running a function inside a VPC used to induce a cold start of several seconds. This is no longer the case since October 2019.
+Read more about this [in the serverless.yml documentation](serverless-yml.mdx#exclusions).
diff --git a/docs/environment/php.md b/docs/environment/php.md
deleted file mode 100644
index 8256fec21..000000000
--- a/docs/environment/php.md
+++ /dev/null
@@ -1,176 +0,0 @@
----
-title: Configuring PHP
-current_menu: php
-introduction: Configure PHP versions, extensions and options for your serverless application using Bref.
----
-
-## php.ini
-
-PHP will read its configuration from:
-
-- `/opt/bref/etc/php/php.ini` (PHP's official production configuration)
-- `/opt/bref/etc/php/conf.d/bref.ini` (Bref's optimizations for Lambda)
-
-These files *cannot be customized*.
-
-### Customizing php.ini
-
-You can create your own `php.ini` to customize PHP's configuration:
-
-1. create a `php/conf.d/` subdirectory in your project
-1. create a `php.ini` file inside that directory _(the name of the file does not matter, it must have an `.ini` extension)_
-
-PHP will automatically include any `*.ini` file found in `php/conf.d/` in your project.
-
-### Customizing php.ini using a custom path
-
-If you want PHP to scan a different directory than `php/conf.d/` in your project, you can override the path by setting it in the [`PHP_INI_SCAN_DIR`](http://php.net/manual/configuration.file.php#configuration.file.scan) environment variable.
-
-> `PHP_INI_SCAN_DIR` must contain an absolute path. Since your code is placed in `/var/task` on AWS Lambda, the environment variable should contain something like `/var/task/my/different/dir`.
-
-Learn how to declare environment variables by reading the [Environment Variables](variables.md) guide.
-
-### Customizing php.ini in extra layers
-
-If you are using Lambda layers, for example to use custom PHP extensions, you can override the default `php.ini` by placing your own configuration file in `/opt/bref/etc/php/conf.d/`.
-
-Make sure to give a unique name to your `.ini` file to avoid any collision with other layers.
-
-## Extensions
-
-Bref strives to include the most common PHP extensions. If a major PHP extension is missing please open an issue to discuss it.
-
-### Extensions installed and enabled
-
-
-
-### Extensions installed but disabled by default
-
-- **[intl](http://php.net/manual/en/intro.intl.php)** - Internationalization extension (referred as Intl) is a wrapper for ICU library, enabling PHP programmers to perform various locale-aware operations.
-- **[APCu](http://php.net/manual/en/intro.apcu.php)** - APCu is APC stripped of opcode caching.
-- **[PostgreSQL PDO Driver](http://php.net/manual/en/ref.pdo-pgsql.php)** - PDO_PGSQL is a driver that implements the PHP Data Objects (PDO) interface to enable access from PHP to PostgreSQL databases.
-
-You can enable these extensions by loading them in `php/conf.d/php.ini` (as mentioned in [the section above](#phpini)), for example:
-
-```ini
-extension=intl
-extension=apcu
-extension=pdo_pgsql
-```
-
-### Extra extensions
-
-Due to space limitations in AWS Lambda, Bref runtimes cannot include every possible PHP extensions. These additional PHP extensions can be included as separate AWS Lambda layers.
-
-All extra PHP extensions are found in [brefphp/extra-php-extensions](https://github.com/brefphp/extra-php-extensions).
-
-Contributions to add more PHP extensions are welcomed.
-
-### Custom extensions
-
-It is also possible to provide your own extensions via [custom AWS Lambda layers](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html).
-
-> This guide is really raw, feel free to contribute to improve it.
-
-To create your custom layer, you will need to:
-
-- compile the extension (and any required libraries) in the same environment as AWS Lambda and Bref
-- include the compiled extension (and required libraries) in a layer
-- upload the layer to AWS Lambda
-- include the in your project
-- enable the extension in a custom `php.ini`
-
-To compile the extension, Bref provides the `bref/build-php-*` Docker images. Here is an example with Blackfire:
-
-```dockerfile
-FROM bref/build-php-80:2
-
-RUN curl -A "Docker" -o /tmp/blackfire.so -L -s "https://packages.blackfire.io/binaries/blackfire-php/1.42.0/blackfire-php-linux_amd64-php-74.so"
-
-# Build the final image from the amazon image that is close to the production environment
-FROM public.ecr.aws/lambda/provided:al2
-
-# Copy things we installed to the final image
-COPY --from=0 /tmp/blackfire.so /opt/bref-extra/blackfire.so
-```
-
-The `.so` extension file can then be retrieved in `/opt/bref-extra/blackfire.so`.
-If you installed system libraries, you may also need to copy them to the `public.ecr.aws/lambda/provided:al2`
-image.
-
-See [brefphp/extra-php-extensions](https://github.com/brefphp/extra-php-extensions)
-for more examples.
-
-## Custom vendor path
-
-Bref automatically requires vendor dependencies from the default `vendor/autoload.php` path.
-
-If your Composer dependencies are installed elsewhere, you can customize that path via the `BREF_AUTOLOAD_PATH` environment variable.
-
-```yaml
-provider:
- # ...
- environment:
- BREF_AUTOLOAD_PATH: '/var/task/foo-bar/vendor/autoload.php'
-```
-
-The path must start with `/var/task`, which is the directory where projects are installed on AWS Lambda.
diff --git a/docs/environment/php.mdx b/docs/environment/php.mdx
new file mode 100644
index 000000000..fabb6b2ad
--- /dev/null
+++ b/docs/environment/php.mdx
@@ -0,0 +1,167 @@
+import { Callout } from 'nextra/components';
+import { NextSeo } from 'next-seo';
+
+
+
+# Configuring PHP
+
+## php.ini
+
+PHP will read its configuration from:
+
+- `/opt/bref/etc/php/php.ini` (PHP's official production configuration)
+- `/opt/bref/etc/php/conf.d/bref.ini` (Bref's optimizations for Lambda)
+
+These files *cannot be customized*.
+
+### Customizing php.ini
+
+You can create your own `php.ini` to customize PHP's configuration:
+
+1. create a `php/conf.d/` subdirectory in your project
+1. create a `php.ini` file inside that directory _(the name of the file does not matter, it must have an `.ini` extension)_
+
+PHP will automatically include any `*.ini` file found in `php/conf.d/` in your project.
+
+### Customizing php.ini using a custom path
+
+If you want PHP to scan a different directory than `php/conf.d/` in your project, you can override the path by setting it in the [`PHP_INI_SCAN_DIR`](https://www.php.net/manual/en/configuration.file.php#configuration.file.scan) environment variable.
+
+
+ `PHP_INI_SCAN_DIR` must contain an absolute path. Since your code is placed in `/var/task` on AWS Lambda, the environment variable should contain something like `/var/task/my/different/dir`.
+
+
+Learn how to declare environment variables by reading the [Environment Variables](variables.md) guide.
+
+### Customizing php.ini in extra layers
+
+If you are using Lambda layers, for example to use custom PHP extensions, you can override the default `php.ini` by placing your own configuration file in `/opt/bref/etc/php/conf.d/`.
+
+Make sure to give a unique name to your `.ini` file to avoid any collision with other layers.
+
+## Extensions
+
+Bref strives to include the most common PHP extensions. If a major PHP extension is missing please open an issue to discuss it.
+
+### Built-in extensions
+
+The following extensions are installed and enabled by default in Bref runtimes:
+
+
+
+### Extensions installed but disabled by default
+
+The following extensions are installed in Bref runtimes, but disabled by default:
+
+- **[intl](https://www.php.net/manual/en/intro.intl.php)** - Internationalization extension (referred as Intl) is a wrapper for ICU library, enabling PHP programmers to perform various locale-aware operations.
+- **[APCu](https://www.php.net/manual/en/intro.apcu.php)** - APCu is APC stripped of opcode caching.
+- **[PostgreSQL PDO Driver](https://www.php.net/manual/en/ref.pdo-pgsql.php)** - PDO_PGSQL is a driver that implements the PHP Data Objects (PDO) interface to enable access from PHP to PostgreSQL databases.
+
+You can enable these extensions by loading them in `php/conf.d/php.ini` (as mentioned in [the section above](#phpini)), for example:
+
+```ini filename="php/conf.d/php.ini"
+extension=intl
+extension=apcu
+extension=pdo_pgsql
+```
+
+### Extra extensions
+
+Due to space limitations in AWS Lambda, Bref runtimes cannot include every possible PHP extensions. These additional PHP extensions can be included as separate AWS Lambda layers.
+
+All extra PHP extensions are found in [brefphp/extra-php-extensions](https://github.com/brefphp/extra-php-extensions).
+
+Contributions to add more PHP extensions are welcomed.
+
+### Custom extensions
+
+It is also possible to provide your own extensions via [custom AWS Lambda layers](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html).
+
+> This guide is really raw, feel free to contribute to improve it.
+
+To create your custom layer, you will need to:
+
+- compile the extension (and any required libraries) in the same environment as AWS Lambda and Bref
+- include the compiled extension (and required libraries) in a layer
+- upload the layer to AWS Lambda
+- include the in your project
+- enable the extension in a custom `php.ini`
+
+To compile the extension, Bref provides the `bref/build-php-*` Docker images. Here is an example with Blackfire:
+
+```dockerfile
+FROM bref/build-php-80:2
+
+RUN curl -A "Docker" -o /tmp/blackfire.so -L -s "https://packages.blackfire.io/binaries/blackfire-php/1.42.0/blackfire-php-linux_amd64-php-74.so"
+
+# Build the final image from the amazon image that is close to the production environment
+FROM public.ecr.aws/lambda/provided:al2
+
+# Copy things we installed to the final image
+COPY --from=0 /tmp/blackfire.so /opt/bref-extra/blackfire.so
+```
+
+The `.so` extension file can then be retrieved in `/opt/bref-extra/blackfire.so`.
+If you installed system libraries, you may also need to copy them to the `public.ecr.aws/lambda/provided:al2`
+image.
+
+See [brefphp/extra-php-extensions](https://github.com/brefphp/extra-php-extensions)
+for more examples.
+
+## Custom vendor path
+
+Bref automatically requires vendor dependencies from the default `vendor/autoload.php` path.
+
+If your Composer dependencies are installed elsewhere, you can customize that path via the `BREF_AUTOLOAD_PATH` environment variable.
+
+```yml filename="serverless.yml"
+provider:
+ # ...
+ environment:
+ BREF_AUTOLOAD_PATH: '/var/task/foo-bar/vendor/autoload.php'
+```
+
+The path must start with `/var/task`, which is the directory where projects are installed on AWS Lambda.
diff --git a/docs/environment/serverless-yml.md b/docs/environment/serverless-yml.mdx
similarity index 83%
rename from docs/environment/serverless-yml.md
rename to docs/environment/serverless-yml.mdx
index 6e43f952a..5e24d4061 100644
--- a/docs/environment/serverless-yml.md
+++ b/docs/environment/serverless-yml.mdx
@@ -1,16 +1,16 @@
----
-title: serverless.yml
-current_menu: serverless-yml
-introduction: Configure your application with the serverless.yml file.
----
+import { NextSeo } from 'next-seo';
+
+
+
+# serverless.yml
Your application is deployed using the Serverless framework based on the `serverless.yml` configuration file.
-This page introduces a few advanced concepts of the `serverless.yml` format. You can learn in the [official Serverless documentation](https://serverless.com/framework/docs/providers/aws/).
+This page introduces a few advanced concepts of the `serverless.yml` format. You can learn more in the [official Serverless documentation](https://serverless.com/framework/docs/providers/aws/).
## Overview
-```yaml
+```yml filename="serverless.yml"
service: app
provider:
@@ -34,24 +34,24 @@ resources:
## Service
-```yaml
+```yml
service: app
```
The [service](https://serverless.com/framework/docs/providers/aws/guide/services/) is simply the name of your project.
-Since Serverless lets us deploy a project in [multiple stages](../deploy.md#stages) (prod, dev, staging…), CloudFormation stacks will contain both the service name and the stage: `app-prod`, `app-dev`, etc.
+Since Serverless lets us deploy a project in [multiple stages](../deploy.mdx#stages) (prod, dev, staging…), CloudFormation stacks will contain both the service name and the stage: `app-prod`, `app-dev`, etc.
## Provider
-```yaml
+```yml
provider:
name: aws
```
Bref only supports the `aws` provider, even though Serverless can deploy applications on other cloud providers like Google Cloud, Azure, etc.
-```yaml
+```yml
provider:
name: aws
# The AWS region in which to deploy (us-east-1 by default)
@@ -199,20 +199,15 @@ resources:
# ...
```
-### References
-
-The CloudFormation `!Ref` syntax can be used. However the `${MyResource.Arn}` CloudFormation syntax cannot be used.
+### CloudFormation functions
-To solve this, the [serverless-pseudo-parameters plugin](https://github.com/svdgraaf/serverless-pseudo-parameters) can help. After installing it, you can reference other resources by replacing the `${...}` syntax with `#{...}` (because `${...}` is conflicting with [serverless.yml native variables](https://serverless.com/framework/docs/providers/aws/guide/variables/)).
+The CloudFormation `!Ref`, `!GetAtt` and `!Sub` functions can be used.
-Here is an example where we define a S3 bucket and a policy that references it. It uses both the `!Ref MyBucket` and `#{MyBucket.Arn}` syntaxes:
+Here is an example where we define a S3 bucket and a policy that references it. It uses both the `!Ref MyBucket` and `!Sub '${MyBucket.Arn}'` syntaxes:
-```yaml
+```yml filename="serverless.yml"
#...
-plugins:
- - serverless-pseudo-parameters
-
resources:
Resources:
MyBucket:
@@ -227,5 +222,5 @@ resources:
- Effect: Allow
Principal: '*' # everyone
Action: s3:GetObject
- Resource: '#{MyBucket.Arn}/*'
+ Resource: !Sub '${MyBucket.Arn}/*'
```
diff --git a/docs/environment/storage.md b/docs/environment/storage.mdx
similarity index 92%
rename from docs/environment/storage.md
rename to docs/environment/storage.mdx
index 564366db0..1dd0eaebb 100644
--- a/docs/environment/storage.md
+++ b/docs/environment/storage.mdx
@@ -1,8 +1,8 @@
----
-title: Storage
-current_menu: storage
-introduction: Learn how to store data and files in serverless PHP applications running on AWS Lambda.
----
+import { NextSeo } from 'next-seo';
+
+
+
+# Storage on AWS Lambda
Here is a simplified overview of the filesystem on AWS Lambda:
@@ -16,7 +16,7 @@ Here is a simplified overview of the filesystem on AWS Lambda:
...
```
-The `/var/task` directory is [limited to 250MB](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html#function-configuration-deployment-and-execution). If you hit that limit, you can deploy [via Docker images instead](../web-apps/docker.md).
+The `/var/task` directory is [limited to 250MB](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html#function-configuration-deployment-and-execution). If you hit that limit, you can deploy [via Docker images instead](../deploy/docker.mdx).
The filesystem on AWS Lambda **is read-only**, except for the `/tmp` directory.
@@ -30,13 +30,9 @@ Instead, data can be stored in [databases](/docs/environment/database.md) or in
### S3 storage
-It is possible to deploy a S3 bucket in `serverless.yml` using the `Storage` feature of the Lift plugin. For example:
-
-```yaml
-# serverless.yml
-
-# ...
+It is possible to deploy a S3 bucket in `serverless.yml` using the [`Storage` feature of the Lift plugin](https://github.com/getlift/lift/blob/master/docs/storage.md). For example:
+```yml filename="serverless.yml"
provider:
environment:
BUCKET_NAME: ${construct:reports-bucket.bucketName}
@@ -94,7 +90,7 @@ This solution is ideal for cache data that can change during the life of the app
As any service, DynamoDB tables can be deployed via CloudFormation using the `resources` key in `serverless.yml`:
-```yaml
+```yml filename="serverless.yml"
service: app
...
@@ -118,13 +114,13 @@ resources:
We need to allow code in Lambda functions to access DynamoDB.
We can also pass the table name as an environment variable to the application.
-```yaml
+```yml filename="serverless.yml"
service: app
provider:
iam:
role:
statements:
- - Effect: Allow
+ - Effect: Allow
Resource: !GetAtt CacheTable.Arn
Action:
- dynamodb:DescribeTable
diff --git a/docs/environment/variables.md b/docs/environment/variables.mdx
similarity index 88%
rename from docs/environment/variables.md
rename to docs/environment/variables.mdx
index 19ed4d31a..e76c469b2 100644
--- a/docs/environment/variables.md
+++ b/docs/environment/variables.mdx
@@ -1,8 +1,9 @@
----
-title: Environment variables
-current_menu: variables
-introduction: Define environment variables for your Bref application.
----
+import { Callout } from 'nextra/components';
+import { NextSeo } from 'next-seo';
+
+
+
+# Environment variables
Environment variables are the perfect solution to configure the application (as recommended in the [12 factor guide](https://12factor.net/config)).
@@ -12,7 +13,7 @@ Environment variables can be defined in `serverless.yml`.
To define an environment variable that will be available in **all functions** declare it in the `provider` section:
-```yaml
+```yml filename="serverless.yml"
provider:
# ...
environment:
@@ -21,7 +22,7 @@ provider:
To define an environment variable that will be available in **a specific function** declare it inside the function's properties:
-```yaml
+```yml filename="serverless.yml"
functions:
foo:
# ...
@@ -29,7 +30,9 @@ functions:
MY_VARIABLE: 'my value'
```
-> Do not store secret values in `serverless.yml` directly. Check out the next section to handle secrets.
+
+ Do not store secret values in `serverless.yml` directly. Check out the next section to handle secrets.
+
## Secrets
@@ -49,7 +52,8 @@ You can also do it in the CLI via the following command:
aws ssm put-parameter --region us-east-1 --name '/my-app/my-parameter' --type String --value 'mysecretvalue'
```
-For Windows users, the first part of the path needs to be double slashes and all subsequent forward slashes changed to backslashes:
+On Windows, the first part of the path needs to be double slashes and all subsequent forward slashes changed to backslashes:
+
```bash
aws ssm put-parameter --region us-east-1 --name '//my-app\my-parameter' --type String --value 'mysecretvalue'
```
@@ -67,7 +71,7 @@ You can inject a secret in an environment variable:
Use the [`${ssm:}` syntax](https://serverless.com/blog/serverless-secrets-api-keys/) to have the variable be replaced by the secret value on deployment:
-```yaml
+```yml filename="serverless.yml"
provider:
# ...
environment:
@@ -90,13 +94,13 @@ Disadvantages:
Alternatively, Bref can fetch the secret values at runtime when the Lambda function starts (aka the "cold start"). To use that feature, we **must install** the `bref/secrets-loader` package:
-```
+```bash
composer require bref/secrets-loader
```
To use it, the environment variable should contain the path to the SSM parameter prefixed with `bref-ssm:`. We also need to authorize Lambda to retrieve the parameter. For example:
-```yaml
+```yml filename="serverless.yml"
provider:
# ...
environment:
@@ -138,7 +142,7 @@ SSM is good enough for most projects.
## Local development
-When [developing locally using `serverless bref:local`](/docs/local-development.md), you can set environment variables using bash:
+When [developing locally using `serverless bref:local`](/docs/local-development.mdx), you can set environment variables using bash:
```bash
VAR1=val1 VAR2=val2 serverless bref:local -f
diff --git a/docs/first-steps.md b/docs/first-steps.md
deleted file mode 100644
index 8290229c2..000000000
--- a/docs/first-steps.md
+++ /dev/null
@@ -1,62 +0,0 @@
----
-title: First steps
-current_menu: first-steps
-introduction: First steps to discover Bref and deploy your first PHP application on AWS Lambda.
-previous:
- link: /docs/installation.html
- title: Installation
-next:
- link: /docs/runtimes/
- title: What are runtimes?
----
-
-This guide will help you deploy your first PHP application on AWS Lambda. For simplicity, we will not be using a PHP framework yet.
-
-Before getting started make sure you have [installed Bref and the required tools](installation.md) first.
-
-## Initializing the project
-
-Starting in an empty directory, install Bref using Composer:
-
-```
-composer require bref/bref
-```
-
-> Make sure that the version of Bref that was installed is 1.0 or greater.
-
-Then let's start by initializing the project by running:
-
-```
-vendor/bin/bref init
-```
-
-Accept all the defaults by pressing "Enter". The following files will be created in your project:
-
-- `index.php` contains the code of your application
-- `serverless.yml` contains the configuration for deploying on AWS
-
-You are free to edit the code in `index.php`, but for now let's keep it simple: we want to run `index.php` on Lambda first.
-
-## Deployment
-
-To deploy, let's run:
-
-```bash
-serverless deploy
-```
-
-Once the command finishes, it should print a URL like this one:
-
-```sh
-https://3pjp2yiw97.execute-api.us-east-1.amazonaws.com
-```
-
-Open this URL and you should see your application: `index.php` is running on Lambda!
-
-🎉 congrats on creating your first serverless application!
-
-To learn more about deployments, head over the [Deployment guide](deploy.md).
-
-## What's next?
-
-Now that you have deployed a simple PHP web app, you can [learn more about runtimes](/docs/runtimes/). That will help you deploy HTTP and console applications.
diff --git a/docs/frameworks/laravel.md b/docs/frameworks/laravel.md
deleted file mode 100644
index df3a30b6a..000000000
--- a/docs/frameworks/laravel.md
+++ /dev/null
@@ -1,443 +0,0 @@
----
-title: Serverless Laravel applications
-current_menu: laravel
-introduction: Learn how to deploy serverless Laravel applications on AWS Lambda using Bref.
----
-
-This guide helps you run Laravel applications on AWS Lambda using Bref. These instructions are kept up to date to target the latest Laravel version.
-
-A demo application is available on GitHub at [github.com/brefphp/examples](https://github.com/brefphp/examples).
-
-## Setup
-
-First, make sure you have followed the [Installation guide](../installation.md) to create an AWS account and install the necessary tools.
-
-Next, in an existing Laravel project, install Bref and the [Laravel-Bref package](https://github.com/brefphp/laravel-bridge).
-
-```
-composer require bref/bref bref/laravel-bridge --update-with-dependencies
-```
-
-Then let's create a [`serverless.yml` configuration file](https://bref.sh/docs/environment/serverless-yml.html):
-
-```
-php artisan vendor:publish --tag=serverless-config
-```
-
-### How it works
-
-By default, the Laravel-Bref package will automatically configure Laravel to work on AWS Lambda.
-
-If you are curious, the package will automatically:
-
-- enable the `stderr` log driver, to send logs to CloudWatch ([read more about logs](../environment/logs.md))
-- enable the [`cookie` session driver](https://laravel.com/docs/session#configuration) (if you prefer, you can configure sessions to be stored in database, DynamoDB or Redis)
-- move the storage directory to `/tmp` (because the default storage directory is read-only on Lambda)
-- adjust a few more settings ([have a look at the `BrefServiceProvider` for details](https://github.com/brefphp/laravel-bridge/blob/master/src/BrefServiceProvider.php))
-
-## Deployment
-
-We do not want to deploy "dev" caches that were generated on our machine (because paths will be different on AWS Lambda). Let's clear them before deploying:
-
-```bash
-php artisan config:clear
-```
-
-When running in AWS Lambda, the Laravel application will automatically cache its configuration when booting. You don't need to run `php artisan config:cache` before deploying.
-
-Let's deploy now:
-
-```bash
-serverless deploy
-```
-
-When finished, the `deploy` command will show the URL of the application.
-
-### Deploying for production
-
-At the moment, we deployed our local installation to Lambda. When deploying for production, we probably don't want to deploy:
-
-- development dependencies,
-- our local `.env` file,
-- or any other dev artifact.
-
-Follow [the deployment guide](/docs/deploy.md#deploying-for-production) for more details.
-
-## Troubleshooting
-
-In case your application is showing a blank page after being deployed, [have a look at the logs](../environment/logs.md).
-
-## Laravel Artisan
-
-As you may have noticed, we define a function named "artisan" in `serverless.yml`. That function is using the [Console runtime](/docs/runtimes/console.md), which lets us run Laravel Artisan on AWS Lambda.
-
-For example, to execute an `artisan` command on Lambda for the above configuration, run the below command.
-
-```sh
-serverless bref:cli --args=""
-```
-
-For more details follow [the "Console" guide](/docs/runtimes/console.md).
-
-## Assets
-
-To deploy Laravel websites, assets need to be served from AWS S3. The easiest approach is to use the [Server-side website construct of the Lift plugin](https://github.com/getlift/lift/blob/master/docs/server-side-website.md).
-
-This will deploy a Cloudfront distribution that will act as a proxy: it will serve static files directly from S3 and will forward everything else to Lambda. This is very close to how traditional web servers like Apache or Nginx work, which means your application doesn't need to change! For more details, read [the official documentation](https://github.com/getlift/lift/blob/master/docs/server-side-website.md#how-it-works).
-
-First install the plugin:
-
-```bash
-serverless plugin install -n serverless-lift
-```
-
-Then add this configuration to your `serverless.yml` file:
-
-```yaml
-service: laravel
-provider:
- # ...
-
-functions:
- # ...
-
-plugins:
- - ./vendor/bref/bref
- - serverless-lift
-
-constructs:
- website:
- type: server-side-website
- assets:
- '/js/*': public/js
- '/css/*': public/css
- '/favicon.ico': public/favicon.ico
- '/robots.txt': public/robots.txt
- # add here any file or directory that needs to be served from S3
-```
-
-Before deploying, compile your assets:
-
-```bash
-npm run prod
-```
-
-Now deploy your website using `serverless deploy`. Lift will create all required resources and take care of
-uploading your assets to S3 automatically.
-
-For more details, see the [Websites section](/docs/websites.md) of this documentation and the official [Lift documentation](https://github.com/getlift/lift/blob/master/docs/server-side-website.md).
-
-### Assets in templates
-
-Assets referenced in templates should be via the `asset()` helper:
-
-```html
-
-```
-
-If your templates reference some assets via direct path, you should edit them to use the `asset()` helper:
-
-```html
--
-+
-```
-
-## File storage on S3
-
-Laravel has a [filesystem abstraction](https://laravel.com/docs/filesystem) that lets us easily change where files are stored. When running on Lambda, you will need to use the `s3` adapter to store files on AWS S3.
-
-To do this, set `FILESYSTEM_DISK: s3` either in `serverless.yml` or your production `.env` file. We can also create an S3 bucket via `serverless.yml` directly:
-
-```yaml
-# ...
-provider:
- # ...
- environment:
- # environment variable for Laravel
- FILESYSTEM_DISK: s3
- AWS_BUCKET: !Ref Storage
- iam:
- role:
- statements:
- # Allow Lambda to read and write files in the S3 buckets
- - Effect: Allow
- Action: s3:*
- Resource:
- - !Sub '${Storage.Arn}' # the storage bucket
- - !Sub '${Storage.Arn}/*' # and everything inside
-
-resources:
- Resources:
- # Create our S3 storage bucket using CloudFormation
- Storage:
- Type: AWS::S3::Bucket
-```
-
-That's it! The AWS credentials (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN) are set automatically in AWS Lambda, you don't have to define them.
-
-### Public files
-
-Laravel has a [special disk called `public`](https://laravel.com/docs/filesystem#the-public-disk): this disk stores files that we want to make public, like uploaded photos, generated PDF files, etc.
-
-Again, those files cannot be stored on Lambda, i.e. they cannot be stored in the default `storage/app/public` directory. You need to store those files on S3.
-
-> Do not run `php artisan storage:link` in AWS Lambda: it is now useless, and it will fail because the filesystem is read-only in Lambda.
-
-To store public files on S3, you could replace the disk in the code:
-
-```diff
-- Storage::disk('public')->put('avatars/1', $fileContents);
-+ Storage::disk('s3')->put('avatars/1', $fileContents);
-```
-
-but doing this will not let your application work locally. A better solution, but more complex, involves making the `public` disk configurable. Let's change the configuration in `config/filesystems.php`:
-
-```diff
- /*
- |--------------------------------------------------------------------------
- | Default Public Filesystem Disk
- |--------------------------------------------------------------------------
- */
-
-+ 'public' => env('FILESYSTEM_DISK', 'public_local'),
-
- ...
-
- 'disks' => [
-
- 'local' => [
- 'driver' => 'local',
- 'root' => storage_path('app'),
- ],
-
-- 'public' => [
-+ 'public_local' => [
- 'driver' => 'local',
- 'root' => storage_path('app/public'),
- 'url' => env('APP_URL').'/storage',
- 'visibility' => 'public',
- ],
-
- 's3' => [
- 'driver' => 's3',
- 'key' => env('AWS_ACCESS_KEY_ID'),
- 'secret' => env('AWS_SECRET_ACCESS_KEY'),
- 'token' => env('AWS_SESSION_TOKEN'),
- 'region' => env('AWS_DEFAULT_REGION'),
- 'bucket' => env('AWS_BUCKET'),
- 'url' => env('AWS_URL'),
- ],
-
-+ 's3_public' => [
-+ 'driver' => 's3',
-+ 'key' => env('AWS_ACCESS_KEY_ID'),
-+ 'secret' => env('AWS_SECRET_ACCESS_KEY'),
-+ 'token' => env('AWS_SESSION_TOKEN'),
-+ 'region' => env('AWS_DEFAULT_REGION'),
-+ 'bucket' => env('AWS_PUBLIC_BUCKET'),
-+ 'url' => env('AWS_URL'),
-+ ],
-
- ],
-```
-
-You can now configure the `public` disk to use S3 by changing `serverless.yml` or your production `.env`:
-
-```dotenv
-FILESYSTEM_DISK=s3
-FILESYSTEM_DISK_PUBLIC=s3
-```
-
-## Laravel Queues
-
-To run Laravel Queues on AWS Lambda using [Amazon SQS](https://aws.amazon.com/sqs/), we don't want to run the `php artisan queue:work` command. Instead, we create a function that is invoked immediately when there are new jobs to process.
-
-To create the SQS queue (and the permissions for the Lambda functions to read/write to it), we can either do that manually, or use `serverless.yml`.
-
-To make things simpler, we will use the [Serverless Lift](https://github.com/getlift/lift) plugin to create and configure the SQS queue.
-
-First install the Lift plugin:
-
-```bash
-serverless plugin install -n serverless-lift
-```
-
-Then use the Queue construct in `serverless.yml`:
-
-```yml
-provider:
- # ...
- environment:
- # ...
- QUEUE_CONNECTION: sqs
- SQS_QUEUE: ${construct:jobs.queueUrl}
-
-functions:
- # ...
-
-constructs:
- jobs:
- type: queue
- worker:
- handler: Bref\LaravelBridge\Queue\QueueHandler
- runtime: php-81
- timeout: 60 # seconds
-```
-
-We define Laravel environment variables in `provider.environment` (this could also be done in the deployed `.env` file):
-
-- `QUEUE_CONNECTION: sqs` enables the SQS queue connection
-- `SQS_QUEUE: ${construct:jobs.queueUrl}` passes the URL of the created SQS queue
-
-If you want to create the SQS queue manually, you will need to set these variables. AWS credentials (`AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`) are automatically set up with the appropriate permissions for Laravel to use the SQS queue.
-
-That's it! Anytime a job is pushed to Laravel Queues, it will be sent to SQS, and SQS will invoke our "worker" function so that it is processed.
-
-> **Note**:
->
-> In the example above, we set the full SQS queue URL in the `SQS_QUEUE` variable.
->
-If you only set the queue name (which is also valid), you need to set the `SQS_PREFIX` environment variable too. For example: `SQS_PREFIX: "https://sqs.${aws:region}.amazonaws.com/${aws:accountId}"`.
-
-### How it works
-
-When integrated with AWS Lambda, SQS has a built-in retry mechanism and storage for failed messages. These features work slightly differently than Laravel Queues. The "Bref for Laravel" integration does **not** use these SQS features.
-
-Instead, "Bref for Laravel" makes all the feature of Laravel Queues work out of the box, just like on any server. Read more in [the Laravel Queues documentation](https://laravel.com/docs/latest/queues).
-
-> **Note:** the "Bref-Laravel bridge" v1 used to do the opposite. We changed that behavior in Bref v2 in order to make the experience smoother for Laravel users.
-
-## Laravel Octane
-
-To run the HTTP application with [Laravel Octane](https://laravel.com/docs/10.x/octane) instead of PHP-FPM, change the following options in the `web` function:
-
-```yml
-functions:
- web:
- handler: Bref\LaravelBridge\Http\OctaneHandler
- runtime: php-81
- environment:
- BREF_LOOP_MAX: 250
- # ...
-```
-
-Keep the following details in mind:
-
-- Laravel Octane does not need Swoole or RoadRunner on AWS Lambda, so it is not possible to use Swoole-specific features.
-- Octane keeps Laravel booted in a long-running process, [beware of memory leaks](https://laravel.com/docs/10.x/octane#managing-memory-leaks).
-- `BREF_LOOP_MAX` specifies the number of HTTP requests handled before the PHP process is restarted (and the memory is cleared).
-
-### Persistent database connections
-
-You can keep database connections persistent across requests to make your application even faster. To do so, set the `OCTANE_PERSIST_DATABASE_SESSIONS` environment variable:
-
-```yml
-functions:
- web:
- handler: Bref\LaravelBridge\Http\OctaneHandler
- runtime: php-81
- environment:
- BREF_LOOP_MAX: 250
- OCTANE_PERSIST_DATABASE_SESSIONS: 1
- # ...
-```
-
-Note that if you are using PostgreSQL (9.6 or newer), you need to set [`idle_in_transaction_session_timeout`](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-IDLE-IN-TRANSACTION-SESSION-TIMEOUT) either in your RDS database's parameter group, or on a specific database itself.
-
-```sql
-ALTER DATABASE SET idle_in_transaction_session_timeout = '10000' -- 10 seconds in ms
-```
-
-## Caching
-
-By default, the Bref bridge will move Laravel's storage and cache directories to `/tmp`. This is because all the filesystem except `/tmp` is read-only.
-
-Note that the `/tmp` directory isn't shared across Lambda instances. If you Lambda function scales up, the cache will be empty in new instances (or after a deployment).
-
-If you want the cache to be shared across all Lambda instances, for example if your application caches a lot of data or if you use it for locking mechanisms (like API rate limiting), you can instead use Redis or DynamoDB.
-
-DynamoDB is the easiest to set up and is "pay per use". Redis is a bit more complex as it requires a VPC and managing instances, but offers slightly faster response times.
-
-### Using DynamoDB
-
-To use DynamoDB as a cache store, change this configuration in `config/cache.php`:
-
-```diff
- # config/cache.php
- 'dynamodb' => [
- 'driver' => 'dynamodb',
- 'key' => env('AWS_ACCESS_KEY_ID'),
- 'secret' => env('AWS_SECRET_ACCESS_KEY'),
- 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
- 'table' => env('DYNAMODB_CACHE_TABLE', 'cache'),
- 'endpoint' => env('DYNAMODB_ENDPOINT'),
-+ 'attributes' => [
-+ 'key' => 'id',
-+ 'expiration' => 'ttl',
-+ ]
- ],
-```
-
-Then follow [this section of the documentation](/docs/environment/storage.md#deploying-dynamodb-tables) to deploy your DynamoDB table using the Serverless Framework.
-
-## Maintenance mode
-
-Similar to the `php artisan down` command, you may put your app into maintenance mode. All that's required is setting the `MAINTENANCE_MODE` environment variable:
-
-```yml
-provider:
- environment:
- MAINTENANCE_MODE: ${param:maintenance, null}
-```
-
-You can then deploy:
-
-```bash
-# Full deployment (goes through CloudFormation):
-serverless deploy --param="maintenance=1"
-
-# Or quick update of the functions config only:
-serverless deploy function --function=web --update-config --param="maintenance=1"
-serverless deploy function --function=artisan --update-config --param="maintenance=1"
-serverless deploy function --function= --update-config --param="maintenance=1"
-```
-
-To take your app out of maintenance mode, redeploy without the `--param="maintenance=1"` option.
-
-## Laravel Passport
-
-Laravel Passport has a `passport:install` command. However, this command cannot be run in Lambda because it needs to write files to the `storage/` directory.
-
-Instead, here is what you need to do:
-
-- Run `php artisan passport:keys` locally to generate key files.
-
- This command will generate the `storage/oauth-private.key` and `storage/oauth-public.key` files, which need to be deployed.
-
- Depending on how you deploy your application (from your machine, or from CI), you may want to whitelist them in `serverless.yml`:
-
- ```yaml
- package:
- patterns:
- - ...
- # Exclude the 'storage' directory
- - '!storage/**'
- # Except the public and private keys required by Laravel Passport
- - 'storage/oauth-private.key'
- - 'storage/oauth-public.key'
- ```
-
-- You can now deploy the application:
-
- ```yaml
- serverless deploy
- ```
-
-- Finally, you can create the tokens (which is the second part of the `passport:install` command):
-
- ```bash
- serverless bref:cli --args="passport:client --personal --name 'Laravel Personal Access Client'"
- serverless bref:cli --args="passport:client --password --name 'Laravel Personal Access Client'"
- ```
-
-All these steps were replacements of running the `passport:install` command [from the Passport documentation](https://laravel.com/docs/passport#installation).
diff --git a/docs/frameworks/symfony.md b/docs/frameworks/symfony.md
deleted file mode 100644
index 07dd65386..000000000
--- a/docs/frameworks/symfony.md
+++ /dev/null
@@ -1,247 +0,0 @@
----
-title: Serverless Symfony applications
-current_menu: symfony
-introduction: Learn how to deploy serverless Symfony applications on AWS Lambda using Bref.
----
-
-This guide helps you run Symfony applications on AWS Lambda using Bref. These instructions are kept up-to-date to be compatible with the latest Symfony version.
-
-Multiple demo applications are available on GitHub at [github.com/brefphp/examples/Symfony](https://github.com/brefphp/examples/tree/master/Symfony).
-
-## Setup
-
-First, **follow the [Installation guide](../installation.md)** to create an AWS account and install the necessary tools.
-
-Next, in an existing Symfony project, install Bref and the [Symfony Bridge package](https://github.com/brefphp/symfony-bridge).
-
-```
-composer require bref/bref bref/symfony-bridge
-```
-
-If you are using [Symfony Flex](https://flex.symfony.com/), it will automatically run
-the [bref/symfony-bridge recipe](https://github.com/symfony/recipes-contrib/tree/master/bref/symfony-bridge/0.1) which will perform the following tasks:
-
-- Create a `serverless.yml` configuration file optimized for Symfony.
-- Add the `.serverless` folder to the `.gitignore` file.
-
-> Otherwise, you can create the `serverless.yml` file manually at the root of the project. Take a look
-at the [default configuration](https://github.com/symfony/recipes-contrib/blob/master/bref/symfony-bridge/0.1/serverless.yaml) provided by the recipe.
-
-You still have a few modifications to do on the application to make it compatible with AWS Lambda.
-
-Since [the filesystem is readonly](/docs/environment/storage.md) except for `/tmp` we need to customize where the cache and logs are stored in
-the `src/Kernel.php` file. This is automatically done by the bridge, you just need to use the `BrefKernel` class instead of the default `BaseKernel`:
-
-```diff
-// src/Kernel.php
-
-namespace App;
-
-+ use Bref\SymfonyBridge\BrefKernel;
-use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
-use Symfony\Component\Config\Loader\LoaderInterface;
-use Symfony\Component\Config\Resource\FileResource;
-use Symfony\Component\DependencyInjection\ContainerBuilder;
--use Symfony\Component\HttpKernel\Kernel as BaseKernel;
-use Symfony\Component\Routing\RouteCollectionBuilder;
-
-- class Kernel extends BaseKernel
-+ class Kernel extends BrefKernel
-{
- // ...
-```
-
-## Deploy
-
-The application is now ready to be deployed. Follow [the deployment guide](/docs/deploy.md).
-
-For better performance in production, warmup the Symfony cache before deploying:
-
-```bash
-php bin/console cache:warmup --env=prod
-```
-
-## Console
-
-As you may have noticed, we define a function of type "console" in `serverless.yml`. That function is using the [Console runtime](/docs/runtimes/console.md),
-which lets us run the Symfony Console on AWS Lambda.
-
-To use it follow [the "Console" guide](/docs/runtimes/console.md).
-
-## Logs
-
-By default, Symfony logs in `stderr`. That is great because Bref [automatically forwards `stderr` to AWS CloudWatch](/docs/environment/logs.md).
-
-However, if the application is using Monolog you need to configure it to log into `stderr` as well:
-
-```yaml
-# config/packages/prod/monolog.yaml
-
-monolog:
- handlers:
- # ...
- nested:
- type: stream
- path: php://stderr
-```
-
-## Environment variables
-
-Since Symfony 4, the production parameters are configured through environment variables. You can define them in `serverless.yml`.
-
-```yaml
-# serverless.yml
-
-provider:
- environment:
- APP_ENV: prod
-```
-
-The secrets (e.g. database passwords) must however not be committed in this file.
-
-To learn more about all this, read the [environment variables documentation](/docs/environment/variables.md).
-
-## Trust API Gateway
-
-When hosting your site on Lambda, API Gateway will act as a proxy between the client and your function.
-
-By default, Symfony doesn't trust proxies for security reasons, but it's safe to do it when using API Gateway and Lambda.
-
-This is needed because otherwise, Symfony will not be able to generate URLs properly.
-
-You should add the following lines to `config/packages/framework.yaml`
-
-```yaml
-# config/packages/framework.yaml
-
-framework:
- # trust the remote address because API Gateway has no fixed IP or CIDR range that we can target
- trusted_proxies: '127.0.0.1'
- # trust "X-Forwarded-*" headers coming from API Gateway
- trusted_headers: [ 'x-forwarded-for', 'x-forwarded-proto', 'x-forwarded-port' ]
-```
-
-Note that API Gateway doesn't set the `X-Forwarded-Host` header, so we don't trust it by default. You should only whitelist this header if you set it manually,
-for example in your CloudFront configuration (this is done automatically
-in [the Cloudfront distribution deployed by Lift](#assets)).
-
-> Be careful with these settings if your app will not be executed only in a Lambda environment.
-
-You can get more details in the [Symfony documentation](https://symfony.com/doc/current/deployment/proxies.html).
-
-### Getting the user IP
-
-**When using CloudFront** on top of API Gateway, you will not be able to retrieve the client IP address, and you will instead get one of Cloudfront's IP when
-calling `Request::getClientIp()`. If you really need this, you will need to
-whitelist [every CloudFront IP](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/LocationsOfEdgeServers.html)
-in `trusted_proxies`.
-
-## Assets
-
-To deploy Symfony websites, assets need to be served from AWS S3. The easiest approach is to use the
-Server-side website construct of the Lift plugin.
-
-This will deploy a Cloudfront distribution that will act as a proxy: it will serve
-static files directly from S3 and will forward everything else to Lambda. This is very close
-to how traditional web servers like Apache or Nginx work, which means your application doesn't need to change!
-For more details, see the official documentation.
-
-First install the plugin
-
-```bash
-serverless plugin install -n serverless-lift
-```
-
-Then add this configuration to your `serverless.yml` file.
-
-```yaml
-...
-service: symfony
-
-provider:
- ...
-
-plugins:
- - ./vendor/bref/bref
- - serverless-lift
-
-functions:
- ...
-
-constructs:
- website:
- type: server-side-website
- assets:
- '/bundles/*': public/bundles
- '/build/*': public/build
- '/favicon.ico': public/favicon.ico
- '/robots.txt': public/robots.txt
- # add here any file or directory that needs to be served from S3
-```
-
-Because this construct sets the `X-Forwarded-Host` header by default, you should add it in your `trusted_headers` config, otherwise Symfony
-might generate wrong URLs.
-
-```diff
-# config/packages/framework.yaml
-
-- trusted_headers: [ 'x-forwarded-for', 'x-forwarded-proto', 'x-forwarded-port' ]
-+ trusted_headers: [ 'x-forwarded-for', 'x-forwarded-proto', 'x-forwarded-port', 'x-forwarded-host' ]
-```
-
-Then, you can compile assets for production in the `public` directory
-
-```bash
-php bin/console assets:install --env prod
-# if using Webpack Encore, additionally run
-yarn encore production
-```
-
-Now run `serverless deploy`, Lift will automatically create the S3 bucket, a Cloudfront distribution and
-upload all specified files and directories to the bucket.
-
-> If you are not using Flex, update the `serverless.yml` file to exclude assets from the deployment ([see the recipe](https://github.com/symfony/recipes-contrib/blob/master/bref/symfony-bridge/0.1/serverless.yaml#L35))
-
-For more details, see the [Websites section](/docs/websites.md) of this documentation
-and the official Lift documentation.
-
-### Assets in templates
-
-For the above configuration to work, assets must be referenced in templates via the `asset()` helper as [recommended by Symfony](https://symfony.com/doc/current/templates.html#linking-to-css-javascript-and-image-assets):
-
-```diff
--
-+
-```
-
-## Symfony Messenger
-
-It is possible to run Symfony Messenger workers on AWS Lambda.
-
-A dedicated Bref package is available for this: [bref/symfony-messenger](https://github.com/brefphp/symfony-messenger).
-
-## Caching
-
-As mentioned above the filesystem is readonly, so if you need a persistent cache it must be stored somewhere else (such as Redis, an RDBMS, or DynamoDB).
-
-### Using DynamoDB for cache
-
-A Symfony bundle is available to use AWS DynamoDB as cache store: [rikudou/psr6-dynamo-db-bundle](https://github.com/RikudouSage/DynamoDbCachePsr6Bundle)
-
-First install the bundle
-
-```bash
-composer require rikudou/psr6-dynamo-db-bundle
-```
-
-Thanks to Symfony Flex, the bundle comes pre-configured to run in Lambda.
-
-Now, you can follow [this section of the documentation](/docs/environment/storage.md#deploying-dynamodb-tables) to deploy your DynamoDB table using the Serverless Framework.
-
-## The `kernel.terminate` Event
-
-The [`kernel.terminate` event](https://symfony.com/doc/current/components/http_kernel.html#component-http-kernel-kernel-terminate) runs **synchronously** on Lambda.
-
-That means that if you use this event, its listeners will be executed **before** the Lambda function returns its response. That will add latency to your response.
-
-To run asynchronous tasks, use the [Messenger component](#symfony-messenger) instead.
diff --git a/docs/function/cron.md b/docs/function/cron.md
deleted file mode 100644
index 8404b3118..000000000
--- a/docs/function/cron.md
+++ /dev/null
@@ -1,47 +0,0 @@
----
-title: Cron functions on AWS Lambda
-current_menu: cron-function
-introduction: Learn how to create serverless cron functions with PHP on AWS Lambda.
-previous:
- link: /docs/function/local-development.html
- title: Local development
----
-
-AWS Lambda lets us run [PHP functions](/docs/runtimes/function.md) as cron tasks using the `schedule` event:
-
-```yaml
-functions:
- console:
- handler: function.php
- runtime: php-81
- events:
- - schedule: rate(1 hour)
-```
-
-The example above will run the function returned by `function.php` every hour in AWS Lambda. For example:
-
-```php
- If you are interested in **cron CLI commands** instead, read the [Cron commands](/docs/web-apps/cron.html) documentation.
diff --git a/docs/function/handlers.md b/docs/function/handlers.md
deleted file mode 100644
index 891c4168e..000000000
--- a/docs/function/handlers.md
+++ /dev/null
@@ -1,458 +0,0 @@
----
-title: Typed PHP Lambda handlers
-current_menu: typed-handlers
-introduction: Handle AWS Lambda events using typed PHP classes.
-previous:
- link: /docs/runtimes/function.html
- title: PHP functions on AWS Lambda
-next:
- link: /docs/function/local-development.html
- title: Local development
----
-
-Handling Lambda events via an anonymous function is the simplest approach:
-
-```php
-return function ($event) {
- return 'Hello ' . $event['name'];
-};
-```
-
-However, Bref also provides classes specific to each Lambda event for a better development experience.
-
-Here is an example using the base `Handler` class, that can handle events of any type:
-
-```php
-getRecords()[0]->getBucket()->getName();
- $fileName = $event->getRecords()[0]->getObject()->getKey();
-
- // do something with the file
- }
-}
-
-return new Handler();
-```
-
-For example, the class can be called whenever a new file is uploaded to S3:
-
-```yaml
-# ...
-
-functions:
- resizeImage:
- handler: handler.php
- events:
- - s3: photos
-```
-
-[Full reference of S3 in `serverless.yml`](https://www.serverless.com/framework/docs/providers/aws/events/s3/).
-
-## SQS events
-
-`SqsHandler` instances handle [SQS events](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html):
-
-```php
-getRecords() as $record) {
- // We can retrieve the message body of each record via `->getBody()`
- $body = $record->getBody();
-
- // do something
- }
- }
-}
-
-return new Handler();
-```
-
-### Partial Batch Response
-
-While handling a batch of records, you can mark it as partially successful to reprocess only the failed records.
-
-In your function declaration in `serverless.yml`, set `functionResponseType` to `ReportBatchItemFailures` to let your function return a partial success result if one or more messages in the batch have failed.
-
-```yaml
-functions:
- worker:
- handler: handler.php
- events:
- - sqs:
- arn: arn:aws:sqs:eu-west-1:111111111111:queue-name
- batchSize: 100
- functionResponseType: ReportBatchItemFailures
-```
-
-In your PHP code, you can now use the `markAsFailed` method:
-
-```php
- public function handleSqs(SqsEvent $event, Context $context): void
- {
- foreach ($event->getRecords() as $record) {
- // do something
-
- // if something went wrong, mark the record as failed
- $this->markAsFailed($record);
- }
- }
-```
-
-### Lift Queue Construct
-
-It is possible to deploy a preconfigured SQS queue in `serverless.yml` using the `Queue` feature of the Lift plugin. For example:
-
-```yaml
-# serverless.yml
-# ...
-
-constructs:
- my-queue:
- type: queue
- worker:
- handler: handler.php
-```
-
-Read more:
-
-- Deploying SQS queues with Lift
-- [Full reference of SQS in `serverless.yml`](https://www.serverless.com/framework/docs/providers/aws/events/sqs/)
-- Learn more about SQS and workers in [Serverless Visually Explained](https://serverless-visually-explained.com/)
-
-## API Gateway HTTP events
-
-**Reminder:** to create HTTP applications, it is possible to use the more traditional "[Bref for web apps](/docs/runtimes/http.md)" runtime, which runs with PHP-FPM.
-
-That being said, it is possible to handle HTTP events from API Gateway with a simple PHP class, like other handlers detailed in this page.
-
-Here is a full comparison between both approaches:
-
-| | Bref for web apps | HTTP handler class |
-|----------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------|
-| What are the use cases? | To build websites, APIs, etc. This should be the **default approach** as it's compatible with mature PHP frameworks and tools. | Build a small website, API, webhook with very little code and no framework. |
-| Why does that solution exist? | For out-of-the-box compatibility with frameworks like Symfony and Laravel. | To match how other languages run in AWS Lambda, as recommended by AWS. |
-| How is it executed? | Using PHP-FPM. | Using the PHP CLI. |
-| What does the routing (i.e. separate pages)? | Your PHP framework (one Lambda receives all the URLs). | API Gateway: we define one Lambda and one handler class per route. |
-| How to read the request? | `$_GET`, `$_POST`, etc. | The `$request` parameter (PSR-7 request). |
-| How to write a response? | `echo`, `header()` function, etc. | Returning a PSR-7 response from the handler class. |
-| How does it work? | Bref turns an API Gateway event into a FastCGI (PHP-FPM) request. | Bref turns an API Gateway event into a PSR-7 request. |
-| Is each request handled in a separate PHP process? | Yes (that's how PHP-FPM works). | Yes (Bref explicitly replicates that to avoid surprises, but that can be customized). |
-
-To create an HTTP handler class, Bref natively supports the [PSR-15](https://www.php-fig.org/psr/psr-15/#2-interfaces) and [PSR-7](https://www.php-fig.org/psr/psr-7/) standards:
-
-```php
-getQueryParams()['name'] ?? 'world';
-
- return new Response(200, [], "Hello $name");
- }
-}
-
-return new HttpHandler();
-```
-
-Since a handler is a controller for a specific route, we can use API Gateway's routing to deploy multiple Lambda functions:
-
-```yaml
-functions:
- create-article:
- handler: create-article-handler.php
- runtime: php-81
- events:
- - httpApi: 'POST /articles'
- get-article:
- handler: get-article-handler.php
- runtime: php-81
- events:
- - httpApi: 'GET /articles/{id}'
-```
-
-Note that path parameters (e.g. `{id}` in the example above) are available as request attributes in the PSR-7 request:
-
-```php
-$id = $request->getAttribute('id');
-```
-
-[Full reference of HTTP events in `serverless.yml`](https://www.serverless.com/framework/docs/providers/aws/events/http-api/).
-
-### Lambda event and context
-
-The API Gateway event and Lambda context are available as attributes on the request:
-```php
-/** @var $event Bref\Event\Http\HttpRequestEvent */
-$event = $request->getAttribute('lambda-event');
-
-/** @var $context Bref\Context\Context */
-$context = $request->getAttribute('lambda-context');
-```
-
-If you're looking for the request context array, for example when using a [Lambda authorizer](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-lambda-authorizer.html#http-api-lambda-authorizer.payload-format-response):
-```php
-$requestContext = $request->getAttribute('lambda-event')->getRequestContext();
-```
-
-## Websocket events
-
-`WebsocketHandler` instances handle Websocket events:
-
-```php
-getRouteKey();
- $eventType = $event->getEventType();
- $body = $event->getBody();
-
- return new HttpResponse('ok');
- }
-}
-
-return new Handler();
-```
-
-[Full reference for Websockets in `serverless.yml`](https://www.serverless.com/framework/docs/providers/aws/events/websocket/).
-
-A complete WebSocket example is available in [Serverless Visually Explained](https://serverless-visually-explained.com/).
-
-## EventBridge events
-
-`EventBridgeHandler` instances handle EventBridge events:
-
-```php
-getDetail()`
- $message = $event->getDetail();
-
- // do something
- }
-}
-
-return new Handler();
-```
-
-You can read more about messaging with EventBridge in [Serverless Visually Explained](https://serverless-visually-explained.com/).
-
-[Full reference of EventBridge in `serverless.yml`](https://www.serverless.com/framework/docs/providers/aws/events/event-bridge/).
-
-## SNS events
-
-`SnsHandler` instances handle [SNS events](https://docs.aws.amazon.com/lambda/latest/dg/with-sns.html):
-
-```php
-getRecords() as $record) {
- $message = $record->getMessage();
-
- // do something
- }
- }
-}
-
-return new Handler();
-```
-
-[Full reference of SNS in `serverless.yml`](https://www.serverless.com/framework/docs/providers/aws/events/sns/).
-
-## DynamoDB events
-
-`DynamoDbHandler` instances handle [DynamoDB events](https://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html):
-
-```php
-getRecords() as $record) {
- $keys = $record->getKeys();
- $old = $record->getOldImage();
- $new = $record->getNewImage();
-
- // do something
- }
- }
-}
-
-return new Handler();
-```
-
-[Full reference of DynamoDB in `serverless.yml`](https://www.serverless.com/framework/docs/providers/aws/events/streams/).
-
-## Kinesis events
-
-`KinesisHandler` instances handle [Kinesis events](https://docs.aws.amazon.com/lambda/latest/dg/with-kinesis.html):
-
-```php
-getRecords() as $record) {
- $data = $record->getData();
-
- // do something
- }
- }
-}
-
-return new Handler();
-```
-
-[Full reference of Kinesis in `serverless.yml`](https://www.serverless.com/framework/docs/providers/aws/events/streams/).
-
-## Kafka events
-
-`KafkaHandler` instances handle [Kafka events](https://docs.aws.amazon.com/lambda/latest/dg/with-kafka.html):
-
-```php
-getRecords() as $record) {
- $data = $record->getValue();
-
- // do something
- }
- }
-}
-
-return new Handler();
-```
diff --git a/docs/index.mdx b/docs/index.mdx
new file mode 100644
index 000000000..a18722df4
--- /dev/null
+++ b/docs/index.mdx
@@ -0,0 +1,220 @@
+import { NextSeo } from 'next-seo';
+
+
+
+# What is Bref and serverless?
+
+Serverless means using cloud services that manage the servers for us.
+
+## Why serverless?
+
+When running PHP on a server, we must:
+
+- setup, configure and maintain that server,
+- pay a fixed price for the server,
+- scale the server(s) if we get more traffic.
+
+When running PHP serverless:
+
+- We do not need to set up servers, the cloud provider takes care of that.
+- We pay only for what we use (per request).
+- Our application scales automatically.
+
+**Serverless provides more scalable, affordable and reliable architectures for less effort.**
+
+Serverless includes services like storage as a service, database as a service, message queue as a service, etc. One service in particular is interesting for us developers: *Function as a Service* (FaaS).
+
+FaaS is a way to run code where the hosting provider takes care of setting up everything, keeping the application available 24/7, scaling it up and down and we are only charged *while the code is actually executing*.
+
+## Why Bref?
+
+Bref aims to make running PHP applications simple.
+
+To reach that goal, Bref takes advantage of serverless technologies. However, while serverless is promising, there are many choices to make, tools to build and best practices to figure out.
+
+Bref's approach is to:
+
+- **simplify problems by removing choices**
+
+ *instead of trying to address every need*
+- **provide simple and familiar solutions**
+
+ *instead of aiming for powerful custom solutions*
+- **empower by sharing knowledge**
+
+ *instead of hiding too much behind leaky abstractions*
+
+### What is Bref
+
+Bref (which means "brief" in french) comes as an open source Composer package and helps you deploy PHP applications to [AWS](https://aws.amazon.com) and run them on [AWS Lambda](https://aws.amazon.com/lambda/).
+
+Bref provides:
+
+- documentation
+- PHP runtimes for AWS Lambda
+- deployment tooling
+- PHP frameworks integration
+
+The choice of AWS as serverless provider is deliberate: at the moment AWS is the leading hosting provider, it is ahead in the serverless space in terms of features, performance and reliability.
+
+Bref uses [the Serverless framework](https://serverless.com/) to configure and deploy serverless applications. Being the most popular tool, Serverless comes with a huge community, a lot of examples online and a simple configuration format.
+
+## Use cases
+
+Bref and AWS Lambda can be used to run many kind of PHP application, for example:
+
+- APIs
+- websites
+- workers
+- batch processes/scripts
+- event-driven microservices
+
+Bref aims to support any PHP framework. It comes with deep integrations with Laravel and Symfony.
+
+If you are interested in real-world examples as well as cost analyses head over to the [**Case Studies** page](/docs/case-studies.md).
+
+## Maturity matrix
+
+The matrix below provides an overview of the "maturity level" for common PHP applications.
+
+This maturity level is a vague metric, however it can be useful to anticipate the effort and the limitations to expect for each scenario. While a green note doesn't mean that Bref and Lambda are silver bullets for the use case (there are no silver bullets), a red note doesn't mean this is impossible or advised against.
+
+This matrix will be updated as Bref and AWS services evolve over time.
+
+
+
+
+
+
Simplicity
+
Performance
+
Reliability
+
+
+
+
+
+ Jobs, Cron
+
+
+
+
+
+
+
+
+
+
+
+
+
API
+
+
+
+
+
+
+
+
+
+
+
+
Website
+
+
+
+
+
+
+
+
+
+
+
+
Legacy application
+
+
+
+
+
+
+
+
+
+
+
+
Event-driven microservices
+
+
+
+
+
+
+
+
+
+
+
+
Real-time applications
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Is this documented and simple to achieve?
+
+
+ Is performance acceptable?
+
+
+ Is this scenario production-ready?
+
+
+
+
+
+
+ Legend:
+ Good use case
+ Some drawbacks
+ Strong limitations
+
+
+- **Jobs, Cron**
+
+ Jobs, cron tasks and batch processes are very good candidates for FaaS. The scaling model of AWS Lambda can lead to very high throughput in queue processing, and the pay-per-use billing model can sometimes result in drastic costs reduction.
+
+ Using Bref, it is possible to implement cron jobs and queue workers using PHP. Bref also provides integration with popular queue libraries, like Laravel Queues and Symfony Messenger.
+
+ One limitation to keep in mind is that each AWS Lambda invocation has a maximum execution time of 15 minutes.
+
+- **API**
+
+ APIs run on AWS Lambda without problems. Performance is now similar to what you could expect on a traditional VPS.
+
+ The main difference to account for is that about 0.5% of HTTP requests are cold starts. If your use case requires that _all_ requests are handled below 10ms, serverless might not be a good fit.
+
+- **Website**
+
+ Websites run well on AWS Lambda. Assets can be stored in S3 and served via Cloudfront. This is documented in the ["Websites" documentation](/docs/use-cases/websites.mdx). Performance is as good as any server.
+
+- **Legacy application**
+
+ Migrating a legacy PHP application to Bref and Lambda can be a challenge. One could expect to rewrite some parts of the code to make the application fit for Lambda (or running in containers in general). For example, file uploads and sessions often need to be adapted to work with the read-only filesystem. Cron tasks, scripts or asynchronous jobs must be made compatible with Lambda and SQS.
+
+ Not impossible, but definitely not the easiest place to start. As a first step, you can follow the guidelines of [The Twelve-Factor App](https://12factor.net). Note that if your application already runs redundantly on multiple servers, it is much more ready for AWS Lambda and the migration could be simple.
+
+- **Real-time applications**
+
+ Warm Lambda invocations are very fast (can be as low as 1ms), but cold starts can take 230ms or more. Cold starts are rare on most applications (less than 0.5% of invocations) and can be further mitigated with [provisioned concurrency](https://docs.aws.amazon.com/lambda/latest/dg/provisioned-concurrency.html), but it's unlikely to ensure they will _never_ happen. This makes Lambda a poor choice for real-time applications where latency must be below 100ms for 100% of requests.
+
+## Getting started
+
+Get started with Bref by reading the [installation documentation](/docs/setup.mdx).
diff --git a/docs/installation.md b/docs/installation.md
deleted file mode 100644
index 4c6d02096..000000000
--- a/docs/installation.md
+++ /dev/null
@@ -1,59 +0,0 @@
----
-title: Installation
-current_menu: installation
-introduction: How to install Bref and the required tools.
-previous:
- link: /docs/
- title: What is Bref and serverless?
-next:
- link: /docs/first-steps.html
- title: First steps
----
-
-To set up Bref correctly please complete all the sections below.
-
-## AWS account
-
-You will need an AWS account. To create one, go to [aws.amazon.com](https://aws.amazon.com/) and click *Sign up*.
-
-AWS has a generous free tier that will usually allow you to deploy your first test applications for free.
-
-## Serverless
-
-Bref relies on the [Serverless framework](https://serverless.com/) and AWS access keys to deploy applications. You will need to:
-
-- install the `serverless` command ([more details here](https://serverless.com/framework/docs/providers/aws/guide/quick-start/)):
-
- ```bash
- npm install -g serverless
- ```
-
- _Bref is compatible with Serverless Framework v3 (current version)._
-
-- [create AWS access keys](/docs/installation/aws-keys.md)
-
-- setup those keys by running:
-
- ```bash
- serverless config credentials --provider aws --key --secret
- ```
-
- If you already use the `aws` CLI command, or if you want to use environment variables instead (for example for a shared server like a CI) you can [read the full guide](https://serverless.com/framework/docs/providers/aws/guide/credentials#using-aws-access-keys).
-
-## Bref
-
-Install Bref in your project using [Composer](https://getcomposer.org/):
-
-```
-composer require bref/bref
-```
-
-> Make sure that the version of Bref that was installed is 2.0 or greater.
-
-> To run the latest version of Bref you must have PHP 8.0 or greater! If you are using PHP 7.4 or less, an outdated version of Bref will be installed instead.
-
-The `bref` command line tool can now be used by running `vendor/bin/bref` in your project.
-
-## What's next?
-
-Read the [first steps](/docs/first-steps.md) guide to create and deploy your first serverless application using Bref.
diff --git a/docs/installation/aws-keys.md b/docs/installation/aws-keys.md
deleted file mode 100644
index 597c4833f..000000000
--- a/docs/installation/aws-keys.md
+++ /dev/null
@@ -1,40 +0,0 @@
----
-title: Creating AWS access keys
-introduction: How to create AWS access keys for Bref.
----
-
-To create AWS access key for Bref and the `serverless` CLI tool follow these steps:
-
-1. In the AWS dashboard, go into IAM and create a new user: [**click here** for a direct link](https://us-east-1.console.aws.amazon.com/iamv2/home#/users/create).
-
-1. Set a user name (for example "bref-cli") and move to the next screen.
-
- ![](aws-keys-step-1.png)
-
-1. Click **Attach policies directly**, search for **AdministratorAccess** and select it.
-
- ![](aws-keys-step-2.png)
-
- > **Warning**: the "AdministratorAccess" policy grants full access to your AWS account. This is simpler when starting with AWS and Bref. However, it is recommended to restrict permissions further eventually.
- >
- > The Serverless documentation has an example of a configuration with stricter permissions: [read this article to create a more secure policy](https://serverless.com/framework/docs/providers/aws/guide/credentials/#creating-aws-access-keys).
-
-1. Finish creating the user.
-
-1. Once your user is created, select it and go to **Security credentials**.
-
- ![](aws-keys-step-3.png)
-
-1. Scroll down to **Access Keys** and click on **Create access key**.
-
- ![](aws-keys-step-4.png)
-
-1. Then select **Command Line Interface**.
-
- ![](aws-keys-step-5.png)
-
-1. Add a description to your access keys and click on **Create access key**.
-
- ![](aws-keys-step-6.png)
-
-[< Back to the installation guide](/docs/installation.md)
diff --git a/docs/laravel/_meta.json b/docs/laravel/_meta.json
new file mode 100644
index 000000000..3b790a914
--- /dev/null
+++ b/docs/laravel/_meta.json
@@ -0,0 +1,7 @@
+{
+ "getting-started": "Getting started",
+ "file-storage": "",
+ "queues": "Laravel Queues",
+ "octane": "Laravel Octane",
+ "passport": "Laravel Passport"
+}
\ No newline at end of file
diff --git a/docs/laravel/caching.mdx b/docs/laravel/caching.mdx
new file mode 100644
index 000000000..245a387c6
--- /dev/null
+++ b/docs/laravel/caching.mdx
@@ -0,0 +1,30 @@
+# Caching
+
+By default, the Bref bridge will move Laravel's storage and cache directories to `/tmp`. This is because all the filesystem except `/tmp` is read-only.
+
+However, the `/tmp` directory isn't shared across Lambda instances. If you Lambda function scales up or is redeployed, the cache will be empty in new instances.
+
+If you want the cache to be shared across all Lambda instances, for example if your application caches a lot of data or if you use it for locking mechanisms (like API rate limiting), you can instead use Redis or DynamoDB.
+
+DynamoDB is the easiest to set up and is "pay per use". Redis is a bit more complex as it requires a VPC and managing instances, but offers slightly faster response times.
+
+## DynamoDB Cache
+
+To use DynamoDB as a cache store, set the following lines in `config/cache.php`:
+
+```php filename="config/cache.php" {8-11}
+ 'dynamodb' => [
+ 'driver' => 'dynamodb',
+ 'key' => env('AWS_ACCESS_KEY_ID'),
+ 'secret' => env('AWS_SECRET_ACCESS_KEY'),
+ 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
+ 'table' => env('DYNAMODB_CACHE_TABLE', 'cache'),
+ 'endpoint' => env('DYNAMODB_ENDPOINT'),
+ 'attributes' => [
+ 'key' => 'id',
+ 'expiration' => 'ttl',
+ ]
+ ],
+```
+
+Then follow [this section of the documentation](/docs/environment/storage.md#deploying-dynamodb-tables) to deploy your DynamoDB table using the Serverless Framework.
diff --git a/docs/laravel/file-storage.mdx b/docs/laravel/file-storage.mdx
new file mode 100644
index 000000000..d76792e3d
--- /dev/null
+++ b/docs/laravel/file-storage.mdx
@@ -0,0 +1,110 @@
+import { Callout } from 'nextra/components';
+
+# File storage
+
+Laravel has a [filesystem abstraction](https://laravel.com/docs/filesystem) that lets us easily change where files are stored.
+
+When running on Lambda, you will need to use the **`s3` adapter** to store files on AWS S3.
+
+To do this, set `FILESYSTEM_DISK: s3` either in `serverless.yml` or your production `.env` file. We can also create an S3 bucket via `serverless.yml` directly:
+
+```yaml filename="serverless.yml"
+# ...
+provider:
+ # ...
+ environment:
+ # environment variable for Laravel
+ FILESYSTEM_DISK: s3
+ AWS_BUCKET: !Ref Storage
+ iam:
+ role:
+ statements:
+ # Allow Lambda to read and write files in the S3 buckets
+ - Effect: Allow
+ Action: s3:*
+ Resource:
+ - !Sub '${Storage.Arn}' # the storage bucket
+ - !Sub '${Storage.Arn}/*' # and everything inside
+
+resources:
+ Resources:
+ # Create our S3 storage bucket using CloudFormation
+ Storage:
+ Type: AWS::S3::Bucket
+```
+
+That's it! The AWS credentials (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN) are set automatically in AWS Lambda, you don't have to define them.
+
+## Public files
+
+Laravel has a [special disk called `public`](https://laravel.com/docs/filesystem#the-public-disk): this disk stores files that we want to make public, like uploaded photos, generated PDF files, etc.
+
+Again, those files cannot be stored on Lambda, i.e. they cannot be stored in the default `storage/app/public` directory. You need to store those files on S3.
+
+
+ Do not run `php artisan storage:link` in AWS Lambda: it is now useless, and it will fail because the filesystem is read-only in Lambda.
+
+
+To store public files on S3, you could replace the disk in the code:
+
+```diff
+- Storage::disk('public')->put('avatars/1', $fileContents);
++ Storage::disk('s3')->put('avatars/1', $fileContents);
+```
+
+but doing this will not let your application work locally. A better solution, but more complex, involves making the `public` disk configurable. Let's change the following lines in `config/filesystems.php`:
+
+```php filename="config/filesystems.php" {7,18,35-43}
+ /*
+ |--------------------------------------------------------------------------
+ | Default Public Filesystem Disk
+ |--------------------------------------------------------------------------
+ */
+
+ 'public' => env('FILESYSTEM_DISK', 'public_local'),
+
+ ...
+
+ 'disks' => [
+
+ 'local' => [
+ 'driver' => 'local',
+ 'root' => storage_path('app'),
+ ],
+
+ 'public_local' => [ // Rename `public` to `public_local`
+ 'driver' => 'local',
+ 'root' => storage_path('app/public'),
+ 'url' => env('APP_URL').'/storage',
+ 'visibility' => 'public',
+ ],
+
+ 's3' => [
+ 'driver' => 's3',
+ 'key' => env('AWS_ACCESS_KEY_ID'),
+ 'secret' => env('AWS_SECRET_ACCESS_KEY'),
+ 'token' => env('AWS_SESSION_TOKEN'),
+ 'region' => env('AWS_DEFAULT_REGION'),
+ 'bucket' => env('AWS_BUCKET'),
+ 'url' => env('AWS_URL'),
+ ],
+
+ 's3_public' => [
+ 'driver' => 's3',
+ 'key' => env('AWS_ACCESS_KEY_ID'),
+ 'secret' => env('AWS_SECRET_ACCESS_KEY'),
+ 'token' => env('AWS_SESSION_TOKEN'),
+ 'region' => env('AWS_DEFAULT_REGION'),
+ 'bucket' => env('AWS_PUBLIC_BUCKET'),
+ 'url' => env('AWS_URL'),
+ ],
+
+ ],
+```
+
+You can now configure the `public` disk to use S3 by changing `serverless.yml` or your production `.env`:
+
+```bash filename=".env"
+FILESYSTEM_DISK=s3
+FILESYSTEM_DISK_PUBLIC=s3
+```
diff --git a/docs/laravel/getting-started.mdx b/docs/laravel/getting-started.mdx
new file mode 100644
index 000000000..2a491a1d6
--- /dev/null
+++ b/docs/laravel/getting-started.mdx
@@ -0,0 +1,97 @@
+import { Callout } from 'nextra/components';
+import { NextSeo } from 'next-seo';
+
+
+
+# Serverless Laravel - Getting started
+
+This guide helps you run Laravel applications on AWS Lambda using Bref. These instructions are kept up to date to target the latest Laravel version.
+
+
+ A demo application is available on GitHub at [github.com/brefphp/examples](https://github.com/brefphp/examples).
+
+
+## Setup
+
+First, **follow the [Setup guide](../setup.mdx)** to create an AWS account and install the necessary tools.
+
+Next, in an existing Laravel project, install Bref and the [Laravel-Bref package](https://github.com/brefphp/laravel-bridge).
+
+```bash
+composer require bref/bref bref/laravel-bridge --update-with-dependencies
+```
+
+Then let's create a [`serverless.yml` configuration file](../environment/serverless-yml.mdx):
+
+```bash
+php artisan vendor:publish --tag=serverless-config
+```
+
+### How it works
+
+By default, the Laravel-Bref package will automatically configure Laravel to work on AWS Lambda.
+
+If you are curious, the package will automatically:
+
+- enable the `stderr` log driver, to send logs to CloudWatch ([read more about logs](../environment/logs.md))
+- enable the [`cookie` session driver](https://laravel.com/docs/session#configuration) (if you prefer, you can configure sessions to be stored in database, DynamoDB or Redis)
+- move the storage directory to `/tmp` (because the default storage directory is read-only on Lambda)
+- adjust a few more settings ([have a look at the `BrefServiceProvider` for details](https://github.com/brefphp/laravel-bridge/blob/master/src/BrefServiceProvider.php))
+
+## Deployment
+
+We do not want to deploy "dev" caches that were generated on our machine (because paths will be different on AWS Lambda). Let's clear them before deploying:
+
+```bash
+php artisan config:clear
+```
+
+When running in AWS Lambda, the Laravel application will automatically cache its configuration when booting. You don't need to run `php artisan config:cache` before deploying.
+
+Let's deploy now:
+
+```bash
+serverless deploy
+```
+
+When finished, the `deploy` command will show the URL of the application.
+
+### Deploying for production
+
+At the moment, we deployed our local codebase to Lambda. When deploying for production, we probably don't want to deploy:
+
+- development dependencies,
+- our local `.env` file,
+- or any other dev artifact.
+
+Follow [the deployment guide](/docs/deploy.md#deploying-for-production) for more details.
+
+## Troubleshooting
+
+In case your application is showing a blank page after being deployed, [have a look at the logs](../environment/logs.md).
+
+## Website assets
+
+Have a look at the [Website guide](../use-cases/websites.mdx) to learn how to deploy a website with assets.
+
+## Laravel Artisan
+
+As you may have noticed, we define a function named "artisan" in `serverless.yml`. That function is using the [Console runtime](../runtimes/console.mdx), which lets us run Laravel Artisan on AWS Lambda.
+
+For example, to execute an `artisan` command on Lambda, run the command below:
+
+```bash
+serverless bref:cli --args=""
+```
+
+For example:
+
+```bash
+serverless bref:cli --args="route:list"
+```
+
+For more details follow [the "Console" guide](../runtimes/console.mdx).
+
+## Inertia
+
+Laravel with Inertia runs without issue, like any other website. Follow the [Websites guide](../use-cases/websites.mdx) to learn how to deploy a Laravel with assets with Bref.
diff --git a/docs/laravel/maintenance-mode.mdx b/docs/laravel/maintenance-mode.mdx
new file mode 100644
index 000000000..d4bc50cee
--- /dev/null
+++ b/docs/laravel/maintenance-mode.mdx
@@ -0,0 +1,23 @@
+# Maintenance mode
+
+Similar to the `php artisan down` command, you may put your app into maintenance mode. All that's required is setting the `MAINTENANCE_MODE` environment variable:
+
+```yml filename="serverless.yml"
+provider:
+ environment:
+ MAINTENANCE_MODE: ${param:maintenance, null}
+```
+
+You can then deploy:
+
+```bash
+# Full deployment (goes through CloudFormation):
+serverless deploy --param="maintenance=1"
+
+# Or quick update of the functions config only:
+serverless deploy function --function=web --update-config --param="maintenance=1"
+serverless deploy function --function=artisan --update-config --param="maintenance=1"
+serverless deploy function --function= --update-config --param="maintenance=1"
+```
+
+To take your app out of maintenance mode, redeploy without the `--param="maintenance=1"` option.
diff --git a/docs/laravel/octane.mdx b/docs/laravel/octane.mdx
new file mode 100644
index 000000000..60517beb0
--- /dev/null
+++ b/docs/laravel/octane.mdx
@@ -0,0 +1,45 @@
+import { NextSeo } from 'next-seo';
+
+
+
+# Laravel Octane
+
+To run the HTTP application with [Laravel Octane](https://laravel.com/docs/10.x/octane) instead of PHP-FPM, change the following options in the `web` function:
+
+```yml
+functions:
+ web:
+ handler: Bref\LaravelBridge\Http\OctaneHandler
+ runtime: php-81
+ environment:
+ BREF_LOOP_MAX: 250
+ # ...
+```
+
+Keep the following details in mind:
+
+- Laravel Octane does not need Swoole or RoadRunner on AWS Lambda, so it is not possible to use Swoole-specific features.
+- Octane keeps Laravel booted in a long-running process, [beware of memory leaks](https://laravel.com/docs/10.x/octane#managing-memory-leaks).
+- The process is kept alive between requests, but you still don't pay for time between requests. The execution model and cost model of AWS Lambda does not change (Lambda is frozen between requests).
+- `BREF_LOOP_MAX` specifies the number of HTTP requests handled before the PHP process is restarted (and the memory is cleared).
+
+## Persistent database connections
+
+You can keep database connections persistent across requests to make your application even faster. To do so, set the `OCTANE_PERSIST_DATABASE_SESSIONS` environment variable:
+
+```yml
+functions:
+ web:
+ handler: Bref\LaravelBridge\Http\OctaneHandler
+ runtime: php-81
+ environment:
+ BREF_LOOP_MAX: 250
+ OCTANE_PERSIST_DATABASE_SESSIONS: 1
+ # ...
+```
+
+Note that if you are using PostgreSQL (9.6 or newer), you need to set [`idle_in_transaction_session_timeout`](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-IDLE-IN-TRANSACTION-SESSION-TIMEOUT) either in your RDS database's parameter group, or on a specific database itself.
+
+```sql
+ALTER DATABASE SET idle_in_transaction_session_timeout = '10000' -- 10 seconds in ms
+```
diff --git a/docs/laravel/passport.mdx b/docs/laravel/passport.mdx
new file mode 100644
index 000000000..142502b81
--- /dev/null
+++ b/docs/laravel/passport.mdx
@@ -0,0 +1,56 @@
+import { Steps } from 'nextra/components';
+import { NextSeo } from 'next-seo';
+
+
+
+# Laravel Passport
+
+Laravel Passport has a `passport:install` command. However, this command cannot be run in Lambda because it needs to write files to the `storage/` directory.
+
+Instead, here is what you need to do:
+
+
+
+ ### Generate keys locally
+
+ Run the following command on your machine to generate key files:
+
+ ```bash
+ php artisan passport:keys
+ ```
+
+ This will generate the `storage/oauth-private.key` and `storage/oauth-public.key` files, which need to be deployed.
+
+ Depending on how you deploy your application (from your machine, or from CI), you may want to whitelist them in `serverless.yml`:
+
+ ```yml filename="serverless.yml"
+ package:
+ patterns:
+ - ...
+ # Exclude the 'storage' directory
+ - '!storage/**'
+ # Except the public and private keys required by Laravel Passport
+ - 'storage/oauth-private.key'
+ - 'storage/oauth-public.key'
+ ```
+
+ ### Deploy
+
+ You can now redeploy the application:
+
+ ```yaml
+ serverless deploy
+ ```
+
+ ### Create tokens
+
+ Finally, you can create the tokens (which is the second part of the `passport:install` command):
+
+ ```bash
+ serverless bref:cli --args="passport:client --personal --name 'Laravel Personal Access Client'"
+ serverless bref:cli --args="passport:client --password --name 'Laravel Personal Access Client'"
+ ```
+
+
+
+All these steps were replacements of running the `passport:install` command [from the Passport documentation](https://laravel.com/docs/passport#installation).
diff --git a/docs/laravel/queues.mdx b/docs/laravel/queues.mdx
new file mode 100644
index 000000000..098882689
--- /dev/null
+++ b/docs/laravel/queues.mdx
@@ -0,0 +1,69 @@
+import { Callout } from 'nextra/components';
+import { NextSeo } from 'next-seo';
+
+
+
+# Laravel Queues
+
+
+ A demo application is available on GitHub at [github.com/brefphp/examples](https://github.com/brefphp/examples).
+
+
+To run Laravel Queues on AWS Lambda using [Amazon SQS](https://aws.amazon.com/sqs/), we don't want to run the `php artisan queue:work` command. Instead, we create a Lambda function that is invoked immediately when there are new jobs to process.
+
+To create the SQS queue (and the permissions for the Lambda functions to read/write to it), we can either do that manually, or use `serverless.yml`.
+
+To make things simpler, we will use the [Serverless Lift](https://github.com/getlift/lift) plugin to create and configure the SQS queue.
+
+First install the Lift plugin:
+
+```bash
+serverless plugin install -n serverless-lift
+```
+
+Then use [the Queue construct](https://github.com/getlift/lift/blob/master/docs/queue.md) in `serverless.yml`:
+
+```yml filename="serverless.yml"
+provider:
+ # ...
+ environment:
+ # ...
+ QUEUE_CONNECTION: sqs
+ SQS_QUEUE: ${construct:jobs.queueUrl}
+
+functions:
+ # ...
+
+constructs:
+ jobs:
+ type: queue
+ worker:
+ handler: Bref\LaravelBridge\Queue\QueueHandler
+ runtime: php-81
+ timeout: 60 # seconds
+```
+
+We define Laravel environment variables in `provider.environment` (this could also be done in the deployed `.env` file):
+
+- `QUEUE_CONNECTION: sqs` enables the SQS queue connection
+- `SQS_QUEUE: ${construct:jobs.queueUrl}` passes the URL of the created SQS queue
+
+If you want to create the SQS queue manually, you will need to set these variables. AWS credentials (`AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`) are automatically set up with the appropriate permissions for Laravel to use the SQS queue.
+
+That's it! Anytime a job is pushed to Laravel Queues, it will be sent to SQS, and SQS will invoke our "worker" function so that it is processed.
+
+
+ In the example above, we set the full SQS queue URL in the `SQS_QUEUE` variable.
+
+ If you only set the queue name (which is also valid), you need to set the `SQS_PREFIX` environment variable too. For example: `SQS_PREFIX: "https://sqs.${aws:region}.amazonaws.com/${aws:accountId}"`.
+
+
+## How it works
+
+When integrated with AWS Lambda, SQS has a built-in retry mechanism and storage for failed messages. These features work slightly differently than Laravel Queues. The "Bref for Laravel" integration does **not** use these SQS features.
+
+Instead, "Bref for Laravel" makes all the feature of Laravel Queues work out of the box, just like on any server. Read more in [the Laravel Queues documentation](https://laravel.com/docs/latest/queues).
+
+
+ The "Bref-Laravel bridge" v1 used to do the opposite. We changed that behavior in Bref v2 in order to make the experience smoother for Laravel users.
+
diff --git a/docs/web-apps/local-development.md b/docs/local-development.mdx
similarity index 54%
rename from docs/web-apps/local-development.md
rename to docs/local-development.mdx
index 4bbdace59..ceacbf6a0 100644
--- a/docs/web-apps/local-development.md
+++ b/docs/local-development.mdx
@@ -1,37 +1,43 @@
----
-title: Local development for web apps
-current_menu: web-local-development
-previous:
- link: /docs/web-apps/cron.html
- title: Cron commands
-next:
- link: /docs/web-apps/docker.html
- title: Docker
----
+import { Tabs, Tab, Callout } from 'nextra/components';
-It is possible to run **web applications** locally.
+# Local development
-> To run event-driven **PHP functions** locally, see [Local development for PHP Functions](/docs/function/local-development.md) instead.
+It is possible to run **web applications** (running with the FPM runtime) locally.
+
+
+ To run **event-driven functions** locally, read [Local development for event-driven functions](./local-development/event-driven-functions.mdx) instead.
+
## The simple way
-To keep things simple, you can run your PHP application like you did without Bref. For example with your favorite framework:
+To keep things simple, you can run your applications locally like you did without Bref.
-- Laravel via `php artisan serve` or [Homestead](https://laravel.com/docs/homestead) or [Laravel Valet](https://laravel.com/docs/valet)
-- Symfony via `symfony server:start` ([documentation](https://symfony.com/doc/current/setup/symfony_server.html))
+
+
+ With **Laravel**, run HTTP applications locally using `php artisan serve`, [Laravel Valet](https://laravel.com/docs/valet), or [Laravel Sail](https://laravel.com/docs/10.x/sail).
-If you are not using any framework, you can use PHP's built-in server:
+ You can test CLI commands locally by running them in your terminal using `php artisan my-command`.
+
+
+ With **Symfony**, run HTTP applications locally using `symfony server:start` ([documentation](https://symfony.com/doc/current/setup/symfony_server.html)).
-```bash
-php -S localhost:8000
-# The application is now available at http://localhost:8000/
-```
+ You can test CLI commands locally by running them in your terminal using `bin/console my-command`.
+
+
+ Run your HTTP applications locally via your preferred method to run PHP: Apache, WAMP, or even the built-in PHP server:
+
+ ```bash
+ php -S localhost:8000
+ # The application is now available at http://localhost:8000/
+ ```
+
+
## Docker
-In order to run the application locally in an environment closer to production, you can use the [Bref Docker images](https://hub.docker.com/u/bref). For example, create the following `docker-compose.yml`:
+In order to run the application locally in an environment closer to production, you can run your application using the [Bref Docker images](https://hub.docker.com/u/bref). For example, create the following `docker-compose.yml`:
-```yaml
+```yml filename="docker-compose.yml"
version: "3.5"
services:
@@ -42,9 +48,17 @@ services:
- .:/var/task
environment:
HANDLER: public/index.php
+ # Assets will be served from this directory
+ DOCUMENT_ROOT: public
```
-After running `docker-compose up`, the application will be available at [http://localhost:8000/](http://localhost:8000/).
+You can then run:
+
+```bash
+docker-compose up
+```
+
+The application will be available at [http://localhost:8000/](http://localhost:8000/).
The `HANDLER` environment variable lets you define which PHP file will be handling all HTTP requests. This should be the same handler that you have defined in `serverless.yml` for your HTTP function.
@@ -56,15 +70,15 @@ The code will be mounted in `/var/task`, just like in Lambda. But in Lambda, `/v
When developing locally, it is common to regenerate cache files on the fly (for example Symfony or Laravel cache). You have 2 options:
-- mount the whole codebase as writable:
+- either mount the whole codebase as writable (per the example above):
- ```yaml
+ ```yaml filename="docker-compose.yml"
volumes:
- .:/var/task
```
-- mount a specific cache directory as writable (better):
+- or mount a specific cache directory as writable (better):
- ```yaml
+ ```yaml filename="docker-compose.yml" {3}
volumes:
- .:/var/task:ro
- ./storage:/var/task/storage
@@ -74,23 +88,33 @@ When developing locally, it is common to regenerate cache files on the fly (for
If you want to serve assets locally, you can define a `DOCUMENT_ROOT` environment variable:
-```yaml
-version: "3.5"
-
+```yaml {6,7} filename="docker-compose.yml"
services:
app:
- image: bref/php-81-fpm-dev:2
- ports: [ '8000:8000' ]
- volumes:
- - .:/var/task
+ # ...
environment:
HANDLER: public/index.php
+ # Assets will be served from this directory
DOCUMENT_ROOT: public
```
In the example above, a `public/assets/style.css` file will be accessible at `http://localhost:8000/assets/style.css`.
-> Be aware that serving assets in production will not work like this out of the box. You will need [to use a S3 bucket](/docs/runtimes/http.md#assets).
+
+ Be aware that serving assets in production will not work like this out of the box. You will need [to use an S3 bucket](./use-cases/websites.mdx).
+
+
+### Console commands
+
+You can run console commands in Docker via:
+
+```bash
+# Laravel (artisan)
+docker-compose run app php artisan ...
+
+# Symfony (bin/console)
+docker-compose run app php bin/console ...
+```
### Xdebug
@@ -98,7 +122,7 @@ The development container (`bref/php--fpm-dev`) comes with Xdebug pre-i
To enable it, create a `php/conf.dev.d/php.ini` file in your project containing:
-```ini
+```ini filename="php/conf.dev.d/php.ini"
zend_extension=xdebug.so
```
@@ -110,7 +134,7 @@ Docker for Mac uses a virtual machine for running docker. That means you need to
Edit the `php/conf.dev.d/php.ini` file:
-```ini
+```ini filename="php/conf.dev.d/php.ini" {3-6}
zend_extension=xdebug.so
[xdebug]
@@ -123,7 +147,7 @@ xdebug.remote_host = 'host.docker.internal'
The development container (`bref/php--fpm-dev`) comes with the [blackfire](https://www.blackfire.io/) extension. When using docker compose, you can add the following service for the blackfire agent:
-```yaml
+```yml filename="docker-compose.yml"
services:
blackfire:
image: blackfire/blackfire
@@ -134,40 +158,9 @@ services:
In order to enable the probe you can create a folder `php/conf.dev.d` in your project and include an ini file enabling blackfire:
-```ini
+```ini filename="php/conf.dev.d/php.ini"
extension=blackfire
blackfire.agent_socket=tcp://blackfire:8707
```
For more details about using blackfire in a docker environment see the [blackfire docs](https://blackfire.io/docs/integrations/docker)
-
-## Console applications
-
-Console applications can be tested just like before: by running the command in your terminal.
-
-For example with Symfony you can run `bin/console ` , or with Laravel run `php artisan `.
-
-If you want to run your console in an environment close to production, you can use the Bref Docker dev images documented above. For example, if you have a `docker-compose.yml` file like this:
-
-```yaml
-version: "3.5"
-
-services:
- app:
- image: bref/php-81-fpm-dev:2
- ports: [ '8000:8000' ]
- volumes:
- - .:/var/task
- environment:
- HANDLER: public/index.php
-```
-
-Then CLI commands can be run in Docker via:
-
-```bash
-# Symfony (bin/console)
-docker-compose run app php bin/console
-
-# Laravel (artisan)
-docker-compose run app php artisan
-```
diff --git a/docs/local-development/_meta.json b/docs/local-development/_meta.json
new file mode 100644
index 000000000..209b7d435
--- /dev/null
+++ b/docs/local-development/_meta.json
@@ -0,0 +1,3 @@
+{
+ "event-driven-functions": "Event-driven functions"
+}
\ No newline at end of file
diff --git a/docs/function/local-development.md b/docs/local-development/event-driven-functions.mdx
similarity index 59%
rename from docs/function/local-development.md
rename to docs/local-development/event-driven-functions.mdx
index 6fe40633e..d7464c3ef 100644
--- a/docs/function/local-development.md
+++ b/docs/local-development/event-driven-functions.mdx
@@ -1,35 +1,30 @@
----
-title: Local development for functions
-current_menu: function-local-development
-previous:
- link: /docs/function/handlers.html
- title: Typed handlers
-next:
- link: /docs/function/cron.html
- title: Cron functions
----
-
-It is possible to run **PHP functions** locally.
-
-> **Warning:**
-> To run **web apps** locally, see [Local development for HTTP applications](/docs/web-apps/local-development.md) instead.
+import { Callout } from 'nextra/components';
+
+# Local development for functions
+
+It is possible to run **event-driven functions** locally.
+
+
+ To run **HTTP applications** (like Laravel or Symfony) locally, read [Local development for HTTP applications](../local-development.mdx) instead.
+
## With Serverless Framework
The `serverless bref:local` command invokes your [PHP functions](/docs/runtimes/function.md) locally, using PHP installed on your machine. You can provide an event if your function expects one.
-> **Note:**
-> The `serverless bref:local` command is a simpler alternative to the native `serverless invoke local` command, which tries to run PHP using Docker with very little success. Use `bref:local` instead of `invoke local`.
+
+ The `serverless bref:local` command is a simpler alternative to the native `serverless invoke local` command, which tries to run PHP using Docker with very little success. Use `serverless bref:local` instead of `serverless invoke local`.
+
For example, given this function:
-```php
+```php filename="my-function.php"
return function (array $event) {
return 'Hello ' . ($event['name'] ?? 'world');
};
```
-```yaml
+```yml filename="serverless.yml"
# ...
functions:
@@ -53,18 +48,14 @@ $ serverless bref:local -f hello --path=event.json
Hello Jane
```
-> **Note:** On Windows PowerShell, you must escape the "double quote" char if you write JSON directly in the CLI. Example:
-> ```bash
-> $ serverless bref:local -f hello --data '{\"name\": \"Bill\"}'
-> ```
-
-The `serverless bref:local` command runs using the local PHP installation. If you prefer to use Docker, check out the "Without Serverless Framework" section below.
-
-## API Gateway local development
-
-If you build HTTP applications with [API Gateway HTTP events](handlers.md#api-gateway-http-events), `serverless bref:local` is a bit unpractical because you need to manually craft HTTP events in JSON.
+
+ On Windows PowerShell, you must escape the "double quote" char if you write JSON directly in the CLI. Example:
+ ```bash
+ $ serverless bref:local -f hello --data '{\"name\": \"Bill\"}'
+ ```
+
-Instead, you can use the [`bref/dev-server`](https://github.com/brefphp/dev-server) package to emulate API Gateway locally.
+The `serverless bref:local` command runs using the local PHP installation. If you prefer to use **Docker**, check out the "Without Serverless Framework" section below.
## Without Serverless Framework
@@ -82,7 +73,7 @@ $ vendor/bin/bref-local my-function.php '{"name": "Jane"}'
Hello Jane
# With a path to a file containing a JSON event.
-$ cat event.json
+$cat event.json
{
"name": "Alex"
}
@@ -90,6 +81,8 @@ $ vendor/bin/bref-local --path event.json my-function.php
Hello Alex
```
+## With Docker
+
If you want to run your function in Docker:
```bash
@@ -99,9 +92,9 @@ $ docker run --rm -it --entrypoint= -v $(PWD):/var/task:ro bref/php-81:2 vendor/
$ docker run --rm -it -v $(PWD):/var/task:ro bref/php-81-fpm-dev:2 vendor/bin/bref-local my-function.php
```
-You can also use Docker Compose:
+You can also use Docker Compose, like described in [Local development for HTTP applications](../local-development.mdx):
-```yaml
+```yml filename="docker-compose.yml"
version: "3.5"
services:
app:
@@ -115,3 +108,9 @@ Then run functions:
```bash
$ docker-compose run app vendor/bin/bref-local my-function.php
```
+
+## API Gateway local development
+
+If you build HTTP applications with [API Gateway HTTP events](../function/handlers.md#api-gateway-http-events), `serverless bref:local` is a bit unpractical because you need to manually craft HTTP events in JSON.
+
+Instead, you can use the [`bref/dev-server`](https://github.com/brefphp/dev-server) package to emulate API Gateway locally.
diff --git a/docs/monitoring.md b/docs/monitoring.md
index 0bdfa8898..e3d928e2d 100644
--- a/docs/monitoring.md
+++ b/docs/monitoring.md
@@ -1,7 +1,4 @@
----
-title: Monitoring
-current_menu: monitoring
----
+# Monitoring
By default, AWS Lambda publishes all logs and general metrics (HTTP response time, code execution duration, etc.) to AWS CloudWatch.
diff --git a/docs/newsletters.md b/docs/newsletters.md
deleted file mode 100644
index f70c75ee7..000000000
--- a/docs/newsletters.md
+++ /dev/null
@@ -1,16 +0,0 @@
----
-title: Newsletters
-current_menu: newsletters
-introduction: A collection of newsletters related to serverless and PHP.
----
-
-This page collects newsletters related to serverless and PHP. Those are not necessarily related to Bref.
-
-You can subscribe to these newsletters to keep up to date with what's happening in the serverless world.
-
-- [Serverless PHP](https://serverless-php.news/)
-
- A monthly newsletter about serverless news related to PHP.
-- [Off by None](https://www.jeremydaly.com/newsletter/)
-
- A weekly newsletter about serverless news in general.
diff --git a/docs/runtimes.mdx b/docs/runtimes.mdx
new file mode 100644
index 000000000..48255fe97
--- /dev/null
+++ b/docs/runtimes.mdx
@@ -0,0 +1,192 @@
+import { Callout } from 'nextra/components';
+import { NextSeo } from 'next-seo';
+
+
+
+# PHP runtimes for AWS Lambda
+
+There is no native support for PHP on AWS Lambda. Instead, we can use third-party runtimes via [AWS Lambda *custom runtimes*](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html).
+
+**Bref provides open-source runtimes to run PHP on Lambda**. These PHP runtimes are distributed as AWS Lambda layers and Docker images.
+
+## Bref runtimes
+
+Bref provides 3 PHP runtimes:
+
+- The "FPM" runtime, to run **web applications**.
+- The "function" runtime, to run **event-driven functions**.
+- The "console" runtime, to run **CLI commands**.
+
+These runtimes are used by the Laravel & Symfony framework integrations to run web applications, console/artisan commands, queues, and more.
+
+The runtimes are available as AWS Lambda layers that you can use (explained below). They are also published as Docker images so that you can run your applications locally (more on that later).
+
+### PHP-FPM runtime for web apps
+
+Name: `php-83-fpm`, `php-82-fpm`, `php-81-fpm`, and `php-80-fpm`.
+
+This runtime uses PHP-FPM to run **web applications** on AWS Lambda, like on a traditional server.
+
+It's **the easiest to start with**: it works like traditional PHP hosting and is compatible with Symfony, Laravel, and other frameworks.
+
+[Learn more about the PHP-FPM runtime](./runtimes/fpm-runtime.mdx).
+
+### Event-driven functions
+
+Name: `php-83`, `php-82`, `php-81`, and `php-80`.
+
+AWS Lambda was initially created to run _functions_ (yes, functions of code) in the cloud.
+
+The Bref "function" runtime lets you create Lambda functions in PHP like with any other language.
+
+This runtime works great to create **event-driven micro-services**.
+
+
+ If you are getting started, we highly recommend using the FPM runtime instead. It's "PHP as usual" (like on any server), with all the benefits of serverless (simplicity, scaling, etc.).
+
+
+[Learn more about the Function runtime](./runtimes/function.mdx).
+
+### Console
+
+Name: `php-83-console`, `php-82-console`, `php-81-console`, and `php-80-console`.
+
+This runtime lets you run CLI console commands on Lambda.
+
+For example, we can run the [Symfony Console](https://symfony.com/doc/master/components/console.html) or [Laravel Artisan](https://laravel.com/docs/artisan).
+
+[Learn more about the Console runtime](./runtimes/console.mdx).
+
+## Usage
+
+To use a runtime, set it on each function in `serverless.yml`:
+
+```yaml
+service: app
+provider:
+ name: aws
+plugins:
+ - ./vendor/bref/bref
+functions:
+ hello:
+ # ...
+ runtime: php-81
+ # or:
+ runtime: php-81-fpm
+ # or:
+ runtime: php-81-console
+```
+
+Bref currently provides runtimes for PHP 8.0, 8.1, 8.2 and 8.3:
+
+- `php-83`
+- `php-82`
+- `php-81`
+- `php-80`
+- `php-83-fpm`
+- `php-82-fpm`
+- `php-81-fpm`
+- `php-80-fpm`
+- `php-83-console`
+- `php-82-console`
+- `php-81-console`
+- `php-80-console`
+
+
+ `php-80` means PHP 8.0.\*. It is not possible to require a specific "patch" version. The latest Bref versions always aim to support the latest PHP versions, so upgrade via Composer frequently to keep PHP up to date.
+
+
+### The Bref plugin for serverless.yml
+
+Make sure to always include the Bref plugin in your `serverless.yml` config:
+
+```yaml
+plugins:
+ - ./vendor/bref/bref
+```
+
+This plugin is what makes `runtime: php-81` work (as well as other utilities). It is explained in more details in the section below.
+
+### ARM runtimes
+
+It is possible to run AWS Lambda functions on [ARM-based AWS Graviton processors](https://aws.amazon.com/blogs/aws/aws-lambda-functions-powered-by-aws-graviton2-processor-run-your-functions-on-arm-and-get-up-to-34-better-price-performance/). This is usually considered a way to reduce costs and improve performance.
+
+You can deploy to ARM by using the `arm64` architecture:
+
+```diff
+functions:
+ api:
+ handler: public/index.php
+ runtime: php-81-fpm
++ architecture: arm64
+```
+
+The Bref plugin will detect that change and automatically use the Bref ARM Lambda layers.
+
+
+ The `bref-extra-extensions` package is not available for ARM processors yet.
+
+
+### AWS Lambda layers
+
+The `runtime: php-xxx` runtimes we use in `serverless.yml` are not _real_ AWS Lambda runtimes. Indeed, PHP is not supported natively on AWS Lambda.
+
+What the Bref plugin for `serverless.yml` (the one we include with `./vendor/bref/bref`) does is it automatically turns this:
+
+```yaml
+functions:
+ hello:
+ # ...
+ runtime: php-81
+```
+
+into this:
+
+```yaml
+functions:
+ hello:
+ # ...
+ runtime: provided.al2
+ layers:
+ - 'arn:aws:lambda:us-east-1:534081306603:layer:php-81:21'
+```
+
+☝️ `provided.al2` [is the generic Linux environment for custom runtimes](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html#runtimes-custom-use), and the `layers` config points to Bref's AWS Lambda layers.
+
+Thanks to the Bref plugin, our `serverless.yml` is simpler. It also automatically adapts to the AWS region in use, and automatically points to the correct layer version. You can learn more about "layers" [in this page](./runtimes/runtimes-details.mdx).
+
+If you want to reference AWS Lambda layers directly (instead of using the simpler `runtime: php-81` syntax), the Bref plugin also provides simple `serverless.yml` variables. These were the default in Bref v1.x, so you may find this older syntax on tutorials and blog posts:
+
+```yaml
+service: app
+provider:
+ name: aws
+ runtime: provided.al2
+plugins:
+ - ./vendor/bref/bref
+functions:
+ hello:
+ # ...
+ layers:
+ - ${bref:layer.php-81}
+ # or:
+ - ${bref:layer.php-81-fpm}
+```
+
+The `${...}` notation is the [syntax to use variables](https://serverless.com/framework/docs/providers/aws/guide/variables/) in `serverless.yml`. The Bref plugin provides the following variables:
+
+- `${bref:layer.php-83}`
+- `${bref:layer.php-82}`
+- `${bref:layer.php-81}`
+- `${bref:layer.php-80}`
+- `${bref:layer.php-83-fpm}`
+- `${bref:layer.php-82-fpm}`
+- `${bref:layer.php-81-fpm}`
+- `${bref:layer.php-80-fpm}`
+- `${bref:layer.console}`
+
+Bref ARM layers are the same as the x86 layers, but with the `arm-` prefix in their name, for example `${bref:layer.arm-php-82}`. The only exception is `${bref:layer.console}` (this is the same layer for both x86 and ARM).
+
+
+ To be clear, it is easier and recommended to use the `runtime: php-xxx` option instead of setting `layers` directly.
+
diff --git a/docs/runtimes/README.md b/docs/runtimes/README.md
deleted file mode 100644
index e6a0c3a6d..000000000
--- a/docs/runtimes/README.md
+++ /dev/null
@@ -1,294 +0,0 @@
----
-title: PHP runtimes for AWS Lambda
-current_menu: runtimes-introduction
-introduction: Bref provides runtimes to bring support for PHP on AWS Lambda.
-previous:
- link: /docs/first-steps.html
- title: First steps
-next:
- link: /docs/runtimes/http.html
- title: Web apps on AWS Lambda
----
-
-There is no built-in support for PHP on AWS Lambda. Instead, we can use 3rd party runtimes via [AWS Lambda *layers*](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html).
-
-**Bref provides open-source runtimes to run PHP on Lambda** (distributed as AWS Lambda layers).
-
-## Bref runtimes
-
-Bref provides 2 main runtimes:
-
-- The "FPM" runtime, to create **web applications**.
-- The "function" runtime, to create **event-driven functions**.
-
-You can see in the documentation menu how these two runtimes are used for two different kinds of applications.
-
-These runtimes are available as AWS Lambda layers that you can use (explained below). They are also published as Docker images so that you can run your applications locally (more on that later).
-
-### Web apps
-
-Name: `php-83-fpm`, `php-82-fpm`, `php-81-fpm`, and `php-80-fpm`.
-
-This runtime uses PHP-FPM to run **web applications** on AWS Lambda.
-
-It's **the easiest to start with**: it works like traditional PHP hosting and is compatible with Symfony and Laravel.
-
-[Get started with the FPM runtime in "Bref for web apps"](/docs/runtimes/http.md).
-
-### Event-driven functions
-
-Name: `php-83`, `php-82`, `php-81`, and `php-80`.
-
-AWS Lambda was initially created to run _functions_ (yes, functions of code) in the cloud.
-
-The Bref "function" runtime lets you create Lambda functions in PHP like with any other language.
-
-This runtime works great to create **event-driven micro-services**.
-
-_Note: if you are getting started, we highly recommend using the FPM runtime instead. It's "PHP as usual" (like on any server), with all the benefits of serverless (simplicity, scaling, etc.)._
-
-[Get started with the Function runtime in "Bref for event-driven functions"](/docs/runtimes/function.md).
-
-### Console
-
-Name: `php-83-console`, `php-82-console`, `php-81-console`, and `php-80-console`.
-
-This runtime lets you run CLI console commands on Lambda.
-
-For example, we can run the [Symfony Console](https://symfony.com/doc/master/components/console.html) or [Laravel Artisan](https://laravel.com/docs/artisan).
-
-[Read more about the `console` runtime here](/docs/runtimes/console.md).
-
-## Usage
-
-To use a runtime, set it on each function in `serverless.yml`:
-
-```yaml
-service: app
-provider:
- name: aws
-plugins:
- - ./vendor/bref/bref
-functions:
- hello:
- # ...
- runtime: php-81
- # or:
- runtime: php-81-fpm
- # or:
- runtime: php-81-console
-```
-
-Bref currently provides runtimes for PHP 8.0, 8.1, 8.2 and 8.3:
-
-- `php-83`
-- `php-82`
-- `php-81`
-- `php-80`
-- `php-83-fpm`
-- `php-82-fpm`
-- `php-81-fpm`
-- `php-80-fpm`
-- `php-83-console`
-- `php-82-console`
-- `php-81-console`
-- `php-80-console`
-
-> `php-80` means PHP 8.0.\*. It is not possible to require a specific "patch" version. The latest Bref versions always aim to support the latest PHP versions, so upgrade frequently to keep PHP up to date.
-
-### ARM runtimes
-
-It is possible to run AWS Lambda functions on [ARM-based AWS Graviton processors](https://aws.amazon.com/blogs/aws/aws-lambda-functions-powered-by-aws-graviton2-processor-run-your-functions-on-arm-and-get-up-to-34-better-price-performance/). This is usually considered a way to reduce costs and improve performance.
-
-You can deploy to ARM by using the `arm64` architecture:
-
-```diff
-functions:
- api:
- handler: public/index.php
- runtime: php-81-fpm
-+ architecture: arm64
-```
-
-The Bref plugin will detect that change and automatically use the Bref ARM Lambda layers.
-
-### The Bref plugin for serverless.yml
-
-Make sure to always include the Bref plugin in your `serverless.yml` config:
-
-```yaml
-plugins:
- - ./vendor/bref/bref
-```
-
-This plugin is what makes `runtime: php-81` work (as well as other utilities). It is explained in more details in the section below.
-
-### AWS Lambda layers
-
-The `runtime: php-xxx` runtimes we use in `serverless.yml` are not _real_ AWS Lambda runtimes. Indeed, PHP is not supported natively on AWS Lambda.
-
-What the Bref plugin for `serverless.yml` (the one we include with `./vendor/bref/bref`) does is it automatically turns this:
-
-```yaml
-functions:
- hello:
- # ...
- runtime: php-81
-```
-
-into this:
-
-```yaml
-functions:
- hello:
- # ...
- runtime: provided.al2
- layers:
- - 'arn:aws:lambda:us-east-1:534081306603:layer:php-81:21'
-```
-
-☝️ `provided.al2` [is the generic Linux environment for custom runtimes](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html#runtimes-custom-use), and the `layers` config points to Bref's AWS Lambda layers.
-
-Thanks to the Bref plugin, our `serverless.yml` is simpler. It also automatically adapts to the AWS region in use, and automatically points to the correct layer version. You will learn more about "layers" below in this page.
-
-If you want to reference AWS Lambda layers directly (instead of using the simpler `runtime: php-81` syntax), the Bref plugin also provides simple `serverless.yml` variables. These were the default in Bref v1.x, so you may find this older syntax on tutorials and blog posts:
-
-```yaml
-service: app
-provider:
- name: aws
- runtime: provided.al2
-plugins:
- - ./vendor/bref/bref
-functions:
- hello:
- # ...
- layers:
- - ${bref:layer.php-80}
- # or:
- - ${bref:layer.php-80-fpm}
-```
-
-The `${...}` notation is the [syntax to use variables](https://serverless.com/framework/docs/providers/aws/guide/variables/) in `serverless.yml`. The Bref plugin provides the following variables:
-
-- `${bref:layer.php-83}`
-- `${bref:layer.php-82}`
-- `${bref:layer.php-81}`
-- `${bref:layer.php-80}`
-- `${bref:layer.php-83-fpm}`
-- `${bref:layer.php-82-fpm}`
-- `${bref:layer.php-81-fpm}`
-- `${bref:layer.php-80-fpm}`
-- `${bref:layer.console}`
-
-Bref ARM layers are the same as the x86 layers, but with the `arm-` prefix in their name, for example `${bref:layer.arm-php-82}`. The only exception is `${bref:layer.console}` (this is the same layer for both x86 and ARM).
-
-> **Note**: to be clear, it is easier and recommended to use the `runtime: php-xxx` option instead of setting `layers` directly.
-
-## Lambda layers in details
-
-> **Notice**: this section is only useful if you want to learn more.
->
-> You can skip it for now if you just want to get started with Bref.
->
-> ▶ [**Get started with web apps**](/docs/runtimes/http.md).
-
-Bref runtimes are distributed as [AWS Lambda layers](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html). While Bref provides a Serverless plugin to simplify how to use them, you can use the layers directly.
-
-The layer names follow this pattern:
-
-```
-arn:aws:lambda::534081306603:layer::
-
-# For example:
-arn:aws:lambda:us-east-1:534081306603:layer:php-80:21
-```
-
-You can use layers via their full ARN, for example in `serverless.yml`:
-
-```yaml
-service: app
-provider:
- name: aws
- runtime: provided.al2
-functions:
- hello:
- ...
- layers:
- - 'arn:aws:lambda:us-east-1:534081306603:layer:php-80:21'
-```
-
-Or if you are using [SAM's `template.yaml`](https://aws.amazon.com/serverless/sam/):
-
-```yaml
-AWSTemplateFormatVersion: '2010-09-09'
-Transform: AWS::Serverless-2016-10-31
-Resources:
- Hello:
- Type: AWS::Serverless::Function
- Properties:
- ...
- Runtime: provided.al2
- Layers:
- - 'arn:aws:lambda:us-east-1:534081306603:layer:php-80:21'
-```
-
-Bref layers work with AWS Lambda regardless of the tool you use to deploy your application: Serverless, SAM, CloudFormation, Terraform, AWS CDK, etc.
-
-> Remember: the layer ARN contains a region. **You need to use the same region as the rest of your application** else Lambda will not find the layer.
-
-### Layers NPM package
-
-You can use [the `@bref.sh/layers.js` NPM package](https://github.com/brefphp/layers.js) to get up-to-date layer ARNs in Node applications, for example with the AWS CDK.
-
-### Layer version (``)
-
-The latest of runtime versions can be found at [**runtimes.bref.sh**](https://runtimes.bref.sh/).
-
-Here are the latest versions:
-
-
-
-You can also find the appropriate ARN/version for your current Bref version by running:
-
-```bash
-serverless bref:layers
-```
-
-**Watch out:** if you use the layer ARN directly, you may need to update the ARN (the `` part) when you update Bref. Follow the Bref release notes closely.
-
-### Bref ping
-
-Bref layers send a ping to estimate the total number of Lambda invocations powered by Bref. That statistic is useful in two ways:
-
-- to provide new users an idea on how much Bref is used in production
-- to communicate to AWS how much Bref is used and push for better PHP integration with AWS Lambda tooling
-
-We consider this to be beneficial both to the Bref project (by getting more users and more consideration from AWS) and for Bref users (more users means a larger community, a stronger and more active project, as well as more features from AWS).
-
-#### What is sent
-
-The data sent in the ping is completely anonymous. It does not contain any identifiable data about anything (the project, users, etc.).
-
-**The only data it contains is:** "A Bref invocation happened with the layer XYZ" (where XYZ is the name of the Bref layer, like "function", "fpm" or "console").
-
-Anyone can inspect the code and the data sent by checking the [`Bref\Runtime\LambdaRuntime::ping()` function](https://github.com/brefphp/bref/blob/master/src/Runtime/LambdaRuntime.php#L374).
-
-#### How is it sent
-
-The data is sent via the [statsd](https://github.com/statsd/statsd) protocol, over [UDP](https://en.wikipedia.org/wiki/User_Datagram_Protocol).
-
-Unlike TCP, UDP does not check that the message correctly arrived to the server.
-It doesn't even establish a connection. That means that UDP is extremely fast:
-the data is sent over the network and the code moves on to the next line.
-When actually sending data, the overhead of that ping takes about 150 micro-seconds.
-
-However, this function actually sends data every 100 invocation, because we don't
-need to measure *all* invocations. We only need an approximation.
-That means that 99% of the time, no data is sent, and the function takes 30 micro-seconds.
-If we average all executions, the overhead of that ping is about 31 micro-seconds.
-Given that it is much much less than even 1 milli-second, we consider that overhead negligible.
-
-#### Disabling
-
-The ping can be disabled by setting a `BREF_PING_DISABLE` environment variable to `1`.
diff --git a/docs/runtimes/_meta.json b/docs/runtimes/_meta.json
new file mode 100644
index 000000000..f9b80dd57
--- /dev/null
+++ b/docs/runtimes/_meta.json
@@ -0,0 +1,6 @@
+{
+ "fpm-runtime": "PHP-FPM runtime",
+ "function": "Function runtime",
+ "console": "Console runtime",
+ "runtimes-details": "Runtimes in details"
+}
\ No newline at end of file
diff --git a/docs/runtimes/console.md b/docs/runtimes/console.mdx
similarity index 53%
rename from docs/runtimes/console.md
rename to docs/runtimes/console.mdx
index ff205ce5a..1a9abbf8e 100644
--- a/docs/runtimes/console.md
+++ b/docs/runtimes/console.mdx
@@ -1,24 +1,30 @@
----
-title: Console commands
-current_menu: console-applications
-introduction: Learn how to run serverless console commands on AWS Lambda with Symfony Console or Laravel Artisan.
-previous:
- link: /docs/websites.html
- title: Website assets
-next:
- link: /docs/web-apps/cron.html
- title: Cron commands
----
+import { NextSeo } from 'next-seo';
-Bref provides a way to run console commands on AWS Lambda.
+
-This can be used to run PHP scripts, the [Symfony Console](https://symfony.com/doc/current/console.html), as well as [Laravel Artisan](https://laravel.com/docs/artisan) commands in production.
+# Console runtime
-## Configuration
+Bref's "Console" runtime lets us run CLI scripts on AWS Lambda.
-The lambda function used for running console applications must use the `php-xx-console` runtime. Here is an example `serverless.yml`:
+This can be used to run PHP scripts, like cron tasks, the [Symfony Console](https://symfony.com/doc/current/console.html), [Laravel Artisan](https://laravel.com/docs/artisan), and more.
-```yaml
+## How it works
+
+When the function is invoked, the Console runtime will execute the PHP script defined as the *handler* in a sub-process.
+
+The result of the execution (exit code and output) will be returned as the result of the AWS Lambda invocation. All the CLI output is also logged ([learn more about logs](../environment/logs.mdx)).
+
+Console functions can be invoked:
+
+- via a cron schedule
+- via the `serverless bref:cli` command
+- manually by invoking the function via the AWS API
+
+## Usage
+
+The Lambda function used for running console applications must use the `php-xx-console` runtime. Here is an example:
+
+```yml filename="serverless.yml" {8-9}
service: app
provider:
name: aws
@@ -26,15 +32,44 @@ plugins:
- ./vendor/bref/bref
functions:
hello:
- handler: bin/console # or 'artisan' for Laravel
+ handler: the-php-script-to-run.php
runtime: php-81-console
```
-Behind the scenes, the `php-xx-console` runtime will deploy a Lambda function configured to use Bref's `php-81` AWS Lambda layer plus Bref's `console` layer (read more about these in the [runtimes documentation](./README.md)).
+Behind the scenes, the `php-xx-console` runtime will deploy a Lambda function configured to use Bref's `php-81` AWS Lambda layer plus Bref's `console` layer (read more about these in the [runtimes documentation](../runtimes.mdx)).
-## Usage
+## Running commands
+
+When invoked, the "Console" runtime executes the `handler` script in a sub-process. For example, if the following handler was defined:
+
+```yml filename="serverless.yml"
+functions:
+ hello:
+ handler: the-php-script-to-run.php
+ runtime: php-81-console
+```
+
+Then the following command would run in Lambda every time the function is invoked:
+
+```sh
+php the-php-script-to-run.php
+```
-To run a console command on AWS Lambda, run `serverless bref:cli` on your computer:
+The Lambda function can be invoked with a payload. It must be a JSON string, for example `"arg1 arg2 --option1=foo"`. Note that it is a string encoded in JSON, that is why it is in quotes, `json_decode($payload)` would return the string itself.
+
+In our example, the following command would run in Lambda when invoked with such a payload:
+
+```sh
+php the-php-script-to-run.php arg1 arg2 --option1=foo
+```
+
+### Cron
+
+Read the dedicated documentation for [running cron tasks on AWS Lambda](../use-cases/cron.mdx).
+
+### CLI invocation
+
+To manually run a console command on AWS Lambda, run `serverless bref:cli` on your computer:
```bash
serverless bref:cli --args=""
@@ -64,7 +99,17 @@ $ AWS_ACCESS_KEY_ID=foo AWS_SECRET_ACCESS_KEY=bar serverless bref:cli
# ...
```
-### Usage without Serverless Framework
+The `bref:cli` command can be used to run CLI commands in Lambda from your machine, but can also be used in CI/CD to run DB migrations for example.
+
+### Interactive terminal
+
+As an alternative to the CLI, the [Bref Dashboard](https://dashboard.bref.sh/?ref=bref) provides a convenient way to run commands via a terminal:
+
+[![Bref Dashboard terminal for Laravel](../runtimes/dashboard-terminal.png)](https://dashboard.bref.sh/?ref=bref)
+
+Functions using the "console" runtime are automatically detected, and colors are enabled by default for Laravel Artisan and Symfony Console.
+
+### Without Serverless Framework
If you do not use `serverless.yml` but something else, like SAM/AWS CDK/Terraform, you can invoke your console function via the AWS CLI. For example:
@@ -97,12 +142,6 @@ aws lambda invoke \
> **Note:**
> The `--payload` needs to contain a JSON string, that is why it is quoted twice: `'"..."'`. This is intentional.
-The [Bref Dashboard](https://dashboard.bref.sh/?ref=bref) also provides a convenient way to run commands via a terminal:
-
-[![Bref Dashboard terminal for Laravel](./dashboard-terminal.png)](https://dashboard.bref.sh/?ref=bref)
-
-Functions using the "console" runtime are automatically detected, and colors are enabled by default for Laravel Artisan and Symfony Console.
-
## Lambda context
Lambda provides information about the invocation, function, and execution environment via the *lambda context*.
diff --git a/docs/runtimes/fpm-runtime.mdx b/docs/runtimes/fpm-runtime.mdx
new file mode 100644
index 000000000..9765f30b7
--- /dev/null
+++ b/docs/runtimes/fpm-runtime.mdx
@@ -0,0 +1,83 @@
+import { Callout } from 'nextra/components';
+import { NextSeo } from 'next-seo';
+
+
+
+# PHP-FPM runtime for AWS Lambda
+
+To run HTTP APIs and websites on AWS Lambda, Bref runs your code **using PHP-FPM**. That means PHP applications can run on Lambda just like on any other PHP hosting platform.
+
+That's great: we can use our favorite framework as usual, like **Laravel or Symfony**.
+
+
+ Every code we deploy on AWS Lambda is called a "Function". Do not let this name confuse you: we do deploy HTTP **applications** in a Lambda Function.
+
+ In the Lambda world, an HTTP application is a *function* that is called by a request and returns a response. Good news: this is exactly what our PHP applications do.
+
+
+## How it works
+
+AWS Lambda can react to HTTP requests via [API Gateway](https://aws.amazon.com/api-gateway/). On Lambda, the Bref runtime starts PHP-FPM and forwards API Gateway requests to PHP-FPM via the FastCGI protocol.
+
+![](./fpm-runtime.png)
+
+Bref is basically doing the same thing as Apache or Nginx, and the PHP code runs in the same environment as on any server.
+
+While this may sound like a lot to deploy an entire application inside Lambda, it works very well. Performance-wise, the overhead of the Bref runtime with PHP-FPM is less than a millisecond. Many users and companies have been running websites and HTTP APIs on Lambda at scale for years.
+
+## Usage
+
+To deploy an HTTP application on AWS Lambda, use the `php-xx-fpm` runtime and combine it with the `httpApi` event:
+
+```yml filename="serverless.yml" {9-11}
+service: app
+provider:
+ name: aws
+plugins:
+ - ./vendor/bref/bref
+functions:
+ app:
+ handler: index.php
+ runtime: php-81-fpm
+ events:
+ - httpApi: '*'
+```
+
+The `httpApi` event will deploy an API Gateway HTTP API and the `*` configuration will forward all requests to your PHP application.
+
+### Handler
+
+The *handler* is the file that is invoked when an HTTP request comes in.
+
+It is the same file that is traditionally configured in Apache or Nginx. In Symfony and Laravel this is usually `public/index.php` but it can be anything.
+
+```yml filename="serverless.yml"
+functions:
+ app:
+ handler: public/index.php
+```
+
+## Context access
+
+### Lambda context
+
+Lambda provides information about the invocation, function, and execution environment via the *lambda context*.
+
+Bref exposes the Lambda context in the `$_SERVER['LAMBDA_INVOCATION_CONTEXT']` variable as a JSON-encoded string.
+Here is an example to retrieve it:
+
+```php
+$lambdaContext = json_decode($_SERVER['LAMBDA_INVOCATION_CONTEXT'], true);
+```
+
+### Request context
+
+API Gateway integrations can add information to the HTTP request via the *request context*.
+This is the case, for example, when using AWS Cognito authentication on API Gateway.
+
+Bref exposes the request context in the `$_SERVER['LAMBDA_REQUEST_CONTEXT']` variable as a JSON-encoded string.
+Here is an example to retrieve it:
+
+```php
+$requestContext = json_decode($_SERVER['LAMBDA_REQUEST_CONTEXT'], true);
+```
diff --git a/docs/runtimes/fpm-runtime.png b/docs/runtimes/fpm-runtime.png
new file mode 100644
index 000000000..9a87cfe50
Binary files /dev/null and b/docs/runtimes/fpm-runtime.png differ
diff --git a/docs/runtimes/function.md b/docs/runtimes/function.md
deleted file mode 100644
index 627a74d34..000000000
--- a/docs/runtimes/function.md
+++ /dev/null
@@ -1,155 +0,0 @@
----
-title: PHP Lambda functions
-current_menu: php-functions
-introduction: Run serverless event-driven PHP functions on AWS Lambda using Bref.
-next:
- link: /docs/function/handlers.html
- title: Typed PHP Lambda handlers
----
-
-Previously, we saw how to use AWS Lambda as web hosting for complete web applications.
-But we can also run event-driven **PHP functions** on AWS Lambda.
-
-Here is an example of a PHP Lambda function written as an anonymous function:
-
-```php
- If you instead want to write a classic **HTTP application** read [Bref for web apps](/docs/runtimes/http.md).
-
-### CLI
-
-A PHP function can be triggered manually from the CLI using the [`serverless invoke` command](https://serverless.com/framework/docs/providers/aws/cli-reference/invoke/):
-
-```bash
-$ serverless invoke -f
-# The function name is the one in serverless.yml, in our example that would be `hello`:
-$ serverless invoke -f hello
-"Hello world"
-```
-
-To pass event data to the lambda use the `--data` option. For example:
-
-```bash
-serverless invoke -f --data='{"name": "John" }'
-```
-
-Run `serverless invoke --help` to learn more about the `invoke` command.
-
-### From PHP applications
-
-A PHP function can be triggered from another PHP application using the AWS PHP SDK:
-
-You first need to install the AWS PHP SDK by running
-
-```bash
-$ composer require aws/aws-sdk-php
-```
-
-```php
-$lambda = new \Aws\Lambda\LambdaClient([
- 'version' => 'latest',
- 'region' => '',
-]);
-
-$result = $lambda->invoke([
- 'FunctionName' => '',
- 'InvocationType' => 'RequestResponse',
- 'LogType' => 'None',
- 'Payload' => json_encode(/* event data */),
-]);
-
-$result = json_decode($result->get('Payload')->getContents(), true);
-```
-
-> A lighter alternative to the official AWS PHP SDK is the [AsyncAws Lambda](https://async-aws.com/clients/lambda.html) package.
-
-### From other AWS services
-
-Functions are perfect to react to events emitted by other AWS services.
-
-For example, you can write code that processes new SQS events, SNS messages, new uploaded files on S3, DynamoDb insert and update events, etc.
-
-This can be achieve by configuring which events will trigger your function via `serverless.yml`. Learn more about this [in the Serverless documentation](https://serverless.com/framework/docs/providers/aws/events/).
diff --git a/docs/runtimes/function.mdx b/docs/runtimes/function.mdx
new file mode 100644
index 000000000..3f6e73d15
--- /dev/null
+++ b/docs/runtimes/function.mdx
@@ -0,0 +1,277 @@
+import { Callout, Tab, Tabs } from 'nextra/components';
+import { NextSeo } from 'next-seo';
+
+
+
+# PHP functions runtime for AWS Lambda
+
+Bref's **"Event-driven function" runtime** lets you run PHP functions on AWS Lambda.
+
+Unlike the [PHP-FPM runtime](./fpm-runtime.mdx), the function runtime does not use PHP-FPM. Instead, it invokes your PHP code directly with the AWS Lambda event.
+
+Here is an example of a PHP Lambda function written as an anonymous function:
+
+```php
+
+ If you are creating HTTP applications, the [PHP-FPM runtime](./fpm-runtime.mdx) is a simpler option.
+
+
+## Usage
+
+To deploy a PHP function on AWS Lambda, use the `php-xx` runtime:
+
+```yaml
+service: app
+provider:
+ name: aws
+plugins:
+ - ./vendor/bref/bref
+functions:
+ hello:
+ handler: my-function.php
+ runtime: php-81
+```
+
+## PHP functions
+
+Functions that can run on Lambda can be an anonymous function or [any kind of callable supported by PHP](https://www.php.net/manual/en/language.types.callable.php).
+
+```php
+
+
+ Set the class name as the `handler` and Bref will retrieve that class from Laravel's service container.
+
+ ```yml filename="serverless.yml"
+ functions:
+ hello:
+ handler: MyApp\Handler
+ ```
+
+
+ Set the class name as the `handler` and Bref will retrieve that class from Symfony's service container.
+
+ ```yml filename="serverless.yml"
+ functions:
+ hello:
+ handler: MyApp\Handler
+ ```
+
+
+ To achieve that, you must integrate Bref with your framework's Dependency Injection Container.
+
+ First, create a file (for example `init.php`) that calls `Bref::setContainer()`:
+
+ ```php
+
+
+
+## Invocation
+
+A PHP function must be invoked via the AWS Lambda API, either manually or by integrating with other AWS services.
+
+
+ If you instead want to write a classic **HTTP application**, use the [PHP-FPM runtime](./fpm-runtime.mdx) instead.
+
+
+### CLI
+
+A PHP function can be triggered manually from the CLI using the [`serverless invoke` command](https://serverless.com/framework/docs/providers/aws/cli-reference/invoke/):
+
+```bash
+$ serverless invoke -f
+# The function name is the one in serverless.yml, in our example that would be `hello`:
+$ serverless invoke -f hello
+"Hello world"
+```
+
+To pass event data to the lambda use the `--data` option. For example:
+
+```bash
+serverless invoke -f --data='{"name": "John" }'
+```
+
+Run `serverless invoke --help` to learn more about the `invoke` command.
+
+### From PHP applications
+
+A PHP function can be triggered from another PHP application using the AWS PHP SDK:
+
+You first need to install the AWS PHP SDK by running
+
+```bash
+$ composer require aws/aws-sdk-php
+```
+
+```php
+$lambda = new \Aws\Lambda\LambdaClient([
+ 'version' => 'latest',
+ 'region' => '',
+]);
+
+$result = $lambda->invoke([
+ 'FunctionName' => '',
+ 'InvocationType' => 'RequestResponse',
+ 'LogType' => 'None',
+ 'Payload' => json_encode(/* event data */),
+]);
+
+$result = json_decode($result->get('Payload')->getContents(), true);
+```
+
+
+ A lighter alternative to the official AWS PHP SDK is the [AsyncAws Lambda](https://async-aws.com/clients/lambda.html) package.
+
+
+### From other AWS services
+
+Functions are perfect to react to events emitted by other AWS services.
+
+For example, you can write code that processes new SQS events, SNS messages, new uploaded files on S3, DynamoDb insert and update events, etc.
+
+Plenty of examples are available in the "Use cases" section in the menu, get started there!
diff --git a/docs/runtimes/http.md b/docs/runtimes/http.md
deleted file mode 100644
index 0258751cf..000000000
--- a/docs/runtimes/http.md
+++ /dev/null
@@ -1,153 +0,0 @@
----
-title: Web applications on AWS Lambda
-current_menu: web-apps
-introduction: Learn how to run serverless HTTP applications with PHP on AWS Lambda using Bref.
-previous:
- link: /docs/runtimes/
- title: PHP runtimes for AWS Lambda
-next:
- link: /docs/websites.html
- title: Website assets
----
-
-To run HTTP APIs and websites on AWS Lambda, Bref runs your code **using PHP-FPM**. That means PHP applications can run on Lambda just like on any other PHP hosting platform.
-
-That's great: we can use our favorite framework as usual, like **Laravel or Symfony**.
-
-If you are interested in the details, know that AWS Lambda can react to HTTP requests via [API Gateway](https://aws.amazon.com/api-gateway/). On Lambda, Bref forwards API Gateway requests to PHP-FPM via the FastCGI protocol (just like Apache or Nginx).
-
-> Every code we deploy on AWS Lambda is called a "Function". Do not let this name confuse you: in this chapter, we do deploy HTTP **applications** in a Lambda Function.
->
-> In the Lambda world, an HTTP application is a *function* that is called by a request and returns a response. Good news: this is exactly what our PHP applications do.
-
-## Setup
-
-Below is a minimal `serverless.yml` configuration to deploy an HTTP application:
-
-```yaml
-service: app
-provider:
- name: aws
- runtime: provided.al2
-plugins:
- - ./vendor/bref/bref
-functions:
- app:
- handler: index.php
- runtime: php-81-fpm
- events:
- - httpApi: '*'
-```
-
-To create it automatically, run `vendor/bin/bref init` and select "Web application".
-
-## Handler
-
-The *handler* is the file that will be invoked when an HTTP request comes in.
-
-It is the same file that is traditionally configured in Apache or Nginx. In Symfony and Laravel this is usually `public/index.php` but it can be anything.
-
-```yaml
-functions:
- app:
- handler: public/index.php
-```
-
-## Runtime
-
-For web apps, the runtime to use is the **FPM** runtime (`php-81-fpm`):
-
-```yaml
-functions:
- app:
- runtime: php-81-fpm
-```
-
-To learn more check out [the runtimes documentation](/docs/runtimes/README.md).
-
-## Routing
-
-On AWS Lambda there is no Apache or Nginx. API Gateway acts as the webserver.
-
-The simplest API Gateway configuration is to send all incoming requests to our application:
-
-```yaml
- events:
- - httpApi: '*'
-```
-
-### Assets
-
-Lambda and API Gateway are only used for executing code. Serving assets via PHP does not make sense as this would be a waste of resources and money.
-
-Deploying a website and serving assets (e.g. CSS, JavaScript, images) is covered in [the "Website assets" documentation](/docs/websites.md).
-
-In some cases however, you will need to serve images (or other assets) via PHP. One example would be if you served generated images via PHP. In those cases, you need to read the [Binary requests and responses](#binary-requests-and-responses) section below.
-
-## Binary requests and responses
-
-By default API Gateway **does not support binary HTTP requests or responses** like
-images, PDF, binary files… To achieve this, you need to enable the option for binary
-media types in `serverless.yml` as well as define the `BREF_BINARY_RESPONSES` environment
-variable:
-
-```yaml
-provider:
- # ...
- apiGateway:
- binaryMediaTypes:
- - '*/*'
- environment:
- BREF_BINARY_RESPONSES: '1'
-```
-
-This will make API Gateway support binary file uploads and downloads, and Bref will
-automatically encode responses to base64 (which is what API Gateway now expects).
-
-Be aware that the max upload and download size is 6MB.
-For larger files, use AWS S3.
-An example is available in [Serverless Visually Explained](https://serverless-visually-explained.com/).
-
-## Context access
-
-### Lambda context
-
-Lambda provides information about the invocation, function, and execution environment via the *lambda context*.
-
-Bref exposes the Lambda context in the `$_SERVER['LAMBDA_INVOCATION_CONTEXT']` variable as a JSON-encoded string.
-Here is an example to retrieve it:
-
-```php
-$lambdaContext = json_decode($_SERVER['LAMBDA_INVOCATION_CONTEXT'], true);
-```
-
-### Request context
-
-API Gateway integrations can add information to the HTTP request via the *request context*.
-This is the case, for example, when using AWS Cognito authentication on API Gateway.
-
-Bref exposes the request context in the `$_SERVER['LAMBDA_REQUEST_CONTEXT']` variable as a JSON-encoded string.
-Here is an example to retrieve it:
-
-```php
-$requestContext = json_decode($_SERVER['LAMBDA_REQUEST_CONTEXT'], true);
-```
-
-## Cold starts
-
-AWS Lambda automatically destroys Lambda containers that have been unused for 10 minutes. Warming up a new container can take some time, especially if your application is large. This delay is called [cold start](https://mikhail.io/serverless/coldstarts/aws/).
-
-To mitigate cold starts for HTTP applications, you can periodically send an event to your Lambda including a `{warmer: true}` key. Bref recognizes this event and immediately responds with a `Status: 100` without executing your code.
-
-You can set up such events using AWS CloudWatch ([read this article for more details](https://www.jeremydaly.com/lambda-warmer-optimize-aws-lambda-function-cold-starts/)):
-
-```yaml
- events:
- - httpApi: '*'
- - schedule:
- rate: rate(5 minutes)
- input:
- warmer: true
-```
-
-You can learn more how AWS Lambda scales and runs in the [Serverless Visually Explained](https://serverless-visually-explained.com/) course.
diff --git a/docs/runtimes/runtimes-details.mdx b/docs/runtimes/runtimes-details.mdx
new file mode 100644
index 000000000..b06e3b3b7
--- /dev/null
+++ b/docs/runtimes/runtimes-details.mdx
@@ -0,0 +1,138 @@
+import { Callout } from 'nextra/components';
+
+# Runtimes in details
+
+
+ This section is only useful if you want to learn more, or if you want to use Bref with another deployment tool than Serverless Framework.
+
+ You can skip it for now if you just want to get started with Bref.
+
+
+## AWS Lambda layers
+
+Bref runtimes are distributed as [AWS Lambda layers](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html). While Bref provides a Serverless plugin to simplify how to use them, you can use the layers directly.
+
+The layer names (aka "[ARN](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference-arns.html)") follow this pattern:
+
+```
+arn:aws:lambda::534081306603:layer::
+```
+
+For example:
+```
+arn:aws:lambda:us-east-1:534081306603:layer:php-80:21
+```
+
+You can use layers via their full ARN, for example in `serverless.yml`:
+
+```yml filename="serverless.yml" {9}
+service: app
+provider:
+ name: aws
+functions:
+ hello:
+ # ...
+ runtime: provided.al2
+ layers:
+ - 'arn:aws:lambda:us-east-1:534081306603:layer:php-80:21'
+```
+
+Or if you are using [SAM's `template.yaml`](https://aws.amazon.com/serverless/sam/):
+
+```yml filename="template.yml"
+AWSTemplateFormatVersion: '2010-09-09'
+Transform: AWS::Serverless-2016-10-31
+Resources:
+ Hello:
+ Type: AWS::Serverless::Function
+ Properties:
+ # ...
+ Runtime: provided.al2
+ Layers:
+ - 'arn:aws:lambda:us-east-1:534081306603:layer:php-80:21'
+```
+
+Bref layers work with AWS Lambda regardless of the tool you use to deploy your application: Serverless, SAM, CloudFormation, Terraform, AWS CDK, etc.
+
+
+ Remember: the layer ARN contains a region. **You need to use the same region as the rest of your application** else Lambda will not find the layer.
+
+
+## Layer versions
+
+All the layer/runtime versions can be found at [**runtimes.bref.sh**](https://runtimes.bref.sh/).
+
+Here are the latest versions:
+
+
+
+You can also find the appropriate ARN/version for your current Bref version by running:
+
+```bash
+serverless bref:layers
+```
+
+
+ If you use a layer ARN directly, you will need to update the ARN regularly (the `version` part).
+
+
+### Layers NPM package
+
+You can use [the `@bref.sh/layers.js` NPM package](https://github.com/brefphp/layers.js) to get up-to-date layer ARNs in Node applications, for example with the AWS CDK.
+
+## Telemetry ping
+
+Bref layers send an anonymous ping to estimate the total number of Lambda invocations powered by Bref. That statistic is useful in two ways:
+
+- to provide new users an idea on how much Bref is used in production
+- to communicate to AWS how much Bref is used and push for better PHP integration with AWS Lambda tooling
+
+We consider this to be beneficial both to the Bref project (to get more users and more consideration from AWS) and for Bref users (more users means a larger community, a stronger and more active project, as well as more features from AWS).
+
+So far, knowing the number of Bref invocations has helped Bref grow, be recognized by AWS, and opened a lot of doors.
+
+### Data
+
+On the month of the Bref 1.0 release, [Bref was powering 1 billion invocations per month](../../news/01-bref-1.0.md#1-billion-executions-per-month).
+
+On the month of the Bref 2.0 release, [Bref was powering 10 billion invocations per month](../../news/02-bref-2.0.md).
+
+### What is sent
+
+The data sent in the ping is completely anonymous. It does not contain any identifiable data about anything (the project, users, etc.).
+
+**The only data it contains is:** "A Bref invocation happened with the layer XYZ" (where XYZ is the name of the Bref layer, like "function", "fpm" or "console").
+
+Here is an example payload:
+
+```
+Invocations_100:1|c\nLayer_fpm_100:1|c
+```
+
+Anyone can inspect the code and the data sent by checking the [`Bref\Runtime\LambdaRuntime::ping()` function](https://github.com/brefphp/bref/blob/master/src/Runtime/LambdaRuntime.php#L374).
+
+### How is it sent
+
+The data is sent via the [statsd](https://github.com/statsd/statsd) protocol, over [UDP](https://en.wikipedia.org/wiki/User_Datagram_Protocol).
+
+Unlike TCP, UDP does not check that the message correctly arrived to the server.
+It doesn't even establish a connection. That means that **UDP is extremely fast**:
+the data is sent over the network and the code moves on to the next line.
+When actually sending data, the overhead of that ping takes about 150 micro-seconds.
+
+However, this function actually sends data every 100 invocation, because we don't
+need to measure *all* invocations. We only need an approximation.
+That means that 99% of the time, no data is sent, and the function takes 30 micro-seconds.
+If we average all executions, the overhead of that ping is about **31 micro-seconds**.
+
+Given that it is much much less than even 1 milli-second, we consider that overhead negligible.
+
+### Disabling
+
+The ping can be disabled by setting a `BREF_PING_DISABLE` environment variable to `1`.
+
+
+ If your company policy requires disabling the ping, it would be extremely beneficial to the project (and transitively to your company) to report privately a rough number of invocations. You can send me a direct email at [matthieu@bref.sh](mailto:matthieu@bref.sh).
+
+ Such data is collected privately and is not shared publicly on its own. I include it in the total number of invocations that I share publicly.
+
diff --git a/docs/serverless-costs.mdx b/docs/serverless-costs.mdx
new file mode 100644
index 000000000..0db87c3a0
--- /dev/null
+++ b/docs/serverless-costs.mdx
@@ -0,0 +1,304 @@
+import { useState } from 'react';
+import { NextSeo } from 'next-seo';
+
+
+
+# Costs of a serverless application
+
+Unlike traditional hosting, serverless hosting is billed based on usage. This means that you only pay for what you use, **down to the request**.
+
+To be clear, this means that if your application is not used, you don't pay anything.
+
+On AWS Lambda, you pay for:
+
+- the number of requests
+- the duration of the requests (the time it takes to execute your code)
+
+There are no costs when the PHP application is waiting between requests (or jobs, events, etc.). It doesn't matter if AWS Lambda scaled your functions up to several instances (containers), you only pay for the requests and the duration of the requests.
+
+For some use cases it has interesting consequences: 1 job running for 10 minutes has about the same costs as 600 jobs running for 1 second in parallel.
+
+## Costs calculator
+
+Use the calculator below to estimate the costs of running your PHP application serverless on AWS Lambda.
+
+
+
+export function Calculator() {
+ const lambdaFreeTierRequests = 1000000;
+ const lambdaFreeTierDuration = 400000;
+ const lambdaCostPerRequest = 0.2 / 1000000;
+ const lambdaCostPerGbS = 0.0000133334; // ARM
+
+ const apiGatewayFreeTierRequests = 1000000;
+ const apiGatewayCostPerRequest = 1 / 1000000;
+
+ const cloudfrontFreeTierRequests = 10000000;
+ const cloudfrontFreeTierBandwidth = 1000;
+ const cloudfrontCostPerRequest = 0.012 / 10000;
+ const cloudfrontCostPerGb = 0.085;
+
+ const s3FreeRequests = 20000;
+ const s3CostPerRequest = 0.0004 / 1000;
+
+ const sqsFreeTierRequests = 1000000;
+ const sqsCostPerRequest = 0.4 / 1000000;
+
+ const rdsStorageFreeTier = 20;
+ const rdsStorageCostPerGb = 0.115;
+ const rdsInstanceCost = {
+ 'db.t4g.micro': 0.016,
+ 'db.t4g.small': 0.032,
+ 'db.t4g.medium': 0.065,
+ 'db.t4g.large': 0.129,
+ 'db.t4g.xlarge': 0.258,
+ 'db.t4g.2xlarge': 0.517,
+ };
+ const rdsInstanceDescription = {
+ 'db.t4g.micro': '1 vCPU, 1GB RAM',
+ 'db.t4g.small': '1 vCPU, 2GB RAM',
+ 'db.t4g.medium': '2 vCPU, 4GB RAM',
+ 'db.t4g.large': '2 vCPU, 8GB RAM',
+ 'db.t4g.xlarge': '4 vCPU, 16GB RAM',
+ 'db.t4g.2xlarge': '8 vCPU, 32GB RAM',
+ };
+ const natGatewayCost = 0.045 * 24 * 30;
+ const natInstanceCost = 0.0042 * 24 * 30;
+
+ const [ httpRequests, setHttpRequests ] = useState(100000);
+ const [ httpDuration, setHttpDuration ] = useState(100);
+ const [ assetsRequests, setAssetsRequests ] = useState(0);
+ const [ bandwidth, setBandwidth ] = useState(0);
+ const [ cacheHit, setCacheHit ] = useState(90);
+ const [ jobs, setJobs ] = useState(0);
+ const [ database, setDatabase ] = useState(undefined);
+ const [ databaseSize, setDatabaseSize ] = useState(20);
+ const [ natType, setNatType ] = useState('natInstance');
+ const [ jobDuration, setJobDuration ] = useState(50);
+
+ // Calculate costs
+ const lambdaInvocations = Number(httpRequests) + Number(jobs);
+ const lambdaGbS = httpRequests * httpDuration / 1000 + jobs * jobDuration / 1000;
+ const lambdaCost = Math.max(0, (lambdaInvocations - lambdaFreeTierRequests) * lambdaCostPerRequest)
+ + Math.max(0, (lambdaGbS - lambdaFreeTierDuration) * lambdaCostPerGbS);
+ const apiGatewayCost = Math.max(0, (httpRequests - apiGatewayFreeTierRequests) * apiGatewayCostPerRequest);
+ const cloudfrontRequestsCost = Math.max(0, (assetsRequests - cloudfrontFreeTierRequests) * cloudfrontCostPerRequest);
+ const cloudfrontBandwidthCost = Math.max(0, (bandwidth - cloudfrontFreeTierBandwidth) * cloudfrontCostPerGb);
+ const cloudfrontCost = cloudfrontRequestsCost + cloudfrontBandwidthCost;
+ const requestsHittingS3 = assetsRequests * cacheHit / 100;
+ const s3Cost = Math.max(0, (requestsHittingS3 - s3FreeRequests) * s3CostPerRequest);
+ const numberOfSqsRequestsPerJob = 3; // Send, receive, delete
+ const sqsCost = Math.max(0, (jobs * numberOfSqsRequestsPerJob - sqsFreeTierRequests) * sqsCostPerRequest);
+ const rdsCost = database ? rdsInstanceCost[database] * 24 * 30 + Math.max(0, (databaseSize - rdsStorageFreeTier) * rdsStorageCostPerGb) : 0;
+ const natCost = (database && natType) ? (natType === 'natInstance' ? natInstanceCost : natGatewayCost) : 0;
+
+ const totalCost = lambdaCost + apiGatewayCost + cloudfrontCost + s3Cost + sqsCost + rdsCost + natCost;
+
+ function smallApi() {
+ setHttpRequests(100000);
+ setHttpDuration(100);
+ setAssetsRequests(0);
+ setBandwidth(0);
+ }
+ function largeApi() {
+ setHttpRequests(5000000);
+ setHttpDuration(100);
+ setAssetsRequests(0);
+ setBandwidth(0);
+ }
+ function smallWebsite() {
+ setHttpRequests(100000);
+ setHttpDuration(200);
+ setAssetsRequests(100000);
+ setBandwidth(2);
+ setCacheHit(90);
+ }
+ function largeWebsite() {
+ setHttpRequests(5000000);
+ setHttpDuration(200);
+ setAssetsRequests(5000000);
+ setBandwidth(100);
+ setCacheHit(90);
+ }
+
+ return (
+
+ CloudFront costs can vary depending on the use case (e.g. number and size of assets, serving images, streaming videos…).
+ Browser caching can be used to reduce costs on high traffic websites.
+ Cloudflare can also be considered as an alternative to CloudFront.
+
+ Costs vary depending on the use case. Aurora Serverless can be considered, as well as reserved RDS instances for lower costs.
+ {' '}
+ PlanetScale can also be considered as an alternative to RDS.
+
+ NAT Gateway is necessary when using a database in a private VPC (virtual network).
+ Data transfer cost is excluded.
+
}
+
+
+
+
+ Total AWS costs
+
+
+ ${totalCost.toFixed(2)}/month
+
+
+
+
+ The calculator takes into account the AWS free tier (except the free tier that expires after 12 months).
+ It uses prices for the us-east-1 region. Other regions can have slightly higher costs (a few percents usually).
+
+
+ Costs can vary at scale and can be optimized in numerous ways.
+ For a cost-optimized architecture tailored to your needs, get in touch.
+
+ )
+}
diff --git a/website/src/components/home/companies/20minutes.svg b/website/src/components/home/companies/20minutes.svg
new file mode 100644
index 000000000..6d825e44e
--- /dev/null
+++ b/website/src/components/home/companies/20minutes.svg
@@ -0,0 +1,17 @@
+
\ No newline at end of file
diff --git a/website/src/components/home/companies/bcast.svg b/website/src/components/home/companies/bcast.svg
new file mode 100644
index 000000000..a58487e56
--- /dev/null
+++ b/website/src/components/home/companies/bcast.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/website/src/components/home/companies/enoptea.png b/website/src/components/home/companies/enoptea.png
new file mode 100644
index 000000000..68a6501a6
Binary files /dev/null and b/website/src/components/home/companies/enoptea.png differ
diff --git a/website/src/components/home/companies/gulli.svg b/website/src/components/home/companies/gulli.svg
new file mode 100644
index 000000000..b9615c66d
--- /dev/null
+++ b/website/src/components/home/companies/gulli.svg
@@ -0,0 +1,95 @@
+
+
+
+
diff --git a/website/src/components/home/companies/mybuilder.svg b/website/src/components/home/companies/mybuilder.svg
new file mode 100644
index 000000000..0ac98d60d
--- /dev/null
+++ b/website/src/components/home/companies/mybuilder.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/website/src/components/home/companies/neural-love.svg b/website/src/components/home/companies/neural-love.svg
new file mode 100644
index 000000000..1222f3f3f
--- /dev/null
+++ b/website/src/components/home/companies/neural-love.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/website/src/components/home/companies/phpstan.svg b/website/src/components/home/companies/phpstan.svg
new file mode 100644
index 000000000..6fbaf5c74
--- /dev/null
+++ b/website/src/components/home/companies/phpstan.svg
@@ -0,0 +1,30 @@
+
\ No newline at end of file
diff --git a/website/src/components/home/intro.jsx b/website/src/components/home/intro.jsx
new file mode 100644
index 000000000..2211960d7
--- /dev/null
+++ b/website/src/components/home/intro.jsx
@@ -0,0 +1,92 @@
+import { CloudArrowUpIcon, PresentationChartLineIcon, BanknotesIcon } from '@heroicons/react/20/solid'
+
+const features = [
+ {
+ name: 'Simple.',
+ description:
+ 'Instead of setting up and maintaining servers, define your application in a simple serverless.yml file. Then deploy to AWS with serverless deploy. Bref integrates with the Serverless Framework for a great developer experience.',
+ icon: CloudArrowUpIcon,
+ },
+ {
+ name: 'Scalable.',
+ description: 'Bref provides open-source runtimes to run PHP on AWS Lambda. AWS Lambda runs your code redundantly across data centers and scales in real-time. All automatically. Handle 1 request/second or 1000 with the same code.',
+ icon: PresentationChartLineIcon,
+ },
+ {
+ name: 'Cost-efficient.',
+ description: 'Instead of paying for servers that are idle most of the time, pay for the time the code is actually running. The AWS free tier even provides about 1 million free requests per month. Play with the serverless costs calculator.',
+ icon: BanknotesIcon,
+ },
+]
+
+export default function Intro() {
+ const date = new Date();
+ const year = date.getFullYear();
+
+ return (
+
+
+
+
+
+ Why Bref? Why serverless?
+
+
+ We're in {year}.
+ Applications should scale automatically.
+ Hosting should be reliable and cost-efficient.
+ Infrastructure should accelerate development, not consume our time.
+
+
+ Bref deploys PHP applications to {' '}
+ AWS Lambda {' '}
+ and sets up the rest of the infrastructure using serverless services.
+
}
+
+ );
+}
diff --git a/website/src/components/home/testimonials.jsx b/website/src/components/home/testimonials.jsx
new file mode 100644
index 000000000..7362413f2
--- /dev/null
+++ b/website/src/components/home/testimonials.jsx
@@ -0,0 +1,141 @@
+import Image from 'next/image';
+import neil from './testimonials/neil.jpg';
+import geeh from './testimonials/geeh.jpg';
+import paul from './testimonials/paul.jpg';
+import marco from './testimonials/marco.jpg';
+import robdwaller from './testimonials/robdwaller.jpg';
+import aranreeks from './testimonials/aranreeks.jpg';
+import nyholm from './testimonials/nyholm.jpg';
+import zmalter from './testimonials/zmalter.jpg';
+import simon from './testimonials/simon.jpg';
+import lorenzo from './testimonials/lorenzo.jpg';
+
+const testimonials = [
+ {
+ body: 'Bref is excellent. We\'ve been running a Laravel app with it since 2020 and it\'s currently handling over 160 million requests per month without a hiccup.',
+ author: {
+ name: 'Neil Morgan',
+ handle: 'neil-r-morgan',
+ link: 'https://www.linkedin.com/in/neil-r-morgan/',
+ image: neil,
+ },
+ },
+ {
+ body: 'Bref has been a boon for running our customer\'s applications. We\'ve had a Laravel API on Bref for the last 12 months serve over 25 million requests with an average response time of 50ms.',
+ author: {
+ name: 'Paul Giberson',
+ handle: 'HalasLabs',
+ link: 'https://twitter.com/HalasLabs/status/1638650910971932672',
+ image: paul,
+ },
+ },
+ {
+ body: 'Every time I throw something up onto AWS Lambda in PHP using Bref I marvel at how mega-useful it is. If you haven’t checked out Bref you’re probably missing out',
+ author: {
+ name: 'Gary Hockin',
+ handle: 'GeeH',
+ link: 'https://twitter.com/GeeH/status/1335909653897752576',
+ image: geeh,
+ },
+ },
+ {
+ body: 'Just finished migrating our production from Heroku to AWS Lambda via Bref. It\'ll save us around $2k a year 🤯',
+ author: {
+ name: 'Zach Malter',
+ handle: 'zmalter99',
+ link: 'https://twitter.com/zmalter99/status/1671228229317689367',
+ image: zmalter,
+ },
+ },
+ {
+ body: 'When your production website with Symfony, API Platform and Bref handles more than 500 simultaneous connections without flinching…',
+ author: {
+ name: '$!m0n',
+ handle: '__si_mon',
+ link: 'https://twitter.com/__si_mon/status/1616778693212348416',
+ image: simon,
+ },
+ },
+ {
+ body: 'I’ve been running APIs and websites with Bref in prod for over a year now. It is indeed as simple as you describe it.',
+ author: {
+ name: 'Tobias Nyholm',
+ handle: 'TobiasNyholm',
+ link: 'https://twitter.com/TobiasNyholm/status/1292027581986934785',
+ image: nyholm,
+ },
+ },
+ {
+ body: 'There is something amazing and magical about Bref and serverless deploying stuff to the cloud.',
+ author: {
+ name: 'Rob Waller',
+ handle: 'RobDWaller',
+ link: 'https://twitter.com/RobDWaller/status/1484569852694118406',
+ image: robdwaller,
+ },
+ },
+ {
+ body: 'Happily using Bref since 2019 to process millions of requests, jobs and scheduled tasks. It powers the best technical accomplishment of my career and has made me a better software engineer and open-source contributor.',
+ author: {
+ name: 'Marco Deleu',
+ handle: 'deleugyn',
+ link: 'https://twitter.com/deleugyn',
+ image: marco,
+ },
+ },
+ {
+ body: 'The team embraced Bref with lightning speed! We were able to roll out the first parts of our new event-driven architecture within days, crafting new features in a mere fraction of the time it used to take — truly mind-blowing!',
+ author: {
+ name: 'Lorenzo Rogai',
+ handle: 'lorenzo-rogai',
+ link: 'https://www.linkedin.com/in/lorenzo-rogai/',
+ image: lorenzo,
+ },
+ },
+ {
+ body: 'An incredible project and one we\'re very proud to use in production for a recent eCommerce project we launched that saw 32 million Lambda invocations last month.',
+ author: {
+ name: 'Aran Reeks',
+ handle: 'AranReeks',
+ link: 'https://twitter.com/AranReeks/status/1332467843254919168',
+ image: aranreeks,
+ },
+ },
+ // More testimonials...
+]
+
+export default function Testimonials() {
+ return (
+
+
+ Happy users and community
+
+
+
+ {testimonials.map((testimonial) => (
+
+
+
+ ))}
+
+
+
+ )
+}
diff --git a/website/src/components/home/testimonials/aranreeks.jpg b/website/src/components/home/testimonials/aranreeks.jpg
new file mode 100644
index 000000000..b4d9910e3
Binary files /dev/null and b/website/src/components/home/testimonials/aranreeks.jpg differ
diff --git a/website/src/components/home/testimonials/geeh.jpg b/website/src/components/home/testimonials/geeh.jpg
new file mode 100644
index 000000000..6be1b99a4
Binary files /dev/null and b/website/src/components/home/testimonials/geeh.jpg differ
diff --git a/website/src/components/home/testimonials/lorenzo.jpg b/website/src/components/home/testimonials/lorenzo.jpg
new file mode 100644
index 000000000..8b9ac3426
Binary files /dev/null and b/website/src/components/home/testimonials/lorenzo.jpg differ
diff --git a/website/src/components/home/testimonials/marco.jpg b/website/src/components/home/testimonials/marco.jpg
new file mode 100644
index 000000000..e3dbe052a
Binary files /dev/null and b/website/src/components/home/testimonials/marco.jpg differ
diff --git a/website/src/components/home/testimonials/neil.jpg b/website/src/components/home/testimonials/neil.jpg
new file mode 100644
index 000000000..62ef2c504
Binary files /dev/null and b/website/src/components/home/testimonials/neil.jpg differ
diff --git a/website/src/components/home/testimonials/nyholm.jpg b/website/src/components/home/testimonials/nyholm.jpg
new file mode 100644
index 000000000..35adcba00
Binary files /dev/null and b/website/src/components/home/testimonials/nyholm.jpg differ
diff --git a/website/src/components/home/testimonials/paul.jpg b/website/src/components/home/testimonials/paul.jpg
new file mode 100644
index 000000000..463a03a6e
Binary files /dev/null and b/website/src/components/home/testimonials/paul.jpg differ
diff --git a/website/src/components/home/testimonials/robdwaller.jpg b/website/src/components/home/testimonials/robdwaller.jpg
new file mode 100644
index 000000000..6e0cd6857
Binary files /dev/null and b/website/src/components/home/testimonials/robdwaller.jpg differ
diff --git a/website/src/components/home/testimonials/simon.jpg b/website/src/components/home/testimonials/simon.jpg
new file mode 100644
index 000000000..2e3917373
Binary files /dev/null and b/website/src/components/home/testimonials/simon.jpg differ
diff --git a/website/src/components/home/testimonials/zmalter.jpg b/website/src/components/home/testimonials/zmalter.jpg
new file mode 100644
index 000000000..ed4cbf403
Binary files /dev/null and b/website/src/components/home/testimonials/zmalter.jpg differ
diff --git a/website/src/components/home/use-cases.jsx b/website/src/components/home/use-cases.jsx
new file mode 100644
index 000000000..fba03d934
--- /dev/null
+++ b/website/src/components/home/use-cases.jsx
@@ -0,0 +1,93 @@
+import { CheckIcon } from '@heroicons/react/20/solid';
+
+const simpleUseCases = [
+ {
+ name: 'Websites',
+ description: 'Run PHP websites with Laravel, Symfony or any other framework, with a worldwide CDN and your custom domain.'
+ },
+ {
+ name: 'HTTP APIs',
+ description: 'REST or GraphQL APIs deployed in seconds. Need more performance? Enable Laravel Octane or the Symfony equivalent.'
+ },
+ {
+ name: 'CLI commands',
+ description: 'Run DB migrations, admin commands, or any other CLI command from your machine or your CI/CD.'
+ },
+ {
+ name: 'Cron tasks',
+ description: 'Every day, every hour, every minute… Run CLI scripts, Symfony Console commands, or the Laravel Scheduler.'
+ },
+];
+
+const advancedUseCases = [
+ {
+ name: 'Job queues',
+ description: 'Run 1000 jobs with 1 worker in 1000 seconds, or with 1000 workers in 1 second. It\'s just as simple and it costs the same. SQS invokes your code directly, no long-running process to maintain.'
+ },
+ {
+ name: 'Event-driven microservices',
+ description: 'Decouple and scale microservices without container madness. Send messages to EventBridge and let it invoke your PHP classes directly. No integration to write.'
+ },
+ {
+ name: 'File processing',
+ description: 'S3 can invoke a PHP class whenever a new file is uploaded. Resize images, convert videos, generate PDFs…'
+ },
+ {
+ name: 'WebSockets',
+ description: 'AWS API Gateway manages the WebSocket connections for you. Send messages to your users in real-time.'
+ },
+];
+
+export default function UseCases() {
+ return (
+
+
+
+
Use cases
+
+ Serverless means whatever you choose it to mean.
+
+
+ Run PHP as usual, {' '}like on any server.
+ Except it scales (almost) infinitely and you don't maintain the infrastructure.
+ Lift-and-shift existing apps or build new ones with your favorite framework.
+
+
+
+ {simpleUseCases.map((feature) => (
+
+
+
+ {feature.name}
+
+
+
+ ))}
+
+
+
+
+
+ Or go the extreme opposite: build {' '}event-driven microservices with infinitely scalable cloud services like SQS and EventBridge.
+
+
+ Or anything in between, that works too.
+
+
+
+ {advancedUseCases.map((feature) => (
+
+
+
+ {feature.name}
+
+
+
+ ))}
+
+
+
+ );
+}
diff --git a/website/src/components/icons/GitHubIcon.jsx b/website/src/components/icons/GitHubIcon.jsx
new file mode 100644
index 000000000..a048e2648
--- /dev/null
+++ b/website/src/components/icons/GitHubIcon.jsx
@@ -0,0 +1,7 @@
+export function GitHubIcon({ children, ...props }) {
+ return ;
+}
diff --git a/website/src/components/icons/LaravelFullIcon.jsx b/website/src/components/icons/LaravelFullIcon.jsx
new file mode 100644
index 000000000..37e00a2cd
--- /dev/null
+++ b/website/src/components/icons/LaravelFullIcon.jsx
@@ -0,0 +1,5 @@
+export function LaravelFullIcon({children, ...props}) {
+ return
+}
diff --git a/website/src/components/icons/LaravelIcon.jsx b/website/src/components/icons/LaravelIcon.jsx
new file mode 100644
index 000000000..e3e82fa49
--- /dev/null
+++ b/website/src/components/icons/LaravelIcon.jsx
@@ -0,0 +1,6 @@
+export function LaravelIcon() {
+ return
+}
diff --git a/website/src/components/icons/SlackIcon.jsx b/website/src/components/icons/SlackIcon.jsx
new file mode 100644
index 000000000..3d9acf3bc
--- /dev/null
+++ b/website/src/components/icons/SlackIcon.jsx
@@ -0,0 +1,3 @@
+export function SlackIcon({children, ...props}) {
+ return
+}
diff --git a/website/src/components/icons/SymfonyFullIcon.jsx b/website/src/components/icons/SymfonyFullIcon.jsx
new file mode 100644
index 000000000..aae6f4cbb
--- /dev/null
+++ b/website/src/components/icons/SymfonyFullIcon.jsx
@@ -0,0 +1,10 @@
+export function SymfonyFullIcon({children, ...props}) {
+ return
+}
diff --git a/website/src/components/icons/SymfonyIcon.jsx b/website/src/components/icons/SymfonyIcon.jsx
new file mode 100644
index 000000000..0aee8d3ab
--- /dev/null
+++ b/website/src/components/icons/SymfonyIcon.jsx
@@ -0,0 +1,8 @@
+export function SymfonyIcon() {
+ return
+}
diff --git a/website/src/components/icons/TwitterIcon.jsx b/website/src/components/icons/TwitterIcon.jsx
new file mode 100644
index 000000000..4e62c1808
--- /dev/null
+++ b/website/src/components/icons/TwitterIcon.jsx
@@ -0,0 +1,6 @@
+export function TwitterIcon({children, ...props}) {
+ return ;
+}
diff --git a/website/src/components/logo.svg b/website/src/components/logo.svg
new file mode 100644
index 000000000..5f12c54e8
--- /dev/null
+++ b/website/src/components/logo.svg
@@ -0,0 +1,5 @@
+
diff --git a/website/src/components/news/ArticleHeader.jsx b/website/src/components/news/ArticleHeader.jsx
new file mode 100644
index 000000000..3d7000014
--- /dev/null
+++ b/website/src/components/news/ArticleHeader.jsx
@@ -0,0 +1,15 @@
+export default function ArticleHeader({ subTitle, date, author, authorGitHub, ...props }) {
+ return
;
+}
\ No newline at end of file
diff --git a/website/src/components/sentry/sentry.png b/website/src/components/sentry/sentry.png
new file mode 100644
index 000000000..5778a1b01
Binary files /dev/null and b/website/src/components/sentry/sentry.png differ
diff --git a/website/src/components/support/plans.jsx b/website/src/components/support/plans.jsx
new file mode 100644
index 000000000..1e18c73d2
--- /dev/null
+++ b/website/src/components/support/plans.jsx
@@ -0,0 +1,240 @@
+import { Fragment } from 'react'
+import { CheckIcon, MinusIcon } from '@heroicons/react/20/solid'
+
+const tiers = [
+ {
+ name: 'OpenSource',
+ id: 'open-source',
+ href: '/docs/',
+ buttonText: 'Get Started',
+ priceMonthly: 'Free and Open Source',
+ description: 'Bref',
+ mostPopular: false,
+ },
+ {
+ name: 'Pro',
+ id: 'pro',
+ href: 'https://matthieunapoli.typeform.com/to/d2OoXKln',
+ buttonText: 'Get Started',
+ priceMonthly: 100,
+ description: 'Bref Pro',
+ mostPopular: true,
+ },
+ {
+ name: 'Enterprise',
+ id: 'enterprise',
+ href: 'mailto:enterprise@bref.sh?subject=Bref%20Enterprise',
+ buttonText: 'Get in touch',
+ priceMonthly: 'Get in touch',
+ description: 'Bref Enterprise',
+ mostPopular: false,
+ },
+]
+const sections = [
+ {
+ name: 'Bref and AWS deployments',
+ features: [
+ { name: 'The Bref open-source project, its documentation and framework integrations', tiers: { OpenSource: true, Pro: true, Enterprise: true } },
+ { name: 'Deploy your applications to your AWS account', tiers: { OpenSource: true, Pro: true, Enterprise: true } },
+ { name: ' Tailor-made AWS Lambda runtimes and PHP extensions optimized for your project', tiers: { Enterprise: 'Optional' } },
+ { name: 'Appear as an open-source sponsor 💙', tiers: { Pro: 'Gold sponsor', Enterprise: 'Premium sponsor' } },
+ ],
+ },
+ {
+ name: 'Resources and support',
+ features: [
+ { name: 'Priority support and bugfixes on GitHub', tiers: { Pro: true, Enterprise: true } },
+ { name: 'Expert support via Slack and Email', tiers: { Pro: true, Enterprise: true } },
+ { name: 'Architecture design and review in Zoom', tiers: { Enterprise: true } },
+ { name: 'GitHub/GitLab infrastructure code review', tiers: { Enterprise: true } },
+ { name: 'Unlimited access to the Serverless Visually Explained course', tiers: { Enterprise: true } },
+ { name: 'Onboarding workshop online or on-site', tiers: { Enterprise: 'Optional' } },
+ ],
+ },
+]
+
+function classNames(...classes) {
+ return classes.filter(Boolean).join(' ')
+}
+
+export default function Plans() {
+ return (
+
+
+
+ Get more with Bref Pro and Enterprise
+
+
+
+ Bref is a free and open-source project hosted on GitHub.
+
+ Bref Pro and Bref Enterprise are support plans offered by Null, the company behind Bref.
+
+
+## [Bref 2.0 is released 🎉](./news/02-bref-2.0.md)
The work on what would be Bref 2.0 started in October 2021, about 1.5 year ago. We went through many different strategies, experiments, rewrites, over **700 commits** to finally land with the stable release.
@@ -16,9 +21,9 @@ Today, we celebrate these achievements, the ongoing work and **the release of Br
Let's dive in what's new in v2 👇
-[▶ Read more](02-bref-2.0.md)
+[▶ Read more](./news/02-bref-2.0.md)
-## [Bref 1.0 is released 🎉](01-bref-1.0.md)
+## [Bref 1.0 is released 🎉](./news/01-bref-1.0.md)
Bref started in November 2017, 3 years ago. Back then, running PHP on AWS Lambda was experimental at best.
@@ -28,4 +33,4 @@ Needless to say **Bref is stable** and has been for a long time.
Today, we're finally releasing **Bref 1.0**!
-[▶ Read more](01-bref-1.0.md)
+[▶ Read more](./news/01-bref-1.0.md)
diff --git a/docs/news/01-bref-1.0.md b/website/src/pages/news/01-bref-1.0.mdx
similarity index 85%
rename from docs/news/01-bref-1.0.md
rename to website/src/pages/news/01-bref-1.0.mdx
index 7738dd06b..91f899f0e 100644
--- a/docs/news/01-bref-1.0.md
+++ b/website/src/pages/news/01-bref-1.0.mdx
@@ -1,11 +1,15 @@
----
-title: Bref 1.0 is released 🎉
-subTitle: Celebrating 1 billion executions per month
-layout: news-article
-articleDate: November 2020
-author: Matthieu Napoli
-authorGithub: mnapoli
----
+import ArticleHeader from '../../components/news/ArticleHeader';
+import { NextSeo } from 'next-seo';
+
+
+
+# Bref 1.0 is released 🎉
+
+
Bref started in November 2017, 3 years ago. Back then, running PHP on AWS Lambda was experimental at best.
@@ -13,7 +17,7 @@ Over the years, as the Bref community grew, as AWS features landed, and as contr
Needless to say, **Bref is stable** and has been for a long time.
-
+
Indeed, Bref runs more than 1 billion requests and jobs every month!
@@ -23,11 +27,11 @@ To celebrate, we're finally releasing **Bref 1.0**!
## 1 billion executions per month
-Thanks to [Bref ping](/docs/runtimes/#bref-ping), we have an anonymous estimate of Bref's usage, i.e. the number of monthly invocations (HTTP requests, worker jobs, etc.) across all users.
+Thanks to [Bref ping](/docs/runtimes/runtimes-details#telemetry-ping), we have an anonymous estimate of Bref's usage, i.e. the number of monthly invocations (HTTP requests, worker jobs, etc.) across all users.
It illustrates clearly that Bref is getting traction and is used in production, at scale:
-![](01/executions.png)
+![](./01/executions.png)
Since we passed 1 billion monthly invocations, I want to celebrate with you this fantastic milestone and thank you for being a part of Bref's community.
@@ -109,7 +113,7 @@ New users now start with the _FPM_ runtime.
Don't worry about FaaS and functions… Start by running **PHP as usual** on a cheap and scalable host. Then, **once you've had your first success**, you can look into the "Function runtime" and its power.
-Check out [the "First steps" guide and see how simple it is!](/docs/first-steps.md).
+Check out [the "First steps" guide and see how simple it is!](/docs/default/getting-started.mdx).
### Clarity for current users
@@ -117,12 +121,12 @@ A common source of errors and confusion was the two runtimes: "FPM" and "Functio
To solve that, we clarified the wording and the structure of the documentation:
-- [**Bref for web apps**](/docs/runtimes/http.md) lets you run Laravel, Symfony, etc. on Lambda like on any server, using PHP-FPM (aka the "FPM" runtime),
-- [**Bref for event-driven functions**](/docs/runtimes/function.md) lets you handle native AWS Lambda events (aka the "Function" runtime).
+- [**Bref for web apps**](/docs/runtimes/fpm-runtime.mdx) lets you run Laravel, Symfony, etc. on Lambda like on any server, using PHP-FPM (aka the "FPM" runtime),
+- [**Bref for event-driven functions**](/docs/runtimes/function.mdx) lets you handle native AWS Lambda events (aka the "Function" runtime).
*Bref for web apps* is the default runtime (see the "onboarding" section above), so if you're not sure: go with this one.
-[![](01/doc-menu.png)](/docs/runtimes/)
+[![](./01/doc-menu.png)](/docs/runtimes/)
### More for expert users
@@ -143,9 +147,9 @@ Well, you already could, but now it will be a bit easier.
> Self-promotion time: I've helped enterprises refactor their microservice architectures using Lambda and SQS/EventBridge.
If you are interested, [get in touch to work together](mailto:matthieu@null.tc).
You can also check out [Serverless Visually Explained](https://serverless-visually-explained.com/?ref=bref-1.0), it contains examples for those use cases.
-
+< /self-promo\>
-Finally, the [`BREF_LOOP_MAX` variable](/docs/environment/performances.md#bref-for-event-driven-functions) is now documented, for those ready to keep the PHP process alive between events to accelerate their workers.
+Finally, the [`BREF_LOOP_MAX` variable](/docs/environment/performances.mdx#bref-for-event-driven-functions) is now documented, for those ready to keep the PHP process alive between events to accelerate their workers.
### Redesigning the header
@@ -175,7 +179,7 @@ Hello Jane
What's awesome is that you decide if you want to use Docker or not (with the Bref images). You can skip Docker for best performances and ease of use, or use Docker to run in an environment that replicates production.
-Read more in the documentation: [Local development for functions](/docs/function/local-development.md).
+Read more in the documentation: [Local development for functions](/docs/local-development/event-driven-functions.mdx).
## API Gateway v2
@@ -209,7 +213,7 @@ functions:
```
**However don't do this blindly:** this will delete your REST API to create a new HTTP API, which will break custom domains you may have set up.
-Instead, you can deploy the same Lambda with both v1 and v2, [set up your domain on v2](/docs/environment/custom-domains.md), and then delete v1:
+Instead, you can deploy the same Lambda with both v1 and v2, [set up your domain on v2](/docs/use-cases/http/custom-domains.mdx), and then delete v1:
```yaml
functions:
@@ -257,7 +261,7 @@ Hope you enjoy it! And stay tuned for the AWS re:Invent conference next week!
You can also join the community [in Slack](/docs/community.md), post details about your project in [Built with Bref](https://github.com/brefphp/bref/issues/267) or share your experience online.
-
diff --git a/docs/news/01/doc-menu.png b/website/src/pages/news/01/doc-menu.png
similarity index 100%
rename from docs/news/01/doc-menu.png
rename to website/src/pages/news/01/doc-menu.png
diff --git a/docs/news/01/executions.png b/website/src/pages/news/01/executions.png
similarity index 100%
rename from docs/news/01/executions.png
rename to website/src/pages/news/01/executions.png
diff --git a/docs/news/02-bref-2.0.md b/website/src/pages/news/02-bref-2.0.mdx
similarity index 77%
rename from docs/news/02-bref-2.0.md
rename to website/src/pages/news/02-bref-2.0.mdx
index bef9f157d..63882550a 100644
--- a/docs/news/02-bref-2.0.md
+++ b/website/src/pages/news/02-bref-2.0.mdx
@@ -1,20 +1,31 @@
----
-title: Bref 2.0 is released 🎉
-subTitle: Celebrating 10 billion executions per month
-layout: news-article
-articleDate: March 2023
-author: Matthieu Napoli
-authorGithub: mnapoli
-socialCard: https://bref.sh/docs/news/02/social-card.png
----
+import ArticleHeader from '../../components/news/ArticleHeader';
+import { NextSeo } from 'next-seo';
+
+
+
+# Bref 2.0 is released 🎉
+
+
The work on what would be Bref 2.0 started in October 2021, about 1.5 year ago. We went through many different strategies, experiments, rewrites, over **700 commits** to finally land with the stable release.
-So far, Bref has been installed more than 2 million times and powers more than **10 billion Lambda executions** (aka requests) every month[*](https://bref.sh/docs/runtimes/#bref-ping).
+So far, Bref has been installed more than 2 million times and powers more than **10 billion Lambda executions** (aka requests) every month[*](https://bref.sh/docs/runtimes/runtimes-details#telemetry-ping).
That's [1 in every 1000 AWS Lambda executions](https://twitter.com/matthieunapoli/status/1603032544424894464)!
-![](02/executions.png)
+![](./02/executions.png)
Today, we celebrate these achievements, the ongoing work, and **the release of Bref 2.0** 🎉
@@ -132,7 +143,7 @@ _Note that it is possible to stay on the 1.x version of the Laravel bridge._
Let's take the opportunity to send huge thanks to Till and George for building such an excellent integration, and for joining the Bref organization on GitHub 💙
-If you want to get started with Laravel on Bref, [check out the documentation](../frameworks/laravel.md).
+If you want to get started with Laravel on Bref, [check out the documentation](../docs/laravel/getting-started.mdx).
## ARM/Graviton support
@@ -199,7 +210,7 @@ Here are the commands that have changed:
serverless bref:cli --args="migrate --force"
```
- No need to provide the function name or the region anymore. Read [the Console documentation](../runtimes/console.md#usage) to learn more. You will also find alternatives if you don't use the `serverless` CLI.
+ No need to provide the function name or the region anymore. Read [the Console documentation](../docs/runtimes/console.md#usage) to learn more. You will also find alternatives if you don't use the `serverless` CLI.
- `vendor/bin/bref local` is replaced by the simpler `serverless bref:local`.
@@ -213,7 +224,7 @@ Here are the commands that have changed:
No need to provide the handler file name anymore, we directly use the function name. The new `serverless bref:local` command has similar arguments as `serverless invoke`.
- Read [the Local Development documentation](../function/local-development.md) to learn more. You will also find alternatives if you don't use the `serverless` CLI.
+ Read [the Local Development documentation](../docs/local-development/event-driven-functions.mdx) to learn more. You will also find alternatives if you don't use the `serverless` CLI.
- `vendor/bin/bref layers` is replaced by the simpler `serverless layers`.
@@ -251,7 +262,7 @@ In the example above, `GITHUB_TOKEN` will be deployed with the string `bref-ssm:
This offers a more secure solution for teams that prefer to keep secrets as tight as possible.
-Read more about this new feature and secrets in general in the [Secrets documentation](../environment/variables.md#at-runtime).
+Read more about this new feature and secrets in general in the [Secrets documentation](../docs/environment/variables.mdx#at-runtime).
## Simpler `docker-compose.yml` for local development
@@ -300,7 +311,7 @@ services:
DOCUMENT_ROOT: public
```
-The `bref/php-XX-fpm-dev` images can now run HTTP applications, console commands as well as event-driven functions too. Read more in [web app local development](../web-apps/local-development.md).
+The `bref/php-XX-fpm-dev` images can now run HTTP applications, console commands as well as event-driven functions too. Read more in [web app local development](../docs/web-apps/local-development.md).
The `bref/fpm-dev-gateway` image is no longer needed, and code running in `bref/php-XX-fpm-dev` now runs in an environment even closer to production.
@@ -310,7 +321,7 @@ The `bref/fpm-dev-gateway` image is no longer needed, and code running in `bref/
Bref 2.0 introduces basic support for the AWS CDK (NodeJS) via [PHP constructs](https://github.com/brefphp/constructs).
-In case you are not familiar with it, AWS CDK is bit more complex than `serverless.yml` to deploy serverless apps. These constructs will be useful to those actively looking to use the CDK with Bref.
+In case you are not familiar with it, AWS CDK is a bit more complex than `serverless.yml` to deploy serverless apps. These constructs will be useful to those actively looking to use the CDK with Bref.
## Rewritten internals
@@ -334,44 +345,44 @@ I know this isn't _that_ exciting, but I had to mention it given the incredible
A huge thanks to the [136 Bref contributors](https://github.com/brefphp/bref/graphs/contributors), to the community for supporting the project, and to the open-source sponsors:
-
@@ -385,25 +396,25 @@ Thank you all!
Hope you enjoy Bref v2!
-There is a complete [**v2 Upgrade Guide**](../upgrading/v2.md) that you can follow.
+There is a complete [**v2 Upgrade Guide**](../docs/upgrading/v2.md) that you can follow.
-Head to the docs to [**get started with Bref**](../), or check out the documentation for [Laravel](../frameworks/laravel.md) or [Symfony](../frameworks/symfony.md).
+Head to the docs to [**get started with Bref**](../), or check out the documentation for [Laravel](../docs/laravel/getting-started.mdx) or [Symfony](../docs/symfony/getting-started.mdx).
You can also join the community [in Slack](/docs/community.md), post details about your project in [Built with Bref](https://github.com/brefphp/bref/issues/267), or share your experience online and mention [@brefphp](https://twitter.com/brefphp) on Twitter.
If you enjoy teasers, here is a preview of a redesign coming soon to Bref:
-
+![](./02/logo.png)
## One more thing
I launched the [**Bref Dashboard**](https://dashboard.bref.sh/) ✨ in January. It helps you monitor and debug Bref applications:
-[![Bref Dashboard](../monitoring/bref-dashboard.png)](https://dashboard.bref.sh/?ref=bref)
+[![Bref Dashboard](../docs/monitoring/bref-dashboard.png)](https://dashboard.bref.sh/?ref=bref)
-And if you need support or help going serverless, check out the [Support Plans](/#ecosystem).
+And if you need support or help going serverless, check out the [Support Plans](/support).
-
+ Get access to the package for a one-time price with optional yearly renewal.
+
+
+
+
+
+ One-time price with optional yearly renewal
+
+
+ The license includes access to the current version of the package.
+ During checkout, you can optionally enable automatic yearly renewal so that you can always access the latest version of the package.
+
+
+
What’s included
+
+
+
+ {includedFeatures.map((feature) => (
+
+
+ {feature}
+
+ ))}
+
+
+
What’s optional
+
+
+
+
+
+ Automatic yearly license renewal with access to future updates
+
+ Runtimes provided by the open-source project are served from the Bref AWS account.
+
+ It works perfectly, but if your project or company policy requires full ownership of AWS Lambda runtimes, Bref Pro and Bref Enterprise help you publish the runtimes to your own AWS account.
+
+
+
+
+
+
+
+
+
+
+ Tailored and optimized runtimes
+
+
+ Bref Enterprise helps you optimize runtimes to your needs and comply with security standards and regulations.
+
- Runtimes provided by the open-source project are served from the Bref AWS account.
-
- It works perfectly, but if your project or company policy requires full ownership of AWS Lambda runtimes, Bref Pro and Bref Enterprise help you publish the runtimes to your own AWS account.
-
-
-
-
-
-
-
-
-
-
- Tailored and optimized runtimes
-
-
- Bref Enterprise helps you optimize runtimes to your needs and comply with security standards and regulations.
-
- Creating and running modern and scalable PHP applications should be simpler. By using serverless technologies, like AWS Lambda, we can focus on development and worry less about servers.
-
-
- Bref is an open source project that brings full support for PHP and its frameworks to AWS Lambda.
-
-
-
-
-
-
-
Open source, battle-tested PHP runtimes for AWS Lambda
-
-
-
-
-
-
- built on top of the cloud
-
-
- Getting started with serverless can be overwhelming. Bref integrates with the open-source Serverless Framework for configuration and deployment.
- We get the best of both world: powerful, yet simple.
-
-
- On top of Serverless' documentation and ecosystem, Bref provides complete documentation and examples for PHP applications.
-
-
-
-
-
-
-
Simple cloud orchestration via the Serverless Framework