Deploy Firebase Hosting Sites on GCP

The gcp:firebase/hostingSite:HostingSite resource, part of the Pulumi GCP provider, provisions a Firebase Hosting site: the container for static content and web app hosting. This guide focuses on three capabilities: standalone site creation, web app integration, and default site provisioning.

Hosting sites require a Firebase-enabled GCP project and optionally reference a Firebase web app for integration. The examples are intentionally small. Combine them with your own content deployment and custom domain configuration.

Create a standalone hosting site

Teams often create hosting sites that aren’t tied to a specific web app, allowing them to serve static content or multiple apps from a single endpoint.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const _default = new gcp.firebase.HostingSite("default", {
    project: "my-project-name",
    siteId: "site-no-app",
});
import pulumi
import pulumi_gcp as gcp

default = gcp.firebase.HostingSite("default",
    project="my-project-name",
    site_id="site-no-app")
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/firebase"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := firebase.NewHostingSite(ctx, "default", &firebase.HostingSiteArgs{
			Project: pulumi.String("my-project-name"),
			SiteId:  pulumi.String("site-no-app"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var @default = new Gcp.Firebase.HostingSite("default", new()
    {
        Project = "my-project-name",
        SiteId = "site-no-app",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.firebase.HostingSite;
import com.pulumi.gcp.firebase.HostingSiteArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var default_ = new HostingSite("default", HostingSiteArgs.builder()
            .project("my-project-name")
            .siteId("site-no-app")
            .build());

    }
}
resources:
  default:
    type: gcp:firebase:HostingSite
    properties:
      project: my-project-name
      siteId: site-no-app

The siteId property sets a globally unique identifier that Firebase uses to construct the site’s subdomain (e.g., site-no-app.web.app). Without an appId, the site operates independently of any Firebase web app, suitable for static content or multi-app scenarios.

When you want to associate a hosting site with a specific Firebase web app, you can link them together to enable app-specific features and analytics.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const _default = new gcp.firebase.WebApp("default", {
    project: "my-project-name",
    displayName: "Test web app for Firebase Hosting",
});
const full = new gcp.firebase.HostingSite("full", {
    project: "my-project-name",
    siteId: "site-with-app",
    appId: _default.appId,
});
import pulumi
import pulumi_gcp as gcp

default = gcp.firebase.WebApp("default",
    project="my-project-name",
    display_name="Test web app for Firebase Hosting")
full = gcp.firebase.HostingSite("full",
    project="my-project-name",
    site_id="site-with-app",
    app_id=default.app_id)
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/firebase"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_default, err := firebase.NewWebApp(ctx, "default", &firebase.WebAppArgs{
			Project:     pulumi.String("my-project-name"),
			DisplayName: pulumi.String("Test web app for Firebase Hosting"),
		})
		if err != nil {
			return err
		}
		_, err = firebase.NewHostingSite(ctx, "full", &firebase.HostingSiteArgs{
			Project: pulumi.String("my-project-name"),
			SiteId:  pulumi.String("site-with-app"),
			AppId:   _default.AppId,
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var @default = new Gcp.Firebase.WebApp("default", new()
    {
        Project = "my-project-name",
        DisplayName = "Test web app for Firebase Hosting",
    });

    var full = new Gcp.Firebase.HostingSite("full", new()
    {
        Project = "my-project-name",
        SiteId = "site-with-app",
        AppId = @default.AppId,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.firebase.WebApp;
import com.pulumi.gcp.firebase.WebAppArgs;
import com.pulumi.gcp.firebase.HostingSite;
import com.pulumi.gcp.firebase.HostingSiteArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var default_ = new WebApp("default", WebAppArgs.builder()
            .project("my-project-name")
            .displayName("Test web app for Firebase Hosting")
            .build());

        var full = new HostingSite("full", HostingSiteArgs.builder()
            .project("my-project-name")
            .siteId("site-with-app")
            .appId(default_.appId())
            .build());

    }
}
resources:
  default:
    type: gcp:firebase:WebApp
    properties:
      project: my-project-name
      displayName: Test web app for Firebase Hosting
  full:
    type: gcp:firebase:HostingSite
    properties:
      project: my-project-name
      siteId: site-with-app
      appId: ${default.appId}

The appId property connects the hosting site to a Firebase web app, enabling integrated features like Firebase Authentication and Analytics. The web app must be created first, then its appId is passed to the hosting site. This extends the basic example by adding web app integration.

Create the default site for a project

Every Firebase project can have one default hosting site that uses the project ID as its site identifier, providing a predictable URL pattern.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const _default = new gcp.firebase.HostingSite("default", {
    project: "my-project-name",
    siteId: "my-project-name",
});
import pulumi
import pulumi_gcp as gcp

default = gcp.firebase.HostingSite("default",
    project="my-project-name",
    site_id="my-project-name")
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/firebase"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := firebase.NewHostingSite(ctx, "default", &firebase.HostingSiteArgs{
			Project: pulumi.String("my-project-name"),
			SiteId:  pulumi.String("my-project-name"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var @default = new Gcp.Firebase.HostingSite("default", new()
    {
        Project = "my-project-name",
        SiteId = "my-project-name",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.firebase.HostingSite;
import com.pulumi.gcp.firebase.HostingSiteArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var default_ = new HostingSite("default", HostingSiteArgs.builder()
            .project("my-project-name")
            .siteId("my-project-name")
            .build());

    }
}
resources:
  default:
    type: gcp:firebase:HostingSite
    properties:
      project: my-project-name
      siteId: my-project-name

When siteId matches the project ID, Firebase provisions the project’s default hosting site. This creates a predictable URL (my-project-name.web.app) and follows Firebase’s convention for the primary site in a project.

Beyond these examples

These snippets focus on specific hosting site features: standalone and app-linked hosting sites, and default site provisioning. They’re intentionally minimal rather than full hosting deployments.

The examples require pre-existing infrastructure such as a Firebase-enabled GCP project, and a Firebase web app for app-linked sites. They focus on provisioning the hosting site rather than deploying content or configuring domains.

To keep things focused, common hosting patterns are omitted, including:

  • Custom domain configuration
  • SSL certificate management
  • Content deployment and versioning
  • Hosting configuration (redirects, headers, rewrites)

These omissions are intentional: the goal is to illustrate how each hosting site feature is wired, not provide drop-in hosting modules. See the Firebase HostingSite resource reference for all available configuration options.

Let's deploy Firebase Hosting Sites

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Site Configuration & Setup
What are the requirements for a Firebase Hosting site ID?
The siteId must be globally unique and a valid domain name label, as it’s used to construct the Firebase-provisioned subdomain for your site.
Do I need to link my Firebase Hosting site to a web app?
No, linking a web app is optional. You can create a site with just siteId and project, or optionally set appId to link it to an existing Firebase Web App.
What's a default Firebase Hosting site?
A default site is created when you set siteId to match your project name. This creates a site with type DEFAULT_SITE.
URLs & Site Types
What URL will my Firebase Hosting site get?
Your site receives a default URL in the format https://{name}.web.app, available in the defaultUrl output property.
What's the difference between DEFAULT_SITE and USER_SITE?
The type output property indicates whether your site is a DEFAULT_SITE (typically when siteId matches project name) or a USER_SITE (additional sites in the project).
Immutability & Limitations
What properties can't be changed after creating a Firebase Hosting site?
Both siteId and project are immutable. Changing either requires recreating the resource.

Using a different cloud?

Explore compute guides for other cloud providers: