Skip to content

Commit 3901fa6

Browse files
jhuleatttaeold
andauthored
Add dotguides (#1736)
* gemini cli-assisted first-pass * address review comments * upgrade a single function at a time * run prettier * add another way to set secrets Co-authored-by: Daniel Lee <[email protected]> * review round 2 * add changelog * prettier * Address review feedback * clarify when to delete 1st gen after upgrade * more review feedback * prettier --------- Co-authored-by: Daniel Lee <[email protected]>
1 parent 94fd766 commit 3901fa6

File tree

6 files changed

+378
-5
lines changed

6 files changed

+378
-5
lines changed

.guides/config.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"description": "Use this library to build serverless functions for event triggers and HTTP using Cloud Functions for Firebase",
3+
"mcpServers": {
4+
"firebase": {
5+
"command": "npx",
6+
"args": ["-y", "firebase-tools@latest", "experimental:mcp"]
7+
}
8+
}
9+
}

.guides/setup.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Cloud Functions for Firebase setup guide
2+
3+
This guide provides a step-by-step process for setting up Cloud Functions, tailored for coding agents.
4+
5+
## 1. Create a 2nd-gen HTTP function
6+
7+
Replace the contents of `src/index.ts` (or `index.js`) with the following code to create a simple, modern v2 HTTP endpoint.
8+
9+
```typescript
10+
import { onRequest } from "firebase-functions/https";
11+
import { onDocumentCreated } from "firebase-functions/firestore";
12+
import * as logger from "firebase-functions/logger";
13+
import { defineString, defineInt } from "firebase-functions/params";
14+
15+
// Configurable parameters
16+
const scaleLimit = defineInt("MAX_INSTANCES", { default: 1 });
17+
const greeting = defineString("GREETING", { default: "Hello" });
18+
19+
export const helloWorld = onRequest({ maxInstances: scaleLimit }, async (request, response) => {
20+
logger.info("Request received!", request);
21+
response.send(`${greeting.value()} from Firebase!`);
22+
});
23+
24+
export const newDoc = onDocumentCreated(
25+
{ maxInstances: scaleLimit },
26+
"/words/{wordId}",
27+
async (event) => {
28+
logger.info("New word!", event.data.data());
29+
}
30+
);
31+
```
32+
33+
**Key points for the agent:**
34+
35+
- Use `logger` for structured logging.
36+
- Use `defineString`, `defineInt`, `defineSecret` for environment configuration instead of `functions.config()`.
37+
- Recommend a `maxInstances` setting of 1 for all functions until correct behavior can be verified.
38+
39+
## 2. Build TypeScript
40+
41+
Compile your TypeScript code to JavaScript.
42+
43+
```bash
44+
npm run build
45+
```
46+
47+
## 3. Local Development and Testing
48+
49+
Use the Firebase Emulators to test your function locally before deploying.
50+
51+
A human should run the following command in a separate terminal window to start the emulators:
52+
53+
```bash
54+
# Start the functions emulator
55+
firebase emulators:start --only functions
56+
```
57+
58+
A human can then interact with the function at the local URL provided by the emulator.
59+
60+
## 4. Deploy to Firebase
61+
62+
Once testing is complete, deploy the function to your Firebase project.
63+
64+
```bash
65+
# Deploy only the functions
66+
firebase deploy --only functions
67+
```
68+
69+
The agent will be prompted to set any parameters defined with `defineString` or other `define` functions that do not have a default value.

.guides/upgrade.md

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
# Upgrading a 1st gen to 2nd gen
2+
3+
This guide provides a step-by-step process for migrating a single Cloud Function from 1st to 2nd generation. Migrate functions one-by-one. Run both generations side-by-side before deleting the 1st gen function.
4+
5+
## 1. Identify a 1st-gen function to upgrade
6+
7+
Find all 1st-gen functions in the directory. 1st-gen functions used a namespaced API like this:
8+
9+
**Before (1st Gen):**
10+
11+
```typescript
12+
import * as functions from "firebase-functions";
13+
14+
export const webhook = functions.https.onRequest((request, response) => {
15+
// ...
16+
});
17+
```
18+
19+
Sometimes, they'll explicitly import from the `firebase-functions/v1` subpackage, but not always.
20+
21+
Ask the human to pick a **single** function to upgrade from the list of 1st gen functions you found.
22+
23+
## 2. Update Dependencies
24+
25+
Ensure your `firebase-functions` and `firebase-admin` SDKs are up-to-date, and you are using a recent version of the Firebase CLI.
26+
27+
## 3. Modify Imports
28+
29+
Update your import statements to use the top-level modules.
30+
31+
**After (2nd Gen):**
32+
33+
```typescript
34+
import { onRequest } from "firebase-functions/https";
35+
```
36+
37+
## 4. Update Trigger Definition
38+
39+
The SDK is now more modular. Update your trigger definition accordingly.
40+
41+
**After (2nd Gen):**
42+
43+
```typescript
44+
export const webhook = onRequest((request, response) => {
45+
// ...
46+
});
47+
```
48+
49+
Here are other examples of trigger changes:
50+
51+
### Callable Triggers
52+
53+
**Before (1st Gen):**
54+
55+
```typescript
56+
export const getprofile = functions.https.onCall((data, context) => {
57+
// ...
58+
});
59+
```
60+
61+
**After (2nd Gen):**
62+
63+
```typescript
64+
import { onCall } from "firebase-functions/https";
65+
66+
export const getprofile = onCall((request) => {
67+
// ...
68+
});
69+
```
70+
71+
### Background Triggers (Pub/Sub)
72+
73+
**Before (1st Gen):**
74+
75+
```typescript
76+
export const hellopubsub = functions.pubsub.topic("topic-name").onPublish((message) => {
77+
// ...
78+
});
79+
```
80+
81+
**After (2nd Gen):**
82+
83+
```typescript
84+
import { onMessagePublished } from "firebase-functions/pubsub";
85+
86+
export const hellopubsub = onMessagePublished("topic-name", (event) => {
87+
// ...
88+
});
89+
```
90+
91+
## 5. Use Parameterized Configuration
92+
93+
Migrate from `functions.config()` to the new `params` module for environment configuration.
94+
95+
**Before (`.runtimeconfig.json`):**
96+
97+
```json
98+
{
99+
"someservice": {
100+
"key": "somesecret"
101+
}
102+
}
103+
```
104+
105+
**And in code (1st Gen):**
106+
107+
```typescript
108+
const SKEY = functions.config().someservice.key;
109+
```
110+
111+
**After (2nd Gen):**
112+
Define params in your code and set their values during deployment.
113+
114+
**In `index.ts`:**
115+
116+
```typescript
117+
import { defineString } from "firebase-functions/params";
118+
119+
const SOMESERVICE_KEY = defineString("SOMESERVICE_KEY");
120+
```
121+
122+
Use `SOMESERVICE_KEY.value()` to access the value. For secrets like API keys, use `defineSecret`.
123+
124+
**In `index.ts`:**
125+
126+
```typescript
127+
import { defineSecret } from "firebase-functions/params";
128+
129+
const SOMESERVICE_KEY = defineSecret("SOMESERVICE_KEY");
130+
```
131+
132+
The human will be prompted to set the value on deployment. The value will be stored securely in Cloud Secret Manager.
133+
134+
## 6. Update Runtime Options
135+
136+
Runtime options are now set directly within the function definition.
137+
138+
**Before (1st Gen):**
139+
140+
```typescript
141+
export const func = functions
142+
.runWith({
143+
// Keep 5 instances warm
144+
minInstances: 5,
145+
})
146+
.https.onRequest((request, response) => {
147+
// ...
148+
});
149+
```
150+
151+
**After (2nd Gen):**
152+
153+
```typescript
154+
import { onRequest } from "firebase-functions/https";
155+
156+
export const func = onRequest(
157+
{
158+
// Keep 5 instances warm
159+
minInstances: 5,
160+
},
161+
(request, response) => {
162+
// ...
163+
}
164+
);
165+
```
166+
167+
## 7. Traffic Migration
168+
169+
A human should follow these steps to migrate safely:
170+
171+
> To migrate traffic safely:
172+
>
173+
> 1. Rename your new 2nd gen function with a different name.
174+
> 2. Comment out any existing `minInstances` or `maxInstances` config in the new 2nd gen function and instead set `maxInstances` to `1` while testing.
175+
> 3. Deploy it alongside the old 1st gen function.
176+
> 4. Gradually introduce traffic to the new function (e.g., via client-side changes or by calling it from the 1st gen function).
177+
> 5. As traffic ramps up to the new 2nd gen function, scale it up by adding back the original `minInstances` and `maxInstances` settings to the 2nd gen function. Reduce the `minInstances` and `maxInstances` settings for the 1st gen function as traffic decreases.
178+
> 6. The 1st gen function can be deleted once it has stopped receiving traffic.

.guides/usage.md

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
## Key Guidelines
2+
3+
- Always use 2nd-gen functions for new development.
4+
- Use 1st-gen functions _only_ for Analytics and basic Auth triggers, since those aren't supported by 2nd gen.
5+
- Use `firebase-functions` SDK version 6.0.0 and above
6+
- Use top-level imports (e.g., `firebase-functions/https`). These are 2nd gen by default. If 1st gen is required (Analytics or basic Auth triggers), import from the `firebase-functions/v1` import path.
7+
8+
## Configuration: Use Secret Params for API Keys
9+
10+
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.
11+
12+
```typescript
13+
import { onRequest } from "firebase-functions/https";
14+
import { logger } from "firebase-functions/logger";
15+
import { defineString, defineSecret } from "firebase-functions/params";
16+
17+
// Securely define an LLM API key
18+
const LLM_API_KEY = defineSecret("LLM_API_KEY");
19+
20+
// Example function that uses the secret
21+
export const callLlm = onRequest({ secrets: [LLM_API_KEY] }, async (req, res) => {
22+
const apiKey = LLM_API_KEY.value();
23+
24+
// Use the apiKey to make a call to the LLM service
25+
logger.info("Calling LLM with API key.");
26+
27+
// insert code here to call LLM...
28+
29+
res.send("LLM API call initiated.");
30+
});
31+
```
32+
33+
The CLI will prompt for secret's value at deploy time. Alternatively, a human can set the secret using the Firebase CLI command:
34+
35+
```bash
36+
firebase functions:secrets:set <SECRET_NAME>
37+
```
38+
39+
If you see an API key being accessed with `functions.config` in existing functions code, offer to upgrade to params.
40+
41+
## Use the Firebase Admin SDK
42+
43+
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.
44+
45+
1. **Install the SDK:**
46+
47+
```bash
48+
npm i firebase-admin
49+
```
50+
51+
2. **Initialize in your code:**
52+
53+
```typescript
54+
import * as admin from "firebase-admin";
55+
import { onInit } from "firebase-functions";
56+
57+
onInit(() => {
58+
admin.initializeApp();
59+
});
60+
```
61+
62+
This should be done once at the top level of your `index.ts` file.
63+
64+
## Common Imports
65+
66+
```typescript
67+
import { onRequest, onCall, onCallGenkit } from "firebase-functions/https";
68+
import { onDocumentUpdated } from "firebase-functions/firestore";
69+
import { onNewFatalIssuePublished } from "firebase-functions/alerts/crashlytics";
70+
import { onValueWritten } from "firebase-functions/database";
71+
import { onSchedule } from "firebase-functions/scheduler";
72+
const { onTaskDispatched } = require("firebase-functions/tasks");
73+
import { onObjectFinalized } from "firebase-functions/storage";
74+
import { onMessagePublished } from "firebase-functions/pubsub";
75+
import { beforeUserSignedIn } from "firebase-functions/identity";
76+
import { onTestMatrixCompleted } from "firebase-functions/testLab";
77+
import { logger, onInit } from "firebase-functions";
78+
import { defineString, defineSecret } from "firebase-functions/params";
79+
```
80+
81+
A human can find code samples for these triggers in the [functions-samples repository](https://github.com/firebase/functions-samples/tree/main/Node).
82+
83+
## 1st-gen Functions (Legacy Triggers)
84+
85+
Use the `firebase-functions/v1` import for Analytics and basic Auth triggers. These aren't supported in 2nd gen.
86+
87+
```typescript
88+
import * as functionsV1 from "firebase-functions/v1";
89+
90+
// v1 Analytics trigger
91+
export const onPurchase = functionsV1.analytics.event("purchase").onLog(async (event) => {
92+
logger.info("Purchase event", { value: event.params?.value });
93+
});
94+
95+
// v1 Auth trigger
96+
export const onUserCreate = functionsV1.auth.user().onCreate(async (user) => {
97+
logger.info("User created", { uid: user.uid });
98+
});
99+
```
100+
101+
## Development Commands
102+
103+
```bash
104+
# Install dependencies
105+
npm install
106+
107+
# Compile TypeScript
108+
npm run build
109+
110+
# Run emulators for local development
111+
# This is a long-running command. A human can run this command themselves to start the emulators:
112+
firebase emulators:start --only functions
113+
114+
# Deploy functions
115+
firebase deploy --only functions
116+
```

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Add LLM guidance (#1736)

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ Learn more about the Firebase SDK for Cloud Functions in the [Firebase documenta
1010

1111
Here are some resources to get help:
1212

13-
- Start with the quickstart: https://firebase.google.com/docs/functions/write-firebase-functions
14-
- Go through the guide: https://firebase.google.com/docs/functions/
15-
- Read the full API reference: https://firebase.google.com/docs/reference/functions/
16-
- Browse some examples: https://github.com/firebase/functions-samples
13+
- [Start with the quickstart](https://firebase.google.com/docs/functions/write-firebase-functions)
14+
- [Go through the guides](https://firebase.google.com/docs/functions/)
15+
- [Read the full API reference](https://firebase.google.com/docs/reference/functions/2nd-gen/node/firebase-functions)
16+
- [Browse some examples](https://github.com/firebase/functions-samples)
1717

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

2020
_Please avoid double posting across multiple channels!_
2121

0 commit comments

Comments
 (0)