If you are building server-rendered Angular or Next.js apps, check out next-generationFirebase App Hosting,a full-stack solution for modern web frameworks.
Addheadersto 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).
Where do you define yourHostingconfiguration?
You define yourFirebase Hostingconfiguration in yourfirebase.jsonfile. Firebase
automatically creates yourfirebase.jsonfile at the root of your project
directory when you run thefirebase initcommand.
You can check the deployedfirebase.jsoncontent using theHostingREST API.
Priority order ofHostingresponses
The differentFirebase Hostingconfiguration options described on this page
can sometimes overlap. If there is a conflict,Hostingdetermines its
response using the following priority order:
Reserved namespaces that begin with a/__/*path segment
If you're usingi18n rewrites, the exact-match
and 404 handling priority order are expanded in scope to accommodate your "i18n
content".
Specify which files to deploy
The default attributes —publicandignore— included
in the defaultfirebase.jsonfile define which files in your project directory
should be deployed to your Firebase project.
The defaulthostingconfiguration in afirebase.jsonfile looks like this:
"hosting": {
"public": "public", // the only required attribute forHosting"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}
public
Required Thepublicattribute specifies which directory to deploy toFirebase Hosting. The default value is a directory namedpublic, 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"
// ...
}
ignore
Optional Theignoreattribute specifies the files to ignore on deploy. It can takeglobsthe same way thatGithandles.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
]
}
Customize a 404/Not Found page
Optional You can serve a custom404 Not Founderror when a user tries to access a page
that doesn't exist.
Create a new file in your project'spublicdirectory, name it404.html, then add your custom404 Not Foundcontent to the file.
Firebase Hostingwill display the content of this custom404.htmlpage if
a browser triggers a404 Not Founderror on your domain or subdomain.
Configure redirects
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 fromexample.com/teamtoexample.com/about.html.
Specify URL redirects by creating aredirectsattribute that contains an array
of objects (called "redirect rules"). In each rule, specify a URL pattern that,
if matched to the request URL path, triggersHostingto respond with a redirect
to the specified destination URL.
Here's the basic structure for aredirectsattribute. This example redirects
requests to/fooby 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 aredirectsattribute
"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}]}
Theredirectsattribute contains an array of redirect rules, where each rule
must include the fields in the table below.
Firebase Hostingcompares thesourceorregexvalue 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 theFirebase Hostingorigin server sends an HTTPS redirect response telling the
browser to make a new request at thedestinationURL.
Field
Description
redirects
source(recommended) orregex
A URL pattern that, if matched to the initial request URL, triggersHostingto apply the redirect
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
Use a type of301for 'Moved Permanently'
Use a type of302for 'Found' (Temporary Redirect)
Capture URL segments for redirects
Optional Sometimes, you might need to capture specific segments of a redirect rule's URL
pattern (sourceorregexvalue), then re-use these segments in the
rule'sdestinationpath.
Capture URL segments when using globs
If you're using asourcefield (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 aregexfield (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 thedestinationfield
with a:prefix, while unnamed capture groups can be referenced by their
numerical index in theregexvalue, indexed from 1. For example:
"hosting":{//..."redirects":[{"regex":"/blog/(?P<post>.+)",//ifyou'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} ]}
Configure rewrites
OptionalUse 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 useHTML5 pushStatefor navigation. When a browser attempts to open a URL path that matches the
specifiedsourceorregexURL pattern, the browser will be given the
contents of the file at thedestinationURL instead.
Specify URL rewrites by creating arewritesattribute that contains an array
of objects (called "rewrite rules"). In each rule, specify a URL pattern that,
if matched to the request URL path, triggersHostingto respond as if the
service were given the specified destination URL.
Here's the basic structure for arewritesattribute. This example servesindex.htmlfor 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 arewritesattribute
"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"}]}
Therewritesattribute contains an array of rewrite rules, where each rule
must include the fields in the table below.
Firebase Hostingonly applies a rewrite rule if a file or directory does not
exist at a URL path that matches the specifiedsourceorregexURL pattern.
When a request triggers a rewrite rule, the browser returns the actual content
of the specifieddestinationfile instead of an HTTP redirect.
Field
Description
rewrites
source(recommended) orregex
A URL pattern that, if matched to the initial request URL, triggersHostingto apply the rewrite
Ifregionis omitted from afunctionblock of thehosting.rewritesconfig, theFirebaseCLI 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.
HowpinTagworks within thefunctionblock
ThepinTagfeature is only available inCloud 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 staticHostingresources
andHostingconfig. Also, this feature allows you to preview your rewrites
to functions onHostingpreview channels.
If you add"pinTag": trueto afunctionblock of thehosting.rewritesconfig, then the "pinned" function will be deployed along with your staticHostingresources and configuration, even when runningfirebase deploy --only hosting. If you roll back a
version of your site, the "pinned" function is also rolled back.
This feature relies onCloud Runtags,
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 (usingfirebase deploy), your function is reachable via the following URLs:
Your Firebase subdomains: PROJECT_ID.web.app/bigbenandPROJECT_ID.firebaseapp.com/bigben
WhenFirebase Hostingforwards traffic to a function, the function receives the
full original request path and query string. For example, a request to/bigben/hello/world?foo=baron yourHostingsite is passed to the function
with the complete path and query intact. Make sure your function handler is
written to handle theentire absolute URL, not just the base path defined in
the rewrite.
When redirecting requests to functions withHosting, supported HTTP request
methods areGET,POST,HEAD,PUT,DELETE,PATCH, andOPTIONS.
Other methods likeREPORTorPROFINDare not supported.
Direct requests to aCloud Runcontainer
You can userewritesto access aCloud Runcontainer from aFirebase HostingURL. The following example is an excerpt fromserving dynamic content usingCloud Run.
For example, to direct all requests from the page/helloworldon yourHostingsite to trigger the startup and running of ahelloworldcontainer
instance:
With this feature, you can ensure that the revision of yourCloud Runservice for generating your site's dynamic content is kept in sync with your
staticHostingresources andHostingconfig. Also, this feature allows
you to preview your rewrites toCloud RunonHostingpreview
channels.
If you add"pinTag": trueto arunblock of thehosting.rewritesconfig, your staticHostingresources and configuration will be pinned to
the most recent revision of theCloud Runservice, at the time of
deploy. If you roll back a version of your site, the revision of the "pinned"Cloud Runservice is also rolled back.
This feature relies onCloud Runtags,
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 (usingfirebase deploy), your container image is reachable via the following URLs:
Your Firebase subdomains: PROJECT_ID.web.app/helloworldandPROJECT_ID.firebaseapp.com/helloworld
"hosting": {
// ...
"appAssociation": "AUTO", // required forDynamic Links(default is AUTO if not specified)
// Add the "rewrites" attribute within "hosting"
"rewrites": [ {
"source": "/**", // theDynamic Linksstart with "https://CUSTOM_DOMAIN/"
"dynamicLinks": true
} ]
}
Specify custom domain path prefixes to use forDynamic Links
"hosting": {
// ...
"appAssociation": "AUTO", // required forDynamic Links(default is AUTO if not specified)
// Add the "rewrites" attribute within "hosting"
"rewrites": [ {
"source": "/promos/**", // theDynamic Linksstart with "https://CUSTOM_DOMAIN/promos/"
"dynamicLinks": true
}, {
"source": "/links/share/**", // theDynamic Linksstart with "https://CUSTOM_DOMAIN/links/share/"
"dynamicLinks": true
} ]
}
ConfiguringDynamic Linksin yourfirebase.jsonfile requires the following:
Field
Description
appAssociation
Must be set toAUTO
If you don't include this attribute in your configuration, the
default forappAssociationisAUTO.
By setting this attribute toAUTO,Hostingcan
dynamically generateassetlinks.jsonandapple-app-site-associationfiles when
they're requested.
rewrites
source
A path that you want to use forDynamic Links
Unlike rules that rewrite paths to URLs, rewrite rules forDynamic Linkscan't contain regular expressions.
dynamicLinks
Must be set totrue
Configure headers
OptionalHeaders 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 aheadersattribute
that contains an array of header objects. In each object, specify a URL pattern
that, if matched to the request URL path, triggersHostingto apply the
specified custom response headers.
Here's the basic structure for aheadersattribute. 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": "*"
} ]
} ]
}
View a more detailed example for aheadersattribute
"hosting":{// ...// Add the "headers" attribute within "hosting""headers":[{// Applies a CORS header for all font files"source":"**/*.@(eot|otf|ttf|ttc|woff|font.css)","headers":[{"key":"Access-Control-Allow-Origin","value":"*"}]},{// Overrides the default 1 hour browser cache with a 2 hour cache for all image files"source":"**/*.@(jpg|jpeg|gif|png)","headers":[{"key":"Cache-Control","value":"max-age=7200"}]},{// A regular expression-based rewrite equivalent to the above behavior"regex":".+/\w+\.(jpg|jpeg|gif|png)$","headers":[{"key":"Cache-Control","value":"max-age=7200"}]},{// Sets the cache header for 404 pages to cache for 5 minutes"source":"404.html","headers":[{"key":"Cache-Control","value":"max-age=300"}]}]}
Theheadersattribute contains an array of definitions, where each definition
must include the fields in the table below.
Field
Description
headers
source(recommended) orregex
A URL pattern that, if matched to the initial request URL, triggersHostingto apply the custom header
To create a header to match against yourcustom 404 page, use404.htmlas yoursourceorregexvalue.
array of (sub-)headers
The custom headers thatHostingapplies to the request path
Each sub-header must include akeyandvaluepair(see next two rows).
key
The name of the header, for exampleCache-Control
value
The value for the header, for examplemax-age=7200
You can learn more aboutCache-Controlin theHostingsection that describes serving dynamic content and hosting
microservices. You can also learn more aboutCORSheaders.
Control.htmlextensions
Optional ThecleanUrlsattribute allows you to control whether or not URLs
should include the.htmlextension.
Whentrue,Hostingautomatically drops the.htmlextension from uploaded
file URLs. If an.htmlextension is added in the request,Hostingperforms
a301redirect to the same path but eliminates the.htmlextension.
Here's how to control the inclusion of.htmlin URLs by including acleanUrlsattribute:
ThetrailingSlashattribute does not affect rewrites to dynamic content
served byCloud FunctionsorCloud Run.
Glob pattern matching
Firebase Hostingconfiguration options make extensive use of theglob pattern matchingnotation with extglob, similar to how Git handlesgitignorerules andBowerhandlesignorerules.This wiki pageis a more detailed reference,
but the following are explanations of examples used on this page:
firebase.json— Only matches thefirebase.jsonfile in the root
of thepublicdirectory
**— Matches any file or folder in an arbitrary sub-directory
*— Only matches files and folders in the root of thepublicdirectory
**/.*— Matches any file beginning with.(usually hidden files,
like in the.gitfolder) in an arbitrary sub-directory
**/node_modules/**— Matches any file or folder in an arbitrary
sub-directory of anode_modulesfolder, which can itself be in an arbitrary
sub-directory of thepublicdirectory
**/*.@(jpg|jpeg|gif|png)— Matches any file in an arbitrary
sub-directory that ends with exactly one of the following:.jpg,.jpeg,.gif, or.png
{"hosting":{"public":"dist/app",// "public" is the only required attribute forHosting"ignore":["firebase.json","**/.*","**/node_modules/**"],"redirects":[{"source":"/foo","destination":"/bar","type":301},{"source":"/firebase/**","destination":"https://www.firebase.com","type":302}],"rewrites":[{// Shows the same content for multiple URLs"source":"/app/**","destination":"/app/index.html"},{// Configures a custom domain forDynamic Links"source":"/promos/**","dynamicLinks":true},{// Directs a request toCloud Functions"source":"/bigben","function":"bigben"},{// Directs a request to aCloud Runcontainerized app"source":"/helloworld","run":{"serviceId":"helloworld","region":"us-central1"}}],"headers":[{"source":"**/*.@(eot|otf|ttf|ttc|woff|font.css)","headers":[{"key":"Access-Control-Allow-Origin","value":"*"}]},{"source":"**/*.@(jpg|jpeg|gif|png)","headers":[{"key":"Cache-Control","value":"max-age=7200"}]},{"source":"404.html","headers":[{"key":"Cache-Control","value":"max-age=300"}]}],"cleanUrls":true,"trailingSlash":false,// Required to configure custom domains forDynamic Links"appAssociation":"AUTO",}}
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-09-04 UTC."],[],[],null,[]]