From 52112254687c3d49d31d0cb5e43f028837584507 Mon Sep 17 00:00:00 2001 From: sedanah-m Date: Thu, 10 Sep 2026 17:59:26 -0400 Subject: [PATCH 01/11] WIP: add server prompt template feature --- .../server-prompt-templates/README.md | 78 +++++++++ .../server-prompt-templates/index.tsx | 149 ++++++++++++++++++ .../server-prompt-templates/service.ts | 34 ++++ ai/ai-samples/src/index.tsx | 14 +- 4 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 ai/ai-samples/src/features/server-prompt-templates/README.md create mode 100644 ai/ai-samples/src/features/server-prompt-templates/index.tsx create mode 100644 ai/ai-samples/src/features/server-prompt-templates/service.ts diff --git a/ai/ai-samples/src/features/server-prompt-templates/README.md b/ai/ai-samples/src/features/server-prompt-templates/README.md new file mode 100644 index 000000000..a6e07f6bd --- /dev/null +++ b/ai/ai-samples/src/features/server-prompt-templates/README.md @@ -0,0 +1,78 @@ +# Firebase AI Logic: Server Prompt Templates Sample + +This quickstart demonstrates how to fetch and execute centrally managed prompt templates stored in the Firebase Console using the Firebase AI Logic SDK. + +## Why Server Prompt Templates? + +- **No deployment updates**: Change prompts, tune system instructions, or switch underlying models directly in the Firebase Console without having to release a new app version. +- **Security**: Protect against exposing your prompt client-side. + +--- + +## 1. Firebase Console Setup + +Before running this sample, create and lock the template in your Firebase project: + +1. Open the [Firebase Console](https://console.firebase.google.com/) and select your project. +2. In the left navigation, navigate to **AI Logic > Prompt Templates**. +3. Click **Create Template**. Note that these starter templates provide the format and syntax for some common use cases and this tutorial assumes you've selected the `Input + System Instructions` option. Once you clicked that, configure the following: + - **Template ID**: `invoice-generator` + - **Model**: `gemini-3.5-flash-lite` (or any available Gemini model) +4. In the **Prompt Content** / **System Instructions** text area, paste the following prompt: + ```text + {{role "system"}} + All output must be a clearly structured invoice document. + Use a tabular or clearly delineated list format for line items. + + {{role "user"}} + Create an example customer invoice for a customer named {{customerName}}. + ``` +5. Click **Save**. +6. **Important**: Click **Lock** (or **Publish**). Client SDKs can only execute locked/published templates. Unlocked templates remain in draft mode and will return `NOT_FOUND` to client applications. + + + +--- + +## 2. Running the Sample Locally + +Run the sample inside the full app shell: +```bash +npm run dev +``` + +Or run this feature directly in isolated mode: +```bash +npm run dev:template +``` + +Open your browser to the local URL (e.g., `http://localhost:XXXX/server-prompt-templates`). + +--- + +## 3. Using in Your Own Project + +To use Server Prompt Templates in any JavaScript or TypeScript project, copy [`service.ts`](./service.ts): + +```ts +import { getAI, getTemplateGenerativeModel } from 'firebase/ai'; +import { initializeApp } from 'firebase/app'; + +const app = initializeApp(firebaseConfig); +const ai = getAI(app); +const model = getTemplateGenerativeModel(ai); +const result = await model.generateContent('invoice-generator', { + customerName: 'Jane Doe', +}); +console.log(result.response.text()); + +// TODO: Add example for model.startChat with templateId once template-grounded multi-turn chat is explored +``` + +--- + +## 4. Troubleshooting & Failure Surfaces + +// make a table for template ID mismatch +// missing variable output +// AI Logic API enabling note \ No newline at end of file diff --git a/ai/ai-samples/src/features/server-prompt-templates/index.tsx b/ai/ai-samples/src/features/server-prompt-templates/index.tsx new file mode 100644 index 000000000..1cb1f8e92 --- /dev/null +++ b/ai/ai-samples/src/features/server-prompt-templates/index.tsx @@ -0,0 +1,149 @@ +import { useState } from 'react'; +import { generateFromTemplate } from './service'; + +export default function ServerPromptTemplatesView() { + const [templateId, setTemplateId] = useState('invoice-generator'); + const [customerName, setCustomerName] = useState('Jane Doe'); + + const [response, setResponse] = useState(''); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + // TODO: Add support for dynamic custom key-value variable pairs if developer wants to test other templates + + const handleExecute = async () => { + const trimmedId = templateId.trim(); + if (!trimmedId) { + setError('Please enter a Template ID.'); + return; + } + + const trimmedCustomerName = customerName.trim(); + if (!trimmedCustomerName) { + setError('Please enter a Customer Name.'); + return; + } + + setLoading(true); + setError(null); + setResponse(''); + + const templateVariables = { + customerName: trimmedCustomerName, + }; + + try { + const text = await generateFromTemplate(trimmedId, templateVariables); + setResponse(text); + } catch (err: unknown) { + const message = + err instanceof Error ? err.message : 'An error occurred while executing the template.'; + setError(message); + } finally { + setLoading(false); + } + }; + + const isNotFoundError = + error && (error.toLowerCase().includes('not found') || error.toLowerCase().includes('not_found')); + + return ( +
+

Server Prompt Templates

+

+ Centrally manage, test, and update AI prompts in the Firebase Console without redeploying client code. +

+ + {/* Prerequisite Setup Notice */} +
+ Console Prerequisite: Requires a published/locked template in the Firebase Console. + See README.md in this feature folder for the setup guide. +
+ +
+ + setTemplateId(e.target.value)} + placeholder="invoice-generator" + style={{ width: '100%', padding: '8px', boxSizing: 'border-box' }} + /> +
+ +
+ + setCustomerName(e.target.value)} + style={{ width: '100%', padding: '8px', boxSizing: 'border-box' }} + /> +
+ + + + {error && ( +
+ Error: {error} + {isNotFoundError && ( +
+ Setup Checklist: +
    +
  • Template {templateId} exists in your Firebase project?
  • +
  • Template status is Locked / Published (drafts cannot be called by client SDKs)?
  • +
  • Your web app configuration matches the Firebase project where the template is stored?
  • +
+
+ )} +
+ )} + + {response && ( +
+

Response:

+ {/* TODO: maybe add copy-to-clipboard/formatted markdown renderer */} +

{response}

+
+ )} +
+ ); +} diff --git a/ai/ai-samples/src/features/server-prompt-templates/service.ts b/ai/ai-samples/src/features/server-prompt-templates/service.ts new file mode 100644 index 000000000..004caecda --- /dev/null +++ b/ai/ai-samples/src/features/server-prompt-templates/service.ts @@ -0,0 +1,34 @@ +import { getAiTemplateModel } from '../../services/firebaseAIService'; + +export interface InvoiceTemplateVariables { + customerName: string; +} + +/** + * Executes a server-side prompt template in a single unary request. + * Centrally managed templates allow updating prompts and models without redeploying client code. + * + * NOTE: DC w/ Christina: Streaming and multi-turn chat are supported by the SDK (generateContentStream / startChat), + * but omitted here to keep this quickstart sample minimal and focused on variable injection. + * + * @param templateId The ID of the locked template in the Firebase Console (e.g. 'invoice-generator') + * @param variables Key-value map matching the {{variables}} declared in the template + * @returns The text string generated by the model + */ +export async function generateFromTemplate( + templateId: string, + variables: Record +): Promise { + try { + // TODO: confo if template versioning/alias options should be exposed here + const model = getAiTemplateModel(); + const result = await model.generateContent(templateId, variables); + return result.response.text(); + } catch (error: unknown) { + console.error('Error generating content from server template:', error); + // TODO: Consider maybe mapping specific SDK error codes if custom error handling is needed + throw error instanceof Error + ? error + : new Error('An unknown error occurred during template generation.'); + } +} diff --git a/ai/ai-samples/src/index.tsx b/ai/ai-samples/src/index.tsx index 7cffbd39e..c25e6fc5c 100644 --- a/ai/ai-samples/src/index.tsx +++ b/ai/ai-samples/src/index.tsx @@ -11,6 +11,7 @@ import ImageGeneration from './features/image-generation'; import AutomaticFunctionCalling from './features/automatic-function-calling'; import VideoAnalysis from './features/video-analysis'; import GroundingWithGoogleSearch from './features/grounding-with-google-search'; +import ServerPromptTemplates from './features/server-prompt-templates'; const router = createBrowserRouter([ { @@ -27,9 +28,14 @@ const router = createBrowserRouter([ { path: 'image-generation', element: }, { path: 'video-analysis', element: }, { path: 'grounding-with-google-search', element: }, + { path: 'server-prompt-templates', element: }, + { path: '*', element: }, ], }, - + { + path: '*', + element: , + }, ]); const isolatedFeature = import.meta.env.VITE_ISOLATED_FEATURE; @@ -51,10 +57,16 @@ const renderContent = () => { return ; case 'automatic-function-calling': return ; + case 'video-analysis': case 'video-anaylsis': return ; case 'grounding-with-google-search': + case 'grounding': return ; + case 'server-prompt-templates': + case 'server-prompt-template': + case 'template': + return ; default: return ; } From ce66714e9156550690d733f8b9dcff2a104be350 Mon Sep 17 00:00:00 2001 From: sedanah-m Date: Mon, 14 Sep 2026 14:22:58 -0400 Subject: [PATCH 02/11] clean up --- ai/ai-samples/README.md | 2 ++ ai/ai-samples/package.json | 3 ++- ai/ai-samples/src/App.tsx | 1 + .../src/features/server-prompt-templates/README.md | 14 ++++++-------- .../features/server-prompt-templates/service.ts | 6 ------ 5 files changed, 11 insertions(+), 15 deletions(-) diff --git a/ai/ai-samples/README.md b/ai/ai-samples/README.md index 5d8f9e8c8..19ab877ef 100644 --- a/ai/ai-samples/README.md +++ b/ai/ai-samples/README.md @@ -16,6 +16,7 @@ This repository demonstrates the following capabilities: * Image Generation * Video Analysis * Grounding with Google Search +* Server Prompt Templates ## Setup & Configuration @@ -51,6 +52,7 @@ npm run dev:auto-function # Automatic Function Calling npm run dev:image # Image Generation npm run dev:video # Video Analysis npm run dev:grounding # Grounding with Google Search +npm run dev:template # Server Prompt Templates ``` After running any of the above commands, open your browser to http://localhost:*** (provided in the console) diff --git a/ai/ai-samples/package.json b/ai/ai-samples/package.json index 5b19c3fa6..a64534329 100644 --- a/ai/ai-samples/package.json +++ b/ai/ai-samples/package.json @@ -13,7 +13,8 @@ "dev:auto-function": "VITE_ISOLATED_FEATURE=automatic-function-calling vite", "dev:image": "VITE_ISOLATED_FEATURE=image-generation vite", "dev:video": "VITE_ISOLATED_FEATURE=video-analysis vite", - "dev:grounding": "VITE_ISOLATED_FEATURE=grounding-with-google-search vite", + "dev:grounding": "VITE_ISOLATED_FEATURE=grounding-with-google-search vite", + "dev:template": "VITE_ISOLATED_FEATURE=server-prompt-templates vite", "build": "tsc -b && vite build", "lint": "eslint .", "preview": "vite preview" diff --git a/ai/ai-samples/src/App.tsx b/ai/ai-samples/src/App.tsx index 9161c259d..8922487c0 100644 --- a/ai/ai-samples/src/App.tsx +++ b/ai/ai-samples/src/App.tsx @@ -10,6 +10,7 @@ const NAV_ITEMS = [ { path: '/image-generation', label: 'Image Generation' }, { path: '/video-analysis', label: 'Video Analysis' }, { path: '/grounding-with-google-search', label: 'Grounding with Google Search' }, + { path: '/server-prompt-templates', label: 'Server Prompt Templates' }, ]; export default function App() { diff --git a/ai/ai-samples/src/features/server-prompt-templates/README.md b/ai/ai-samples/src/features/server-prompt-templates/README.md index a6e07f6bd..6119df40b 100644 --- a/ai/ai-samples/src/features/server-prompt-templates/README.md +++ b/ai/ai-samples/src/features/server-prompt-templates/README.md @@ -28,9 +28,8 @@ Before running this sample, create and lock the template in your Firebase projec Create an example customer invoice for a customer named {{customerName}}. ``` 5. Click **Save**. -6. **Important**: Click **Lock** (or **Publish**). Client SDKs can only execute locked/published templates. Unlocked templates remain in draft mode and will return `NOT_FOUND` to client applications. +6. **Important**: While client applications can execute both unlocked (draft) and locked templates during development, you should always **Lock** your template before deploying to production. Locking freezes the prompt configuration, ensuring that subsequent console edits do not accidentally change your production app's behavior. - --- @@ -65,14 +64,13 @@ const result = await model.generateContent('invoice-generator', { customerName: 'Jane Doe', }); console.log(result.response.text()); - -// TODO: Add example for model.startChat with templateId once template-grounded multi-turn chat is explored ``` --- ## 4. Troubleshooting & Failure Surfaces - -// make a table for template ID mismatch -// missing variable output -// AI Logic API enabling note \ No newline at end of file +| Issue | Cause | Resolution | +|---|---|---| +| `NOT_FOUND` / 404 | Template ID mismatch or template doesn't exist in the active Firebase project | Verify that the template ID in your code is exactly `invoice-generator` and that you are initialized in the correct Firebase Project | +| Missing Variable output | Variable names in client code don't match console | Ensure the keys passed to `templateVariables` match the `{{variable}}` placeholders in your prompt template. | +| `PERMISSION_DENIED` | Firebase AI Logic API not enabled or App Check blocked | Follow the Firebase AI Logic guided setup in the console and ensure your API key / App Check tokens are valid. | \ No newline at end of file diff --git a/ai/ai-samples/src/features/server-prompt-templates/service.ts b/ai/ai-samples/src/features/server-prompt-templates/service.ts index 004caecda..f75086c9d 100644 --- a/ai/ai-samples/src/features/server-prompt-templates/service.ts +++ b/ai/ai-samples/src/features/server-prompt-templates/service.ts @@ -8,9 +8,6 @@ export interface InvoiceTemplateVariables { * Executes a server-side prompt template in a single unary request. * Centrally managed templates allow updating prompts and models without redeploying client code. * - * NOTE: DC w/ Christina: Streaming and multi-turn chat are supported by the SDK (generateContentStream / startChat), - * but omitted here to keep this quickstart sample minimal and focused on variable injection. - * * @param templateId The ID of the locked template in the Firebase Console (e.g. 'invoice-generator') * @param variables Key-value map matching the {{variables}} declared in the template * @returns The text string generated by the model @@ -20,13 +17,10 @@ export async function generateFromTemplate( variables: Record ): Promise { try { - // TODO: confo if template versioning/alias options should be exposed here const model = getAiTemplateModel(); const result = await model.generateContent(templateId, variables); return result.response.text(); } catch (error: unknown) { - console.error('Error generating content from server template:', error); - // TODO: Consider maybe mapping specific SDK error codes if custom error handling is needed throw error instanceof Error ? error : new Error('An unknown error occurred during template generation.'); From a96a189ec5b0e0bfb101b59196ac8b952e0de0d5 Mon Sep 17 00:00:00 2001 From: sedanah-m Date: Mon, 14 Sep 2026 14:27:07 -0400 Subject: [PATCH 03/11] more clean up --- ai/ai-samples/src/features/server-prompt-templates/README.md | 4 ++-- ai/ai-samples/src/features/server-prompt-templates/index.tsx | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/ai/ai-samples/src/features/server-prompt-templates/README.md b/ai/ai-samples/src/features/server-prompt-templates/README.md index 6119df40b..9ab1d381d 100644 --- a/ai/ai-samples/src/features/server-prompt-templates/README.md +++ b/ai/ai-samples/src/features/server-prompt-templates/README.md @@ -51,7 +51,7 @@ Open your browser to the local URL (e.g., `http://localhost:XXXX/server-prompt-t ## 3. Using in Your Own Project -To use Server Prompt Templates in any JavaScript or TypeScript project, copy [`service.ts`](./service.ts): +To use Server Prompt Templates in your project: ```ts import { getAI, getTemplateGenerativeModel } from 'firebase/ai'; @@ -68,7 +68,7 @@ console.log(result.response.text()); --- -## 4. Troubleshooting & Failure Surfaces +## 4. Possile Troubleshooting & Failure Surfaces | Issue | Cause | Resolution | |---|---|---| | `NOT_FOUND` / 404 | Template ID mismatch or template doesn't exist in the active Firebase project | Verify that the template ID in your code is exactly `invoice-generator` and that you are initialized in the correct Firebase Project | diff --git a/ai/ai-samples/src/features/server-prompt-templates/index.tsx b/ai/ai-samples/src/features/server-prompt-templates/index.tsx index 1cb1f8e92..d955caed8 100644 --- a/ai/ai-samples/src/features/server-prompt-templates/index.tsx +++ b/ai/ai-samples/src/features/server-prompt-templates/index.tsx @@ -9,8 +9,6 @@ export default function ServerPromptTemplatesView() { const [loading, setLoading] = useState(false); const [error, setError] = useState(null); - // TODO: Add support for dynamic custom key-value variable pairs if developer wants to test other templates - const handleExecute = async () => { const trimmedId = templateId.trim(); if (!trimmedId) { @@ -140,7 +138,6 @@ export default function ServerPromptTemplatesView() { {response && (

Response:

- {/* TODO: maybe add copy-to-clipboard/formatted markdown renderer */}

{response}

)} From 2fb02e6f013301b47a1b7a850304ce089ad87e62 Mon Sep 17 00:00:00 2001 From: sedanah-m Date: Mon, 14 Sep 2026 14:29:55 -0400 Subject: [PATCH 04/11] cleanup --- .../src/features/server-prompt-templates/service.ts | 4 ++-- ai/ai-samples/src/index.tsx | 5 ----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/ai/ai-samples/src/features/server-prompt-templates/service.ts b/ai/ai-samples/src/features/server-prompt-templates/service.ts index f75086c9d..c8a8ebc3b 100644 --- a/ai/ai-samples/src/features/server-prompt-templates/service.ts +++ b/ai/ai-samples/src/features/server-prompt-templates/service.ts @@ -1,4 +1,4 @@ -import { getAiTemplateModel } from '../../services/firebaseAIService'; +import { getAiModel } from '../../services/firebaseAIService'; export interface InvoiceTemplateVariables { customerName: string; @@ -17,7 +17,7 @@ export async function generateFromTemplate( variables: Record ): Promise { try { - const model = getAiTemplateModel(); + const model = getAiModel(); const result = await model.generateContent(templateId, variables); return result.response.text(); } catch (error: unknown) { diff --git a/ai/ai-samples/src/index.tsx b/ai/ai-samples/src/index.tsx index c25e6fc5c..a4175158c 100644 --- a/ai/ai-samples/src/index.tsx +++ b/ai/ai-samples/src/index.tsx @@ -29,13 +29,8 @@ const router = createBrowserRouter([ { path: 'video-analysis', element: }, { path: 'grounding-with-google-search', element: }, { path: 'server-prompt-templates', element: }, - { path: '*', element: }, ], }, - { - path: '*', - element: , - }, ]); const isolatedFeature = import.meta.env.VITE_ISOLATED_FEATURE; From c006f02cf4b99a83f6d37978549bb342009ef8cd Mon Sep 17 00:00:00 2001 From: sedanah-m Date: Mon, 14 Sep 2026 14:32:37 -0400 Subject: [PATCH 05/11] renaming --- ai/ai-samples/src/index.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/ai/ai-samples/src/index.tsx b/ai/ai-samples/src/index.tsx index a4175158c..555a70a68 100644 --- a/ai/ai-samples/src/index.tsx +++ b/ai/ai-samples/src/index.tsx @@ -52,13 +52,10 @@ const renderContent = () => { return ; case 'automatic-function-calling': return ; - case 'video-analysis': case 'video-anaylsis': return ; case 'grounding-with-google-search': - case 'grounding': return ; - case 'server-prompt-templates': case 'server-prompt-template': case 'template': return ; From 0a3b122292a8522113f91f4f39e76369d53bf412 Mon Sep 17 00:00:00 2001 From: sedanah-m Date: Mon, 14 Sep 2026 14:34:21 -0400 Subject: [PATCH 06/11] fix typo --- ai/ai-samples/src/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ai/ai-samples/src/index.tsx b/ai/ai-samples/src/index.tsx index 555a70a68..040e45c96 100644 --- a/ai/ai-samples/src/index.tsx +++ b/ai/ai-samples/src/index.tsx @@ -56,7 +56,7 @@ const renderContent = () => { return ; case 'grounding-with-google-search': return ; - case 'server-prompt-template': + case 'server-prompt-templates': case 'template': return ; default: From 44a7e6b9d9b7ad4d4465037e3343d0d0188662da Mon Sep 17 00:00:00 2001 From: sedanah-m Date: Mon, 14 Sep 2026 15:04:16 -0400 Subject: [PATCH 07/11] fix typo --- .../src/features/server-prompt-templates/service.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ai/ai-samples/src/features/server-prompt-templates/service.ts b/ai/ai-samples/src/features/server-prompt-templates/service.ts index c8a8ebc3b..e43aca96c 100644 --- a/ai/ai-samples/src/features/server-prompt-templates/service.ts +++ b/ai/ai-samples/src/features/server-prompt-templates/service.ts @@ -1,5 +1,4 @@ -import { getAiModel } from '../../services/firebaseAIService'; - +import { getAiTemplateModel } from '../../services/firebaseAIService'; export interface InvoiceTemplateVariables { customerName: string; } @@ -17,7 +16,7 @@ export async function generateFromTemplate( variables: Record ): Promise { try { - const model = getAiModel(); + const model = getAiTemplateModel(); const result = await model.generateContent(templateId, variables); return result.response.text(); } catch (error: unknown) { From a414a653eff3d1bee117f32bcda9123b5a561f88 Mon Sep 17 00:00:00 2001 From: sedanah-m Date: Mon, 14 Sep 2026 15:21:35 -0400 Subject: [PATCH 08/11] refactor some descriptions and clean up typo --- .../src/features/server-prompt-templates/README.md | 8 ++++---- .../src/features/server-prompt-templates/index.tsx | 2 ++ .../src/features/server-prompt-templates/service.ts | 1 + 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ai/ai-samples/src/features/server-prompt-templates/README.md b/ai/ai-samples/src/features/server-prompt-templates/README.md index 9ab1d381d..dbb198c2d 100644 --- a/ai/ai-samples/src/features/server-prompt-templates/README.md +++ b/ai/ai-samples/src/features/server-prompt-templates/README.md @@ -30,7 +30,6 @@ Before running this sample, create and lock the template in your Firebase projec 5. Click **Save**. 6. **Important**: While client applications can execute both unlocked (draft) and locked templates during development, you should always **Lock** your template before deploying to production. Locking freezes the prompt configuration, ensuring that subsequent console edits do not accidentally change your production app's behavior. - --- ## 2. Running the Sample Locally @@ -45,7 +44,7 @@ Or run this feature directly in isolated mode: npm run dev:template ``` -Open your browser to the local URL (e.g., `http://localhost:XXXX/server-prompt-templates`). +Open your browser to the local URL (e.g., `http://localhost:***` provided in the console). --- @@ -68,9 +67,10 @@ console.log(result.response.text()); --- -## 4. Possile Troubleshooting & Failure Surfaces +## 4. Possible Troubleshooting & Failure Surfaces + | Issue | Cause | Resolution | |---|---|---| -| `NOT_FOUND` / 404 | Template ID mismatch or template doesn't exist in the active Firebase project | Verify that the template ID in your code is exactly `invoice-generator` and that you are initialized in the correct Firebase Project | +| `NOT_FOUND` / 404 | Template ID mismatch or template doesn't exist in the active Firebase project | Verify that the template ID in your code is exactly `invoice-generator` and that you are initialized in the correct Firebase Project | | Missing Variable output | Variable names in client code don't match console | Ensure the keys passed to `templateVariables` match the `{{variable}}` placeholders in your prompt template. | | `PERMISSION_DENIED` | Firebase AI Logic API not enabled or App Check blocked | Follow the Firebase AI Logic guided setup in the console and ensure your API key / App Check tokens are valid. | \ No newline at end of file diff --git a/ai/ai-samples/src/features/server-prompt-templates/index.tsx b/ai/ai-samples/src/features/server-prompt-templates/index.tsx index d955caed8..2b014ca0e 100644 --- a/ai/ai-samples/src/features/server-prompt-templates/index.tsx +++ b/ai/ai-samples/src/features/server-prompt-templates/index.tsx @@ -65,6 +65,7 @@ export default function ServerPromptTemplatesView() { }} > Console Prerequisite: Requires a published/locked template in the Firebase Console. + Console Prerequisite: Requires a saved template in the Firebase Console. See README.md in this feature folder for the setup guide. @@ -128,6 +129,7 @@ export default function ServerPromptTemplatesView() {
  • Template {templateId} exists in your Firebase project?
  • Template status is Locked / Published (drafts cannot be called by client SDKs)?
  • +
  • Template is saved in the Firebase Console (and locked for production)?
  • Your web app configuration matches the Firebase project where the template is stored?
diff --git a/ai/ai-samples/src/features/server-prompt-templates/service.ts b/ai/ai-samples/src/features/server-prompt-templates/service.ts index e43aca96c..9b25aae0d 100644 --- a/ai/ai-samples/src/features/server-prompt-templates/service.ts +++ b/ai/ai-samples/src/features/server-prompt-templates/service.ts @@ -1,4 +1,5 @@ import { getAiTemplateModel } from '../../services/firebaseAIService'; + export interface InvoiceTemplateVariables { customerName: string; } From 7f988f7815a3de1977fb3fcff028b05e7e972ccb Mon Sep 17 00:00:00 2001 From: sedanah-m Date: Mon, 14 Sep 2026 15:25:32 -0400 Subject: [PATCH 09/11] add get `AiTemplateModel` --- .../src/services/firebaseAIService.ts | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/ai/ai-samples/src/services/firebaseAIService.ts b/ai/ai-samples/src/services/firebaseAIService.ts index ec9ededeb..320a29bc2 100644 --- a/ai/ai-samples/src/services/firebaseAIService.ts +++ b/ai/ai-samples/src/services/firebaseAIService.ts @@ -1,17 +1,17 @@ -import { initializeApp} from 'firebase/app'; -import { getAI, getGenerativeModel } from 'firebase/ai'; +import { initializeApp } from 'firebase/app'; +import { getAI, getGenerativeModel, getTemplateGenerativeModel, RequestOptions } from 'firebase/ai'; import { initializeAppCheck, ReCaptchaEnterpriseProvider } from 'firebase/app-check'; -const firebaseConfig = import.meta.env.VITE_FIREBASE_CONFIG - ? JSON.parse(import.meta.env.VITE_FIREBASE_CONFIG) +const firebaseConfig = import.meta.env.VITE_FIREBASE_CONFIG + ? JSON.parse(import.meta.env.VITE_FIREBASE_CONFIG) : { - apiKey: "YOUR_API_KEY", + apiKey: "YOUR_API_KEY", authDomain: "YOUR_AUTH_DOMAIN", projectId: "YOUR_PROJECT_ID", storageBucket: "YOUR_STORAGE_BUCKET", messagingSenderId: "YOUR_MESSAGING_SENDER_ID", appId: "YOUR_APP_ID" - }; + }; const app = initializeApp(firebaseConfig); @@ -20,9 +20,9 @@ if (typeof window !== 'undefined') { (window as any).FIREBASE_APPCHECK_DEBUG_TOKEN = true; initializeAppCheck(app, { - // The string here doesn't matter in this specific case, as setting - // FIREBASE_APPCHECK_DEBUG_TOKEN above means it will be ignored. - // However, in production, this MUST be a valid reCAPTCHA site key. + // The string here doesn't matter in this specific case, as setting + // FIREBASE_APPCHECK_DEBUG_TOKEN above means it will be ignored. + // However, in production, this MUST be a valid reCAPTCHA site key. provider: new ReCaptchaEnterpriseProvider('YOUR_RECAPTCHA_SITE_KEY'), isTokenAutoRefreshEnabled: true }); @@ -32,4 +32,8 @@ const ai = getAI(app); export const getAiModel = (modelName: string = 'gemini-3.5-flash-lite', additionalConfig: Record = {}) => { return getGenerativeModel(ai, { model: modelName, ...additionalConfig }); +}; + +export const getAiTemplateModel = (requestOptions?: RequestOptions) => { + return getTemplateGenerativeModel(ai, requestOptions); }; \ No newline at end of file From 7d780135b44c2856caafaa7f5d351a4661ed1094 Mon Sep 17 00:00:00 2001 From: sedanah-m Date: Mon, 14 Sep 2026 15:26:59 -0400 Subject: [PATCH 10/11] format doc --- ai/ai-samples/src/services/firebaseAIService.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ai/ai-samples/src/services/firebaseAIService.ts b/ai/ai-samples/src/services/firebaseAIService.ts index 320a29bc2..72431f370 100644 --- a/ai/ai-samples/src/services/firebaseAIService.ts +++ b/ai/ai-samples/src/services/firebaseAIService.ts @@ -6,11 +6,11 @@ const firebaseConfig = import.meta.env.VITE_FIREBASE_CONFIG ? JSON.parse(import.meta.env.VITE_FIREBASE_CONFIG) : { apiKey: "YOUR_API_KEY", - authDomain: "YOUR_AUTH_DOMAIN", - projectId: "YOUR_PROJECT_ID", - storageBucket: "YOUR_STORAGE_BUCKET", - messagingSenderId: "YOUR_MESSAGING_SENDER_ID", - appId: "YOUR_APP_ID" + authDomain: "YOUR_AUTH_DOMAIN", + projectId: "YOUR_PROJECT_ID", + storageBucket: "YOUR_STORAGE_BUCKET", + messagingSenderId: "YOUR_MESSAGING_SENDER_ID", + appId: "YOUR_APP_ID" }; const app = initializeApp(firebaseConfig); From ecf9781ab12c77bc4b2ad1349d9f5fdf46eb392f Mon Sep 17 00:00:00 2001 From: sedanah-m Date: Mon, 14 Sep 2026 17:19:09 -0400 Subject: [PATCH 11/11] add a comment; remove unnecessary steps in readme. --- ai/ai-samples/README.md | 2 ++ .../server-prompt-templates/README.md | 21 +------------------ 2 files changed, 3 insertions(+), 20 deletions(-) diff --git a/ai/ai-samples/README.md b/ai/ai-samples/README.md index 19ab877ef..aa3c6f268 100644 --- a/ai/ai-samples/README.md +++ b/ai/ai-samples/README.md @@ -52,6 +52,8 @@ npm run dev:auto-function # Automatic Function Calling npm run dev:image # Image Generation npm run dev:video # Video Analysis npm run dev:grounding # Grounding with Google Search +# Note: Server Prompt Templates requires template setup in the Firebase Console first. +# See src/features/server-prompt-templates/README.md for setup instructions before running: npm run dev:template # Server Prompt Templates ``` diff --git a/ai/ai-samples/src/features/server-prompt-templates/README.md b/ai/ai-samples/src/features/server-prompt-templates/README.md index dbb198c2d..42eafc7dc 100644 --- a/ai/ai-samples/src/features/server-prompt-templates/README.md +++ b/ai/ai-samples/src/features/server-prompt-templates/README.md @@ -48,26 +48,7 @@ Open your browser to the local URL (e.g., `http://localhost:***` provided in the --- -## 3. Using in Your Own Project - -To use Server Prompt Templates in your project: - -```ts -import { getAI, getTemplateGenerativeModel } from 'firebase/ai'; -import { initializeApp } from 'firebase/app'; - -const app = initializeApp(firebaseConfig); -const ai = getAI(app); -const model = getTemplateGenerativeModel(ai); -const result = await model.generateContent('invoice-generator', { - customerName: 'Jane Doe', -}); -console.log(result.response.text()); -``` - ---- - -## 4. Possible Troubleshooting & Failure Surfaces +## 3. Possible Troubleshooting & Failure Surfaces | Issue | Cause | Resolution | |---|---|---|