With Firebase Hosting, you can configure customized hosting behavior for requests to your site.
Specify which files in your local project directory you want to deploy to Firebase Hosting. Learn how.
Serve a customized 404/Not Found page. Learn how.
Set up redirects for pages that you've moved or deleted.
Learn how.
Set up rewrites for any of these purposes:
Show the same content for multiple URLs. Learn how.
Serve a function or access a Cloud Run container from a Hosting URL. Learn how: function or container.
Create a custom domain Dynamic Link. Learn how.
Add headers to pass along additional information about a request or a
response, such as how browsers should handle the page and its content
(authentication, caching, encoding, etc.). Learn how.
Set up internationalization (i18n) rewrites to serve specific content based on a user's language preference and/or country. Learn how (different page).
You define your Firebase Hosting configuration in your
firebase.json file. Firebase
automatically creates your firebase.json file at the root of your project
directory when you run the
firebase init command.
You can find a
full firebase.json configuration example
(covering only Firebase Hosting) at the bottom of this page. Note that a
firebase.json file can also contain
configurations for other Firebase services.
You can check the deployed firebase.json content using the
Hosting REST API.
The different Firebase Hosting configuration options described on this page can sometimes overlap. If there is a conflict, Hosting determines its response using the following priority order:
/__/* path segmentIf you're using i18n rewrites, the exact-match and 404 handling priority order are expanded in scope to accommodate your "i18n content".
The default attributes — public and ignore — included
in the default firebase.json file define which files in your project directory
should be deployed to your Firebase project.
The default hosting configuration in a firebase.json file looks like this:
"hosting": {
"public": "public", // the only required attribute for Hosting
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}
Required
The public attribute specifies which directory to deploy to
Firebase Hosting. The default value is a directory named public, but you
can specify any directory's path, as long as it exists in your project
directory.
The following is the default specified name of the directory to deploy:
"hosting": {
"public": "public"
// ...
}
You can change the default value to the directory that you want to deploy:
"hosting": {
"public": "dist/app"
// ...
}
Optional
The ignore attribute specifies the files to ignore on deploy. It can take
globs the same way that
Git handles .gitignore.
The following are the default values for the files to ignore:
"hosting": {
// ...
"ignore": [
"firebase.json", // the Firebase configuration file (the file described on this page)
"**/.*", // files with a leading period should be hidden from the system
"**/node_modules/**" // contains dependencies used to create your site but not run it
]
}
Optional
You can serve a custom 404 Not Found error when a user tries to access a page
that doesn't exist.
Create a new file in your project's public directory, name it
404.html, then add your custom 404 Not Found content to the file.
Firebase Hosting will display the content of this custom 404.html page if
a browser triggers a 404 Not Found error on your domain or subdomain.
Optional
Use a URL redirect to prevent broken links if you've moved a page
or to shorten URLs. For example, you could redirect a browser from
example.com/team to example.com/about.html.
Specify URL redirects by creating a redirects attribute that contains an array
of objects (called "redirect rules"). In each rule, specify a URL pattern that,
if matched to the request URL path, triggers Hosting to respond with a redirect
to the specified destination URL.
Here's the basic structure for a redirects attribute. This example redirects
requests to /foo by making a new request to /bar.
"hosting": {
// ...
// Returns a permanent redirect to "/bar" for requests to "/foo" (but not "/foo/**")
"redirects": [ {
"source": "/foo",
"destination": "/bar",
"type": 301
} ]
}
View a more detailed example for a redirects attribute
"hosting": {
// ...
// Add the "redirects" attribute within "hosting"
"redirects": [ {
// Returns a permanent redirect to "/bar" for requests to "/foo" (but not "/foo/**")
"source": "/foo",
"destination": "/bar",
"type": 301
}, {
// Returns a permanent redirect to "/bar" for requests to both "/foo" and "/foo/**"
"source": "/foo{,/**}"
"destination": "/bar"
"type": 301
}, {
// Returns a temporary redirect for all requests to files or directories in the "firebase" directory
"source": "/firebase/**",
"destination": "https://firebase.google.com/",
"type": 302
}, {
// A regular expression-based redirect equivalent to the above behavior
"regex": "/firebase/.*",
"destination": "https://firebase.google.com/",
"type": 302
} ]
}
The redirects attribute contains an array of redirect rules, where each rule
must include the fields in the table below.
Firebase Hosting compares the source or regex value against all URL
paths at the start of every request (before the browser determines whether a
file or folder exists at that path). If a match is found, then the
Firebase Hosting origin server sends an HTTPS redirect response telling the
browser to make a new request at the destination URL.
| Field | Description | |
|---|---|---|
redirects |
||
source (recommended) or regex
|
A URL pattern that, if matched to the initial request URL, triggers Hosting to apply the redirect
|
|
destination |
A static URL where the browser should make a new request This URL can be a relative or an absolute path. |
|
type |
The HTTPS response code
|
|
Optional
Sometimes, you might need to capture specific segments of a redirect rule's URL
pattern (source or regex value), then re-use these segments in the
rule's destination path.
Capture URL segments when using globs
If you're using a source field (that is, specifying a glob for your URL
pattern), you can capture segments by including a : prefix to identify the
segment. If you also need to capture the remaining URL path after the segment,
include a * immediately after the segment. For example:
"hosting": { // ... "redirects": [ { "source": "/blog/:post*", // captures the entire URL segment beginning at "post" "destination": "https://blog.myapp.com/:post", // includes the entire URL segment identified and captured by the "source" value "type": 301 }, { "source": "/users/:id/profile", // captures only the URL segment "id", but nothing following "destination": "/users/:id/newProfile", // includes the URL segment identified and captured by the "source" value "type": 301 } ] }
Capture URL segments when using RE2 regular expressions
If you're using a regex field (that is, specifying a RE2 regular expression
for your URL pattern), you can capture segments using either named or unnamed
RE2 capture groups. Named capture groups can be used in the destination field
with a : prefix, while unnamed capture groups can be referenced by their
numerical index in the regex value, indexed from 1. For example:
"hosting": { // ... "redirects": [ { "regex": "/blog/(?P<post>.+)", // if you're familiar with PCRE, be aware that RE2 requires named capture groups to begin with ?P "destination": "https://blog.myapp.com/:post", // includes the entire URL segment identified and captured by the `regex` value "type": 301 }, { "regex": "/users/(\d+)/profile", // uses the \d directive to only match numerical path segments "destination": "/users/:1/newProfile", // the first capture group to be seen in the `regex` value is named 1, and so on "type": 301 } ] }
Optional
Use a rewrite to show the same content for multiple URLs. Rewrites are
particularly useful with pattern matching, as you can accept any URL that
matches the pattern and let the client-side code decide what to display.
You can also use rewrites to support apps that use
HTML5 pushState
for navigation. When a browser attempts to open a URL path that matches the
specified source or regex URL pattern, the browser will be given the
contents of the file at the destination URL instead.
Specify URL rewrites by creating a rewrites attribute that contains an array
of objects (called "rewrite rules"). In each rule, specify a URL pattern that,
if matched to the request URL path, triggers Hosting to respond as if the
service were given the specified destination URL.
Here's the basic structure for a rewrites attribute. This example serves
index.html for requests to files or directories that don't exist.
"hosting": {
// ...
// Serves index.html for requests to files or directories that do not exist
"rewrites": [ {
"source": "**",
"destination": "/index.html"
} ]
}
View a more detailed example for a rewrites attribute
"hosting": { // ... // Add the "rewrites" attribute within "hosting" "rewrites": [ { // Serves index.html for requests to files or directories that do not exist "source": "**", "destination": "/index.html" }, { // Serves index.html for requests to both "/foo" and "/foo/**" // Using "/foo/**" only matches paths like "/foo/xyz", but not "/foo" "source": "/foo{,/**}", "destination": "/index.html" }, { // A regular expression-based rewrite equivalent to the above behavior "regex": "/foo(/.*)?", "destination": "/index.html" }, { // Excludes specified pathways from rewrites "source": "!/@(js|css)/**", "destination": "/index.html" } ] }
The rewrites attribute contains an array of rewrite rules, where each rule
must include the fields in the table below.
Firebase Hosting only applies a rewrite rule if a file or directory does not
exist at a URL path that matches the specified source or regex URL pattern.
When a request triggers a rewrite rule, the browser returns the actual content
of the specified destination file instead of an HTTP redirect.
| Field | Description | |
|---|---|---|
rewrites |
||
source (recommended) or regex
|
A URL pattern that, if matched to the initial request URL, triggers Hosting to apply the rewrite
|
|
destination |
A local file that must exist This URL can be a relative or an absolute path. |
|
You can use rewrites to serve a function from a Firebase Hosting URL. The
following example is an excerpt from
serving dynamic content using Cloud Functions.
For example, to direct all requests from the page /bigben on your
Hosting site to execute the bigben function:
"hosting": {
// ...
// Directs all requests from the page `/bigben` to execute the `bigben` function
"rewrites": [ {
"source": "/bigben",
"function": {
"functionId": "bigben",
"region": "us-central1" // optional (see note below)
"pinTag": true // optional (see note below)
}
} ]
}
How region
works within the function block
If
regionis omitted from afunctionblock of thehosting.rewritesconfig, the Firebase CLI attempts to automatically detect the region from the function's source code which, if unspecified, defaults tous-central1. If the function's source code is unavailable, the CLI attempts to detect the region from the deployed function. If the function is in multiple regions, the CLI requiresregionto be specified in thehosting.rewritesconfig.
How
pinTag works within the function block
The
pinTagfeature is only available in Cloud Functions for Firebase (2nd gen). With this feature, you can ensure that each function for generating your site's dynamic content is kept in sync with your static Hosting resources and Hosting config. Also, this feature allows you to preview your rewrites to functions on Hosting preview channels.If you add
"pinTag": trueto afunctionblock of thehosting.rewritesconfig, then the "pinned" function will be deployed along with your static Hosting resources and configuration, even when running. If you roll back a version of your site, the "pinned" function is also rolled back.firebase deploy --only hosting This feature relies on Cloud Run tags, which have a limit of 1000 tags per service and 2000 tags per region. This means that after hundreds of deploys, the oldest versions of a site may stop working.
After adding this rewrite rule and deploying to Firebase (using
firebase deploy), your function is reachable via the following URLs:
Your Firebase subdomains:
PROJECT_ID.web.app/bigben and
PROJECT_ID.firebaseapp.com/bigben
Any connected custom domains:
CUSTOM_DOMAIN/bigben
When Firebase Hosting forwards traffic to a function, the function receives the
full original request path and query string. For example, a request to
/bigben/hello/world?foo=bar on your Hosting site is passed to the function
with the complete path and query intact. Make sure your function handler is
written to handle the entire absolute URL, not just the base path defined in
the rewrite.
When redirecting requests to functions with Hosting, supported HTTP request
methods are GET, POST, HEAD, PUT, DELETE, PATCH, and OPTIONS.
Other methods like REPORT or PROFIND are not supported.
You can use rewrites to access a Cloud Run container from a
Firebase Hosting URL. The following example is an excerpt from
serving dynamic content using Cloud Run.
For example, to direct all requests from the page /helloworld on your
Hosting site to trigger the startup and running of a helloworld container
instance:
"hosting": {
// ...
// Directs all requests from the page `/helloworld` to trigger and run a `helloworld` container
"rewrites": [ {
"source": "/helloworld",
"run": {
"serviceId": "helloworld", // "service name" (from when you deployed the container image)
"region": "us-central1" // optional (if omitted, default is us-central1)
}
} ]
}
How pinTag
works within the run block
With this feature, you can ensure that the revision of your Cloud Run service for generating your site's dynamic content is kept in sync with your static Hosting resources and Hosting config. Also, this feature allows you to preview your rewrites to Cloud Run on Hosting preview channels.
If you add
"pinTag": trueto arunblock of thehosting.rewritesconfig, your static Hosting resources and configuration will be pinned to the most recent revision of the Cloud Run service, at the time of deploy. If you roll back a version of your site, the revision of the "pinned" Cloud Run service is also rolled back.This feature relies on Cloud Run tags, which have a limit of 1000 tags per service and 2000 tags per region. This means that after hundreds of deploys, the oldest versions of a site may stop working.
After adding this rewrite rule and deploying to Firebase (using
firebase deploy), your container image is reachable via the following URLs:
Your Firebase subdomains:
PROJECT_ID.web.app/helloworld and
PROJECT_ID.firebaseapp.com/helloworld
Any connected custom domains:
CUSTOM_DOMAIN/helloworld
When redirecting requests to Cloud Run containers with Hosting,
supported HTTP request methods are GET, POST, HEAD, PUT, DELETE,
PATCH, and OPTIONS. Other methods like REPORT or PROFIND are not
supported.
For the best performance, colocate your Cloud Run service with Hosting using the following regions:
us-west1us-central1us-east1europe-west1asia-east1Rewrites to Cloud Run from Hosting are supported in the following regions:
asia-east1asia-east2asia-northeast1asia-northeast2asia-northeast3asia-south1asia-south2asia-southeast1asia-southeast2australia-southeast1australia-southeast2europe-central2europe-north1europe-southwest1europe-west1europe-west12europe-west2europe-west3europe-west4europe-west6europe-west8europe-west9me-central1me-west1northamerica-northeast1northamerica-northeast2southamerica-east1southamerica-west1us-central1us-east1us-east4us-east5us-south1us-west1us-west2us-west3us-west4us-west1us-central1us-east1europe-west1asia-east1You can use rewrites to create custom domain Dynamic Links. Visit the Dynamic Links
documentation for detailed information about
setting up a custom domain for Dynamic Links.
Use your custom domain only for Dynamic Links
"hosting": {
// ...
"appAssociation": "AUTO", // required for Dynamic Links (default is AUTO if not specified)
// Add the "rewrites" attribute within "hosting"
"rewrites": [ {
"source": "/**", // the Dynamic Links start with "https://CUSTOM_DOMAIN/"
"dynamicLinks": true
} ]
}Specify custom domain path prefixes to use for Dynamic Links
"hosting": {
// ...
"appAssociation": "AUTO", // required for Dynamic Links (default is AUTO if not specified)
// Add the "rewrites" attribute within "hosting"
"rewrites": [ {
"source": "/promos/**", // the Dynamic Links start with "https://CUSTOM_DOMAIN/promos/"
"dynamicLinks": true
}, {
"source": "/links/share/**", // the Dynamic Links start with "https://CUSTOM_DOMAIN/links/share/"
"dynamicLinks": true
} ]
}Configuring Dynamic Links in your firebase.json file requires the following:
| Field | Description | |
|---|---|---|
appAssociation |
Must be set to
|
|
rewrites |
||
source |
A path that you want to use for Dynamic Links Unlike rules that rewrite paths to URLs, rewrite rules for Dynamic Links can't contain regular expressions. |
|
dynamicLinks |
Must be set to true
|
|
Optional
Headers allow the client and the server to pass additional information along
with a request or a response. Some sets of headers can affect how the browser
handles the page and its content, including access control, authentication,
caching, and encoding.
Specify custom, file-specific response headers by creating a headers attribute
that contains an array of header objects. In each object, specify a URL pattern
that, if matched to the request URL path, triggers Hosting to apply the
specified custom response headers.
Here's the basic structure for a headers attribute. This example applies a
CORS header for all font files.
"hosting": {
// ...
// Applies a CORS header for all font files
"headers": [ {
"source": "**/*.@(eot|otf|ttf|ttc|woff|font.css)",
"headers": [ {
"key": "Access-Control-Allow-Origin",
"value": "*"
} ]
} ]
}