extension-to-functions-codebase
Skill for converting an installed Firebase Extension (or extension source) into a standalone Cloud Functions for Firebase codebase or publishable npm package, including V1 to V2 trigger upgrades, lifecycle hooks, and declarative security
Works with
---
name: extension-to-functions-codebase
description: Skill for converting an installed Firebase Extension (or extension source) into a standalone Cloud Functions for Firebase codebase or publishable npm package, including V1 to V2 trigger upgrades, lifecycle hooks, and declarative security
license: Apache-2.0
---
# Extension to Functions Codebase & npm Package Migration
## Overview
Migrates a Firebase Extension into either:
1. **A local Cloud Functions codebase** (`functions/src/` for app integration).
1. **A publishable npm package** (reusable open-source package exporting V2
functions).
Leverages native Cloud Functions features (declarative IAM, Parameterized
Config, SDK Lifecycle Hooks) and modernizes 1st Gen triggers to 2nd Gen using
the Destructuring Compatibility Shim.
______________________________________________________________________
## Target Migration Workflows
- **Target A: Local Functions Codebase** (End-User App Integration)
- Output: Code under `functions/src/`. Config in `.env`.
- Deployment: `firebase deploy --only functions`.
- **Target B: Publishable npm Package / Shareable Package**
- Output: Reusable npm package exporting V2 functions.
- Configuration: `package.json` specifying `exports` map,
`engines: { "node": ">=22" }`, and
`peerDependencies: { "firebase-functions": ">=6.0.0" }`.
- Usage: Consumers install package and re-export functions in `index.ts`
(`export * from "<package-name>"`).
______________________________________________________________________
## Core Rules & Constraints
### 1. Declarative IAM & APIs (Zero-Local-Overhead)
Use native SDK declarations instead of manual `gcloud` scripts or console
instructions:
- Use `requiresRole("roles/...")` for required GCP IAM permissions.
- Use `requiresAPI("service.googleapis.com", "Description")` for Google APIs.
### 2. Global Parameter Access Restriction
- **Never call `.value()` at top-level module load scope.**
- Initialize global SDK instances inside `onInit()` or lazy getters:
```typescript
import { defineString } from "firebase-functions/params";
import { onInit } from "firebase-functions/v2";
const dataset = defineString("DATASET_ID");
let client: BigQuery;
onInit(() => {
client = new BigQuery({ datasetId: dataset.value() });
});
```
### 3. V2 Concurrency & Cost Parity
V2 enables concurrency (up to 80 requests). To preserve V1 single-concurrency
pricing, set `cpu: "gcf_gen1"`.
______________________________________________________________________
## Step-by-Step Migration Execution
### Step 1: Inventory Extension Resources
1. **`extension.yaml`**:
- `params` → `defineString`, `defineInt`, `defineBoolean`, `defineSecret`.
- `apis` → `requiresAPI(...)`.
- `roles` → `requiresRole(...)`.
- `lifecycleEvents` → `afterFirstDeploy` & `afterRedeploy`.
- `resources` → Upgrade 1st Gen triggers to 2nd Gen (`onDocumentWritten`,
`onTaskDispatched`, `onRequest`).
1. **Files & Scripts**: Preserve devDependencies, test framework (`jest`), and
test scripts.
### Step 2: Configure `package.json`
- Set `name: "<package-name>"`, `engines: { "node": ">=22" }`.
- Set `peerDependencies`:
```json
"peerDependencies": {
"firebase-admin": "^11.0.0 || ^12.0.0",
"firebase-functions": ">=6.0.0"
}
```
- Configure `exports` map targeting ESM/CommonJS and TypeScript declarations
(`lib/index.js`, `lib/index.d.ts`).
### Step 3: Upgrade Triggers from V1 to V2
- Firestore: Use `onDocumentWritten` from `firebase-functions/v2/firestore`.
- Tasks: Use `onTaskDispatched` from `firebase-functions/v2/tasks`. Remove
`EXT_INSTANCE_ID` when enqueueing tasks.
- HTTP: Use `onRequest` from `firebase-functions/v2/https`.
- Apply Destructuring Compatibility Shim (`{ change, context }`,
`{ snapshot, context }`) where legacy 1st Gen handlers expect
`(change, context)`.
### Step 4: Convert Lifecycle Events
Map extension lifecycle events to SDK lifecycle hooks in `src/index.ts`:
- `onInstall` → `afterFirstDeploy({ task: { function: "initTask" } })`
- `onUpdate` / `onConfigure` →
`afterRedeploy({ task: { function: "setupTask" } })`
### Step 5: Package README & Export Instructions
Generate `README.md` containing:
1. Installation instructions (`npm install`).
1. Re-export snippet (`export * from "<package-name>"`).
1. Parameterized Configuration `.env` reference table.
1. What Changed (Extension vs Package) comparison table.
_Reminder: NEVER execute `npm publish`._More General & Other skills
find-skills
vercel-labs/skills
Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.
grill-me
mattpocock/skills
A relentless interview to sharpen a plan or design.
grill-with-docs
mattpocock/skills
A relentless interview to sharpen a plan or design, which also creates docs (ADR's and glossary) as we go.

