Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ netlify.toml
deno.lock
.azure
.azure-swa
.firebase-app
.firebase
.firebaserc
firebase.json
.bun
.deno
.aws
Expand Down
4 changes: 2 additions & 2 deletions docs/react-server.wrangler.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[[routes]]
pattern = "react-server.dev/*"
zone_name = "react-server.dev"
pattern = "react-server.dev"
custom_domain = true
59 changes: 48 additions & 11 deletions docs/src/components/AdapterGrid.jsx
Original file line number Diff line number Diff line change
@@ -1,61 +1,98 @@
import { useLanguage } from "../i18n.mjs";
import { defaultLanguage } from "../const.mjs";

const adapters = [
{
name: "Vercel",
href: "/deploy/vercel",
description: "Serverless & edge functions",
description: {
en: "Serverless & edge functions",
ja: "サーバーレス & エッジ関数",
},
},
{
name: "Netlify",
href: "/deploy/netlify",
description: "Serverless functions & edge CDN",
description: {
en: "Serverless functions & edge CDN",
ja: "サーバーレス関数 & エッジ CDN",
},
},
{
name: "Cloudflare",
href: "/deploy/cloudflare",
description: "Workers & Pages",
description: {
en: "Workers & Pages",
ja: "Workers & Pages",
},
},
{
name: "AWS Lambda",
href: "/deploy/aws",
description: "Serverless functions",
description: {
en: "Serverless functions",
ja: "サーバーレス関数",
},
},
{
name: "Bun",
href: "/deploy/bun",
description: "Standalone Bun server",
description: {
en: "Standalone Bun server",
ja: "スタンドアロン Bun サーバー",
},
},
{
name: "Deno",
href: "/deploy/deno",
description: "Standalone Deno server",
description: {
en: "Standalone Deno server",
ja: "スタンドアロン Deno サーバー",
},
},
{
name: "Azure Functions",
href: "/deploy/azure",
description: "Functions v4 with streaming",
description: {
en: "Functions v4 with streaming",
ja: "ストリーミング対応 Functions v4",
},
},
{
name: "Azure Static Web Apps",
href: "/deploy/azure-swa",
description: "Managed functions & CDN",
description: {
en: "Managed functions & CDN",
ja: "マネージド関数 & CDN",
},
},
{
name: "Firebase Functions",
href: "/deploy/firebase",
description: {
en: "Cloud Functions v2 with streaming",
ja: "ストリーミング対応 Cloud Functions v2",
},
},
];

export default function AdapterGrid() {
const lang = useLanguage();
return (
<div className="my-4 grid grid-cols-1 md:grid-cols-3 gap-4 not-prose">
<div className="my-4 grid grid-cols-1 md:grid-cols-3 auto-rows-fr gap-4 not-prose">
{adapters.map(({ name, href, description }) => (
<a
key={href}
href={href}
href={`${lang === defaultLanguage ? "" : `/${lang}`}${href}`}
hrefLang={lang}
className="adapter-card flex flex-col rounded-xl p-4 bg-gray-50 dark:bg-gray-800 text-xs shadow-lg dark:shadow-[rgba(255,255,255,0.1)] border border-gray-500 no-underline hover:no-underline transition-colors hover:border-gray-300 dark:hover:border-gray-400"
style={{ textDecoration: "none", color: "inherit" }}
>
<span className="adapter-card-title relative inline-block self-start font-semibold text-base text-black dark:text-gray-300 mb-1">
{name}
</span>
<span className="font-normal text-sm text-gray-500 dark:text-gray-400">
{description}
{description[lang] ?? description.en}
</span>
</a>
))}
Expand Down
14 changes: 3 additions & 11 deletions docs/src/pages/en/(pages)/deploy/adapters.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ category: Deploy
order: 0
---

import AdapterGrid from "../../../../components/AdapterGrid.jsx";
import Link from "../../../../components/Link.jsx";

# Adapters
Expand All @@ -14,25 +15,16 @@ You can use adapters to configure your app for different deployment environments
### Available adapters
</Link>

- [x] Vercel
- [x] Netlify
- [x] Cloudflare Workers/Pages
- [x] AWS Lambda
- [x] Bun
- [x] Deno
- [x] Azure Functions
- [x] Azure Static Web Apps
<AdapterGrid />

<Link name="configuration">
## Configuration
</Link>

Add `adapter` entry to your `react-server.config.mjs` file. You can specify the name of a built-in adapter (`vercel`, `netlify`, `cloudflare`, `aws`, `bun`, `deno`, `azure`, or `azure-swa`) as a string, or use an external adapter package.
Add `adapter` entry to your `react-server.config.mjs` file. You can specify the name of a built-in adapter (`vercel`, `netlify`, `cloudflare`, `aws`, `bun`, `deno`, `azure`, `azure-swa`, or `firebase`) as a string, or use an external adapter package.

> **Note:** When running a production build with **Bun** or **Deno**, the corresponding adapter is automatically detected and used without any configuration. You can override this with an explicit `adapter` setting in your config or via `--adapter <name>` on the CLI. Use `--no-adapter` to disable auto-detection.

> **Note:** The `aws` adapter requires the [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html) and configured AWS credentials. See the [AWS Lambda](/deploy/aws) page for setup instructions.

```mjs
export default {
adapter: 'vercel',
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/en/(pages)/deploy/api.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ You need to pass adapter properties to the `createAdapter` function to configure

`handler`: The adapter handler function.

`deploy`: The deployment command and arguments. This is optional. When provided, the adapter will show what command the developer needs to run to deploy the application after it has been built. If the `--deploy` flag is provided during the build, the adapter will run this command. The `deploy` property can also be a function that will be called with the adapter options, CLI options and the handler result. This is useful if you need to customize the deployment command based on the adapter options or the handler result. If you don't provide a result with `command` and `args`, the default deployment handling spawning the command will be skipped. This is useful if you want to implement a custom deployment workflow in the adapter.
`deploy`: The deployment command and arguments. This is optional. When provided, the adapter will show what command the developer needs to run to deploy the application after it has been built. If the `--deploy` flag is provided during the build, the adapter will run this command. You can also pass a JSON string to `--deploy` (e.g. `--deploy '{"project": "my-project"}'`) to provide additional adapter options at deploy time — these are merged into `adapterOptions` with CLI values taking precedence. The `deploy` property can also be a function that will be called with the adapter options, CLI options and the handler result. This is useful if you need to customize the deployment command based on the adapter options or the handler result. If you don't provide a result with `command` and `args`, the default deployment handling spawning the command will be skipped. This is useful if you want to implement a custom deployment workflow in the adapter.

The deploy descriptor supports the following properties:

Expand Down
197 changes: 197 additions & 0 deletions docs/src/pages/en/(pages)/deploy/firebase.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
---
title: Firebase
category: Deploy
order: 8
---

import Link from "../../../../components/Link.jsx";

# Firebase Functions

To deploy to Firebase, use the built-in `firebase` adapter. This adapter uses Firebase Cloud Functions (v2) with Firebase Hosting rewrites, bundling your server into a single edge file with full response streaming support.

<Link name="installation">
## Installation
</Link>

You need the [Firebase CLI](https://firebase.google.com/docs/cli) installed:

```sh
npm install -g firebase-tools

# Login to Firebase
firebase login
```

No additional packages are needed — the adapter is built into `@lazarv/react-server`.

Your Firebase project must be on the **Blaze (pay-as-you-go) plan** to deploy Cloud Functions. You can upgrade in the [Firebase Console](https://console.firebase.google.com).

Add the adapter to your `react-server.config.mjs` file:

```mjs
export default {
adapter: "firebase",
};
```

<Link name="configuration">
## Configuration
</Link>

You can customize the adapter by passing options:

```mjs
export default {
adapter: [
"firebase",
{
project: "my-project", // Firebase project ID
region: "us-central1", // Function region
memory: "512MiB", // Memory allocation
timeoutSeconds: 60, // Request timeout
minInstances: 0, // Minimum warm instances
maxInstances: 100, // Maximum concurrent instances
concurrency: 80, // Requests per instance
hosting: {}, // Extra firebase.json hosting properties
functions: {}, // Extra firebase.json functions properties
firebase: {}, // Extra top-level firebase.json properties
},
],
};
```

### Configuration Options

- `project`: Firebase project ID. Falls back to `package.json` name (without scope prefix).
- `region`: Cloud Functions region (default: `"us-central1"`). See [available regions](https://cloud.google.com/functions/docs/locations).
- `memory`: Memory allocation for the function (default: `"512MiB"`). Valid values: `"128MiB"`, `"256MiB"`, `"512MiB"`, `"1GiB"`, `"2GiB"`, `"4GiB"`, `"8GiB"`, `"16GiB"`, `"32GiB"`.
- `timeoutSeconds`: Maximum request duration in seconds (default: `60`). Maximum is 540 for v2 functions.
- `minInstances`: Minimum number of warm instances to keep ready (default: `0`). Setting this above 0 reduces cold starts but incurs costs.
- `maxInstances`: Maximum number of concurrent instances (default: `100`).
- `concurrency`: Maximum concurrent requests per instance (default: `80`).
- `hosting`: Additional properties to merge into the `hosting` section of `firebase.json`.
- `functions`: Additional properties to merge into the `functions` section of `firebase.json`.
- `firebase`: Additional top-level properties to merge into `firebase.json`.

You can also pass adapter options at deploy time via the `--deploy` flag:

```sh
pnpm react-server build --adapter firebase --deploy='{"project":"my-project"}'
```

<Link name="deploy">
## Deploy
</Link>

Build and deploy in one step:

```sh
pnpm react-server build --deploy
```

Or build first and deploy manually:

```sh
# Build
pnpm react-server build

# Deploy using Firebase CLI
firebase deploy --only functions,hosting --project <project-id>
```

<Link name="streaming">
## Response Streaming
</Link>

This adapter supports response streaming. React Server Components, Suspense boundaries, and progressive HTML delivery all work out of the box. The generated Cloud Function streams the response body chunk by chunk using the Node.js response object's `write()` method.

<Link name="how-it-works">
## How it works
</Link>

The adapter uses an **edge build** mode, bundling your entire server into a single file. At build time, it:

1. Bundles your server into `.firebase-app/server/.react-server/server/edge.mjs`
2. Copies all static assets into `.firebase-app/public/`
3. Generates a `src/index.mjs` wrapper that:
- Imports `onRequest` from `firebase-functions/v2/https`
- Registers an HTTP-triggered function matching all methods and paths
- Serves static files from a build-time route map using `readFileSync()`
- Converts incoming Express-style requests to standard `Request` objects
- Delegates dynamic requests to the bundled edge handler
- Streams the response back
4. Generates `package.json` with `firebase-functions` and `firebase-admin` dependencies
5. Runs `npm install` in `.firebase-app/` to install dependencies
6. Generates `firebase.json` with Hosting rewrites pointing to the function
7. Generates `.firebaserc` with the project ID (if available)

> **Important:** The `firebase-functions` and `firebase-admin` packages cannot be bundled into the edge build. The Firebase Functions runtime expects these as external dependencies in `node_modules`.

<Link name="static-files">
## Static Files
</Link>

Static files are served by Firebase Hosting's CDN when possible. All static assets (HTML, CSS, JS, images) are copied to `.firebase-app/public/` and served directly by Hosting. The function also has a static file route map as a fallback for any requests that reach the function.

Assets under `/assets/` and `/client/` paths are served with immutable cache headers (`Cache-Control: public, max-age=31536000, immutable`).

<Link name="local-development">
## Local Development
</Link>

After building, you can test locally using the Firebase Emulator:

```sh
firebase emulators:start --only functions,hosting
```

<Link name="output-structure">
## Output Structure
</Link>

```
.firebase-app/
├── package.json # Dependencies (firebase-functions, firebase-admin)
├── node_modules/ # Installed dependencies
├── public/ # Static assets (HTML, CSS, JS, images)
├── server/
│ └── .react-server/ # Bundled server (edge.mjs, manifests)
└── src/
└── index.mjs # Firebase Cloud Function entry

firebase.json # Firebase configuration (Hosting + Functions)
.firebaserc # Firebase project alias
```

<Link name="troubleshooting">
## Troubleshooting
</Link>

### "Blaze plan required" error

Firebase Cloud Functions require the Blaze (pay-as-you-go) billing plan. Upgrade your project at the [Firebase Console](https://console.firebase.google.com). The Blaze plan still includes generous free-tier usage — you only pay for actual usage beyond the free limits. The billing plan is per-project and does not affect your other Firebase projects.

### Cold starts

By default, `minInstances` is `0`, meaning the function scales to zero when idle. The first request after scaling to zero will experience a cold start (typically 1-3 seconds). Set `minInstances: 1` to keep one instance warm:

```mjs
export default {
adapter: ["firebase", { minInstances: 1 }],
};
```

### "Could not find project" error

Make sure your project ID is correct. You can list your Firebase projects with:

```sh
firebase projects:list
```

Set the project explicitly via adapter options or the `--deploy` flag:

```sh
pnpm react-server build --adapter firebase --deploy='{"project":"my-project"}'
```
8 changes: 8 additions & 0 deletions docs/src/pages/en/(pages)/framework/cli.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,14 @@ Deploy using adapter. Default is `false`.

If you use an adapter in your `react-server.config.mjs` file, the adapter will pre-build your app for deployment and when you use this argument, the adapter will also deploy your app at the end of the build process.

You can also pass a JSON string to `--deploy` to provide adapter-specific options at deploy time. These options are merged with the `adapterOptions` from your configuration file, with the CLI values taking precedence.

```sh
pnpm react-server build --deploy '{"project": "my-project"}'
```

This is useful when you want to override or provide adapter options without modifying your configuration file, for example specifying a deployment target project or environment.

<Link name="build-eval">
### --eval
</Link>
Expand Down
Loading
Loading