-
Notifications
You must be signed in to change notification settings - Fork 6
add firebase-functions-basics #15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
496ed2b
f65ab01
0075f47
628dd86
5b0dab9
addcf4c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| --- | ||
| name: firebase-functions-basics | ||
| description: Guide for setting up and using Cloud Functions for Firebase. Use this skill when the user's app requires server-side logic, integrating with third-party APIs, or responding to Firebase events. | ||
| compatibility: This skill requires the Firebase CLI. Install it by running `npm install -g firebase-tools`. | ||
| --- | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - **Firebase Project**: Created via `firebase projects:create` (see `firebase-basics`). | ||
| - **Firebase CLI**: Installed and logged in (see `firebase-basics`). | ||
|
|
||
| ## Core Concepts | ||
|
|
||
| Cloud Functions for Firebase lets you automatically run backend code in response to events triggered by Firebase features and HTTPS requests. Your code is stored in Google's cloud and runs in a managed environment. | ||
|
|
||
| ### Generation 1 vs Generation 2 | ||
|
|
||
| This section only applies to Node.js, since all Python functions are 2nd gen. | ||
|
|
||
| - Always use 2nd-gen functions for new development. They are powered by Cloud Run and offer better performance and configurability. | ||
| - Use 1st-gen functions *only* for Analytics and basic Auth triggers, since those aren't supported by 2nd gen. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I might modify this. Maybe "discourage analytics functions because they will not be supported in 2nd gen." and something around the idea that auth functions may not be released yet, use them if they are but use 1st gen otherwise. They are coming imminently (though they have been for ages). |
||
| - 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. If 1st gen is required (Analytics or basic Auth triggers), import from the `firebase-functions/v1` import path. | ||
jhuleatt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| ### Secrets Management | ||
|
|
||
| For sensitive information like API keys (e.g., for LLMs, payment providers, etc.), **always** use `defineSecret` (Node.js) or `SecretParam` (Python). This stores the value securely in Cloud Secret Manager. | ||
|
|
||
| ### 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. | ||
|
|
||
| ## Workflow | ||
|
|
||
| ### 1. Provisioning & Setup | ||
|
|
||
| Functions can be initialized using the CLI or manually. Ensure you have initialized the Firebase Admin SDK to interact with other Firebase services. | ||
|
|
||
| 1. Install the Admin SDK: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this Node.js-specific? If so, it probably belongs in the lower-level references file. I'm no coding genius, but I'm thinking this file is leaning Node and possibly neglecting Python and other runtimes-to-be. If we can make it language agnostic, that would be a win I think.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This may be redundant with what's in the node setup. We're also being inconsistent with initializeApp. I like using it in onInit tbh |
||
|
|
||
| ```bash | ||
| npm i firebase-admin | ||
| ``` | ||
|
|
||
| 2. Initialize in your code: | ||
|
|
||
| ```typescript | ||
| import { initializeApp } from "firebase-admin/app"; | ||
| import { onInit } from "firebase-functions"; | ||
|
|
||
| onInit(() => { | ||
| initializeApp(); | ||
| }); | ||
| ``` | ||
|
|
||
| This should be done once at the top level of your `index.ts` file. | ||
|
|
||
| ### 2. Writing Functions | ||
|
|
||
| For Node.js, see [references/node_setup.md](references/node_setup.md). For Python, see [references/python_setup.md](references/python_setup.md) | ||
|
|
||
| ### 3. Local Development & Deployment | ||
|
|
||
| The CLI will prompt for a secret's value at deploy time. Alternatively, a human can set the secret using the Firebase CLI command: | ||
|
|
||
| ```bash | ||
| firebase functions:secrets:set <SECRET_NAME> | ||
| ``` | ||
|
|
||
| #### Development Commands | ||
|
|
||
| ```bash | ||
| # Install dependencies | ||
| npm install | ||
|
|
||
| # Compile TypeScript | ||
| npm run build | ||
|
|
||
| # Run emulators for local development | ||
| # This is a long-running command. A human can run this command themselves to start the emulators: | ||
| firebase emulators:start --only functions | ||
|
|
||
| # Deploy functions | ||
| firebase deploy --only functions | ||
| ``` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| # Cloud Functions for Firebase setup guide | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The thing people hate about params is that they can't use it at global scope. I wonder if we should update the skill to show a use of onInit? |
||
|
|
||
| This guide provides a step-by-step process for setting up Cloud Functions, tailored for coding agents. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we specify "with the Node.js runtime," and also add a "(Node.js)" to the title line? |
||
|
|
||
| ## 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. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like the clarification below in the Python page: "along with a Firestore-triggered function." |
||
|
|
||
| ```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) => { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: If you're going to use scaleLimit repeatedly, should it be in setGlobalOptions? |
||
| 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:** | ||
|
|
||
| - Use `logger` for structured logging. | ||
| - Use `defineString`, `defineInt`, `defineSecret` for environment configuration. | ||
| - Recommend a `maxInstances` setting of 1 for all functions until correct behavior can be verified. | ||
|
|
||
| ## 2. Build TypeScript | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we missing a dependencies step? Or do we assume they installed with Node.js dependencies?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we mention that building isn't necessary before deploying? |
||
|
|
||
| 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. | ||
|
|
||
| A human should run the following command in a separate terminal window to start the emulators: | ||
|
|
||
| ```bash | ||
| # Start the functions emulator | ||
| firebase emulators:start --only functions | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we expand this to say you should be running tsc --watch concurrently if running typescript? TIL you can run: We should even consider making this the dev script? |
||
| ``` | ||
|
|
||
| A human 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. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| # Cloud Functions for Firebase setup guide (Python) | ||
|
|
||
| This guide provides a step-by-step process for setting up Cloud Functions with the Python runtime, tailored for coding agents. | ||
|
|
||
| ## 1. Create a 2nd-gen HTTP function | ||
|
|
||
| Replace the contents of `functions/main.py` with the following code to create a simple, modern v2 HTTP endpoint along with a Firestore-triggered function. | ||
|
|
||
| ```python | ||
| from firebase_functions import https_fn, firestore_fn, options, params | ||
| from firebase_admin import initialize_app, firestore | ||
| import google.cloud.firestore | ||
|
|
||
| app = initialize_app() | ||
|
|
||
| # Configurable parameters | ||
| SCALE_LIMIT = params.IntParam("MAX_INSTANCES", default=1).value | ||
| GREETING = params.StringParam("GREETING", default="Hello").value | ||
|
|
||
|
|
||
| @https_fn.on_request( | ||
| cors=options.CorsOptions(cors_origins="*", cors_methods=["get", "post"]), | ||
| max_instances=SCALE_LIMIT, | ||
| ) | ||
| def helloworld(req: https_fn.Request) -> https_fn.Response: | ||
| """A simple HTTP-triggered function.""" | ||
| print("Request received!") | ||
| return https_fn.Response(f"{GREETING} from Firebase!") | ||
|
|
||
|
|
||
| @firestore_fn.on_document_created(document="words/{wordId}", max_instances=SCALE_LIMIT) | ||
| def newdoc(event: firestore_fn.Event[firestore_fn.DocumentSnapshot | None]) -> None: | ||
| """Triggered when a new document is created in /words.""" | ||
| if event.data is None: | ||
| return | ||
| print(f"New word: {event.data.to_dict()}") | ||
| ``` | ||
|
|
||
| **Key points for the agent:** | ||
|
|
||
| - Use `print()` for logging (output goes to Cloud Logging automatically). | ||
| - Use `params.StringParam`, `params.IntParam`, and `params.SecretParam` for environment configuration. | ||
| - Recommend a `max_instances` setting of 1 for all functions until correct behavior can be verified. | ||
| - The entry point is always `functions/main.py`. All functions must be defined in or imported into this file. | ||
| - Dependencies go in `functions/requirements.txt`. | ||
|
|
||
| ## 2. Install dependencies | ||
|
|
||
| Ensure `functions/requirements.txt` lists the needed packages: | ||
|
|
||
| ``` | ||
| firebase-functions | ||
| firebase-admin | ||
| ``` | ||
|
|
||
| Then install with: | ||
|
|
||
| ```bash | ||
| pip install -r functions/requirements.txt | ||
| ``` | ||
|
|
||
| There is no build step for Python (unlike TypeScript). | ||
|
|
||
| ## 3. Local Development and Testing | ||
|
|
||
| Use the Firebase Emulators to test your function locally before deploying. | ||
|
|
||
| A human should run the following command in a separate terminal window to start the emulators: | ||
|
|
||
| ```bash | ||
| # Start the functions emulator | ||
| firebase emulators:start --only functions | ||
| ``` | ||
|
|
||
| A human 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 | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Auth triggers are on the near horizon, right? Is there a way to comment or flag this for update when we get them?