Skip to content
9 changes: 9 additions & 0 deletions .guides/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"description": "Use this library to build serverless functions for event triggers and HTTP using Firebase and Cloud Run Functions",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we saying "Firebase and Cloud Run Functions" very deliberately, for a good reason?

If not, I'd avoid mention of a separate product, and just go with "using Cloud Functions for Firebase."

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

"mcpServers": {
"firebase": {
"command": "npx",
"args": ["-y", "firebase-tools@latest", "experimental:mcp"]
}
}
}
69 changes: 69 additions & 0 deletions .guides/setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Cloud Functions for Firebase setup guide

This guide provides a step-by-step process for setting up a new Firebase Functions project, tailored for a coding agent.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should watch out for this non-official naming . . . suggest just "Cloud Functions."

Also suggest "coding agents."

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed


## 1. Create a 2nd-gen HTTP function

Replace the contents of `src/index.ts` (or `index.js`) with the following code to create a simple, modern v2 HTTP endpoint.

```typescript
import { onRequest } from "firebase-functions/https";
import { onDocumentCreated } from "firebase-functions/firestore";
import * as logger from "firebase-functions/logger";
import { defineString, defineInt } from "firebase-functions/params";

// Configurable parameters
const scaleLimit = defineInt("MAX_INSTANCES", { default: 1 });
const greeting = defineString("GREETING", { default: "Hello" });

export const helloWorld = onRequest({ maxInstances: scaleLimit }, async (request, response) => {
logger.info("Request received!", request);
response.send(`${greeting.value()} from Firebase!`);
});

export const newDoc = onDocumentCreated(
{ maxInstances: scaleLimit },
"/words/{wordId}",
async (event) => {
logger.info("New word!", event.data.data());
}
);
```

**Key points for the agent:**

- Always import from `firebase-functions/*` for new functions.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to call out the Auth and Analytics exceptions? "Always" is a strong word to a robot.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll remove this bullet point, I think we have enough examples in here that it isn't needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

plus, everything is under "firebase-functions/*" so it isn't really saying anything

- Use `logger` for structured logging.
- Use `defineString`, `defineInt`, `defineSecret` for environment configuration instead of `functions.config()`.

## 2. Build TypeScript

Compile your TypeScript code to JavaScript.

```bash
npm run build
```

## 3. Local Development and Testing

Use the Firebase Emulators to test your function locally before deploying.

Tell the user to run the following command in a separate terminal window to start the emulators:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would "developer" be a better term than user?

Just thinking of how literal-minded an agent might be.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated to "human" #1736 (comment)


```bash
# Start the functions emulator
firebase emulators:start --only functions
```

The user can then interact with the function at the local URL provided by the emulator.

## 4. Deploy to Firebase

Once testing is complete, deploy the function to your Firebase project.

```bash
# Deploy only the functions
firebase deploy --only functions
```

The agent will be prompted to set any parameters defined with `defineString` or other `define` functions that do not have a default value.
178 changes: 178 additions & 0 deletions .guides/upgrade.md
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this can be really powerful, but we need to be careful. Maybe the goal of /upgrade should be to upgrade a single function at a time and the guide should be written in that way - like step 1 find v1 functions step 2 ask user which function to upgrade and then it has the guidance to do that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that does sound safer. I've changed step 1 to find and prompt for a single function to migrate.

Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# Upgrading a Firebase Function to 2nd Gen

This guide provides a step-by-step process for migrating a single Cloud Function from 1st to 2nd generation. Migrate functions incrementally, running both generations side-by-side.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we need to be more specific in terms of " one by one" or " each additional function discreetly," again because the agent might have a different way of interpreting " incrementally" such as maybe line by line.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated


## 1. Identify a 1st-gen function to upgrade

Find all 1st-gen functions in the directory. 1st-gen functions used a namespaced API like this:

**Before (1st Gen):**

```typescript
import * as functions from "firebase-functions";

export const webhook = functions.https.onRequest((request, response) => {
// ...
});
```

Sometimes, they'll explicitly import from the `firebase-functions/v1` subpackage, but not always.
Comment on lines +7 to +19
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@taeold this seems like a cool opportunity for an mcp tool

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MCP tools for something very niche like "find all v1 functions" are a bit of a tough sell for me, but what you can do is pre-specify shell commands that will get the info you want. For example a find or grep or sed command that helps it find all the files it needs to look at.


Ask the user to pick a **single** function to upgrade from the list of 1st gen functions you found.

## 2. Update Dependencies

Ensure your `firebase-functions` and `firebase-admin` SDKs are up-to-date, and you are using a recent version of the Firebase CLI.

## 3. Modify Imports

Update your import statements to use the top-level modules.

**After (2nd Gen):**

```typescript
import { onRequest } from "firebase-functions/https";
```

## 4. Update Trigger Definition

The SDK is now more modular. Update your trigger definition accordingly.

**After (2nd Gen):**

```typescript
export const webhook = onRequest((request, response) => {
// ...
});
```

Here are other examples of trigger changes:

### Callable Triggers

**Before (1st Gen):**

```typescript
export const getprofile = functions.https.onCall((data, context) => {
// ...
});
```

**After (2nd Gen):**

```typescript
import { onCall } from "firebase-functions/https";

export const getprofile = onCall((request) => {
// ...
});
```

### Background Triggers (Pub/Sub)

**Before (1st Gen):**

```typescript
export const hellopubsub = functions.pubsub.topic("topic-name").onPublish((message) => {
// ...
});
```

**After (2nd Gen):**

```typescript
import { onMessagePublished } from "firebase-functions/pubsub";

export const hellopubsub = onMessagePublished("topic-name", (event) => {
// ...
});
```

## 5. Use Parameterized Configuration

Migrate from `functions.config()` to the new `params` module for environment configuration.

**Before (`.runtimeconfig.json`):**

```json
{
"someservice": {
"key": "somesecret"
}
}
```

**And in code (1st Gen):**

```typescript
const SKEY = functions.config().someservice.key;
```

**After (2nd Gen):**
Define params in your code and set their values during deployment.

**In `index.ts`:**

```typescript
import { defineString } from "firebase-functions/params";

const SOMESERVICE_KEY = defineString("SOMESERVICE_KEY");
```

Use `SOMESERVICE_KEY.value()` to access the value. For secrets like API keys, use `defineSecret`.

**In `index.ts`:**

```typescript
import { defineSecret } from "firebase-functions/params";

const SOMESERVICE_KEY = defineSecret("SOMESERVICE_KEY");
```

You will be prompted to set the value on deployment, which is stored securely in Cloud Secret Manager.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the agent to the deployment, or would this be "The developer will be prompted?"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the Flutter team settled on "human". I'll update all uses of "user" to "human".


## 6. Update Runtime Options

Runtime options are now set directly within the function definition.

**Before (1st Gen):**

```typescript
export const func = functions
.runWith({
// Keep 5 instances warm
minInstances: 5,
})
.https.onRequest((request, response) => {
// ...
});
```

**After (2nd Gen):**

```typescript
import { onRequest } from "firebase-functions/https";

export const func = onRequest(
{
// Keep 5 instances warm
minInstances: 5,
},
(request, response) => {
// ...
}
);
```

## 7. Traffic Migration

Tell the user these steps to migrate safely:

> To migrate traffic safely:
>
> 1. Rename your new 2nd gen function with a different name.
> 2. Comment out any existing `minInstances` or `maxInstances` config and instead set `maxInstances` to `1` while testing.
> 3. Deploy it alongside the old 1st gen function.
> 4. Gradually introduce traffic to the new function (e.g., via client-side changes or by calling it from the 1st gen function).
> 5. Add back the original `minInstances` and `maxInstances` settings to the 2nd gen function.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we specify a condition for step 5, like " After all traffic has been redirected to the new 2nd gen function, …" ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea, updated

> 6. Once you are confident, you can delete the 1st gen function.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By the same token, I wonder how an agent will interpret its level of confidence . . . we may need to be more specific/ less emotional :).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

118 changes: 118 additions & 0 deletions .guides/usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
## Key Guidelines

- Always use 2nd-gen functions for new development.
- Use 1st-gen functions _only_ for Analytics and basic Auth triggers.
- Use `firebase-functions` SDK version 6.0.0 and above
- Use top-level imports (e.g., `firebase-functions/https`). These are 2nd gen by default.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to be clear that Auth and analytics are going to be exceptions to this rule RE top-level imports?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated


## Configuration: Use Secret Params for API Keys

For sensitive information like API keys (e.g., for LLMs, payment providers, etc.), **always** use `defineSecret`. This stores the value securely in Cloud Secret Manager.

```typescript
import { onRequest } from "firebase-functions/https";
import { logger } from "firebase-functions/logger";
import { defineString, defineSecret } from "firebase-functions/params";

// Securely define an LLM API key
const LLM_API_KEY = defineSecret("LLM_API_KEY");

// Example function that uses the secret
export const callLlm = onRequest({ secrets: [LLM_API_KEY] }, async (req, res) => {
const apiKey = LLM_API_KEY.value();

// Use the apiKey to make a call to the LLM service
logger.info("Calling LLM with API key.");

// insert code here to call LLM...

res.send("LLM API call initiated.");
});
```

When you deploy a function with `secrets`, the CLI will prompt you to enter the secret's value. Alternatively, you can instruct the user to set the secret using the Firebase CLI command:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deployment question again -- is the agent doing the deploying? If so, "you" is fine (agents are the New You!! :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

simplified this


```bash
firebase functions:secrets:set <SECRET_NAME>
```

If you see an API key being accessed with `functions.config` in the user's code, instruct them to upgrade to params.

## Use the Firebase Admin SDK

To interact with Firebase services like Firestore, Auth, or RTDB from within your functions, you need to initialize the Firebase Admin SDK. Call `initializeApp` without any arguments so that Application Default Credentials are used.

1. **Install the SDK:**

```bash
npm i firebase-admin
```

2. **Initialize in your code:**

```typescript
import * as admin from "firebase-admin";
import { onInit } from "firebase-functions";
onInit(() => {
admin.initializeApp();
});
```
This should be done once at the top level of your `index.ts` file.
## Common Imports
```typescript
import { onRequest, onCall, onCallGenkit } from "firebase-functions/https";
import { onDocumentUpdated } from "firebase-functions/firestore";
import {
onNewFatalIssuePublished,
} from "firebase-functions/alerts/crashlytics";
import { onValueWritten } from "firebase-functions/database";
import { onSchedule } from "firebase-functions/scheduler";
const {onTaskDispatched} = require("firebase-functions/tasks");
import { onObjectFinalized } from "firebase-functions/storage";
import { onMessagePublished } from "firebase-functions/pubsub";
import { beforeUserSignedIn } from "firebase-functions/identity";
import {onTestMatrixCompleted} from "firebase-functions/testLab";
import { logger, onInit } from "firebase-functions";
import { defineString, defineSecret } from "firebase-functions/params";
```
Let the user know that code samples for these triggers are available in the [functions-samples repository](https://github.com/firebase/functions-samples/tree/main/Node).
## 1st-gen Functions (Legacy Triggers)
Use the `firebase-functions/v1` import for Analytics and basic Auth triggers. These aren't supported in 2nd gen.
```typescript
import * as functionsV1 from "firebase-functions/v1";
// v1 Analytics trigger
export const onPurchase = functionsV1.analytics.event("purchase").onLog(async (event) => {
logger.info("Purchase event", { value: event.params?.value });
});
// v1 Auth trigger
export const onUserCreate = functionsV1.auth.user().onCreate(async (user) => {
logger.info("User created", { uid: user.uid });
});
```
## Development Commands
```bash
# Install dependencies
npm install
# Compile TypeScript
npm run build
# Run emulators for local development
# This is a long-running command. Tell the user to run this command themselves to start the emulators:
firebase emulators:start --only functions
# Deploy functions
firebase deploy --only functions
```
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Add LLM guidance (#1736)
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ Learn more about the Firebase SDK for Cloud Functions in the [Firebase documenta

Here are some resources to get help:

- Start with the quickstart: https://firebase.google.com/docs/functions/write-firebase-functions
- Go through the guide: https://firebase.google.com/docs/functions/
- Read the full API reference: https://firebase.google.com/docs/reference/functions/
- Browse some examples: https://github.com/firebase/functions-samples
- [Start with the quickstart](https://firebase.google.com/docs/functions/write-firebase-functions)
- [Go through the guide](https://firebase.google.com/docs/functions/)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we point them to functions/get-started?

If our aim is more general, let's pluralize "guides"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

- [Read the full API reference](https://firebase.google.com/docs/reference/functions/)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This reference link goes to a top-level "nav" page that includes 1st gen. Do we want instead to go directly to https://firebase.google.com/docs/reference/functions/2nd-gen/node/firebase-functions?"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

- [Browse some examples](https://github.com/firebase/functions-samples)

If the official documentation doesn't help, try asking through our official support channels: https://firebase.google.com/support/
If the official documentation doesn't help, try asking through our [official support channels](https://firebase.google.com/support/)

_Please avoid double posting across multiple channels!_

Expand Down
Loading