Skip to main content

Overview

Arre uses Firebase Cloud Functions (2nd generation) for serverless backend operations. Functions handle AI processing, external API integrations, and operations that require server-side execution.

Available Functions

processMagicImport

Extracts actionable tasks from uploaded documents using Google Gemini AI.
This function is the core of the “Magic Import” feature, allowing users to upload PDFs, CSVs, or text files and automatically generate task lists.

Configuration

functions/index.js
exports.processMagicImport = onCall({ 
  secrets: [geminiApiKey],
  memory: "512MiB",
  timeoutSeconds: 60
}, async (request) => {
  // Function implementation
});
secrets
Secret[]
Requires GEMINI_API_KEY from Google Cloud Secret Manager.
memory
string
Allocated memory: 512MiB for processing large documents.
timeoutSeconds
number
Maximum execution time: 60 seconds.

Input Parameters

fileBase64
string
required
Base64-encoded file content. Supports PDF, CSV, and text files.
mimeType
string
required
File MIME type. Supported values:
  • application/pdf
  • text/csv
  • application/vnd.ms-excel
  • text/plain
instructions
string
Optional user instructions for task extraction. Example: “Focus on action items from the meeting notes”

Output Format

tasks
string[]
required
Array of extracted task titles. Maximum 10 tasks returned.
{
  "tasks": [
    "Review Q3 report",
    "Schedule team meeting",
    "Update project timeline"
  ]
}

Implementation Details

1

Authentication Check

Validates that the user is authenticated:
functions/index.js:57-59
if (!request.auth) {
  throw new HttpsError('unauthenticated', 'User must be logged in.');
}
2

Parse File Content

Extracts text based on MIME type:
functions/index.js:26-44
const parseFileContent = async (fileBase64, mimeType) => {
  const buffer = Buffer.from(fileBase64, 'base64');

  if (mimeType === 'application/pdf') {
    const data = await pdf(buffer);
    return data.text;
  } 
  
  if (mimeType === 'text/csv' || mimeType === 'application/vnd.ms-excel') {
    const records = parse(buffer.toString('utf-8'), {
      columns: true,
      skip_empty_lines: true
    });
    return JSON.stringify(records, null, 2);
  }

  // Fallback for text files
  return buffer.toString('utf-8');
};
3

AI Prompt Engineering

Constructs prompt for Gemini AI:
functions/index.js:72-83
const systemPrompt = `
  You are an expert productivity assistant for the "Arre" app.
  Your goal is to extract actionable tasks from the provided document content.
  
  Rules:
  1. Return ONLY a valid JSON array of strings. No markdown, no explanations.
  2. Each string must be a clear, actionable task title.
  3. If specific instructions are provided, prioritize them.
  4. Limit to the top 10 most important tasks if the document is large.
  
  User Instructions: ${instructions || "Extract all tasks."}
`;
4

Call Gemini API

Sends request to Google Gemini 2.5 Flash:
functions/index.js:86-92
const model = getGeminiModel(geminiApiKey.value());

const result = await model.generateContent([
  systemPrompt,
  { text: `Document Content:\n${extractedText.substring(0, 30000)}` }
]);

const response = result.response;
const text = response.text();
5

Parse and Validate Response

Cleans AI response and validates JSON:
functions/index.js:98-104
const jsonString = text.replace(/```json/g, '').replace(/```/g, '').trim();
const tasks = JSON.parse(jsonString);

if (!Array.isArray(tasks)) {
  throw new Error("AI did not return an array.");
}

return { tasks };

Error Handling

functions/index.js:108-111
try {
  // Function logic...
} catch (error) {
  console.error("Magic Import Error:", error);
  throw new HttpsError('internal', 'Details extraction failed.', error.message);
}
All errors are logged to Cloud Functions logs and returned as HttpsError with sanitized messages to avoid exposing sensitive information.

Usage Example

import { httpsCallable } from 'firebase/functions';
import { functions } from './firebase';

const processMagicImport = httpsCallable(functions, 'processMagicImport');

const fileInput = document.querySelector('input[type="file"]');
const file = fileInput.files[0];

// Convert file to base64
const reader = new FileReader();
reader.onload = async (e) => {
  const base64 = e.target.result.split(',')[1];
  
  const result = await processMagicImport({
    fileBase64: base64,
    mimeType: file.type,
    instructions: 'Extract urgent action items only'
  });
  
  console.log('Extracted tasks:', result.data.tasks);
};
reader.readAsDataURL(file);

generateBriefing

Generates AI-powered daily briefings based on user’s tasks and projects.

Configuration

functions/index.js:118-122
exports.generateBriefing = onCall({
  secrets: [geminiApiKey],
  memory: "512MiB",
  timeoutSeconds: 60
}, async (request) => { /* ... */ });

Input Parameters

tasks
Task[]
required
Array of user’s tasks with status, date, and project information.
projects
Project[]
Array of user’s projects for context.
localTime
string
User’s local time in ISO 8601 format for time-aware briefings.

Output Format

briefing
string
required
Markdown-formatted briefing with overview, today’s tasks, and upcoming priorities.
Good morning! You have 5 tasks on your plate today.

**Today's Focus:**
- Complete the Q3 report for your Work project
- Schedule team meeting
- Review code changes

**Tomorrow:**
Keep an eye on the project deadline approaching on Friday.

Google Tasks Integration

Three functions handle Google Tasks API integration:
Fetches available task lists for the authenticated user.
functions/index.js:207-224
exports.getGoogleTaskLists = onCall({
  secrets: [googleClientId, googleClientSecret],
  memory: "256MiB",
  timeoutSeconds: 30
}, async (request) => {
  const tasksService = await getGoogleTasksClient(request.auth.uid);
  const res = await tasksService.tasklists.list({ maxResults: 100 });
  return { lists: res.data.items || [] };
});

Secret Management

Defining Secrets

Secrets are defined at the top of functions/index.js:
functions/index.js:12-15
const { defineSecret } = require('firebase-functions/params');

const geminiApiKey = defineSecret('GEMINI_API_KEY');
const googleClientId = defineSecret('GOOGLE_CLIENT_ID');
const googleClientSecret = defineSecret('GOOGLE_CLIENT_SECRET');

Setting Secrets

Use Firebase CLI to set secrets in Google Cloud Secret Manager:
firebase functions:secrets:set GEMINI_API_KEY
firebase functions:secrets:set GOOGLE_CLIENT_ID
firebase functions:secrets:set GOOGLE_CLIENT_SECRET
Secrets are automatically injected into the function runtime when specified in the secrets parameter.

Accessing Secret Values

const apiKey = geminiApiKey.value();
Never log or expose secret values in responses. Always use try-catch blocks to prevent secret leakage through error messages.

Dependencies

Cloud Functions use the following npm packages:
functions/package.json
{
  "dependencies": {
    "firebase-admin": "^latest",
    "firebase-functions": "^latest",
    "@google/generative-ai": "^latest",
    "googleapis": "^latest",
    "pdf-parse": "^latest",
    "csv-parse": "^latest"
  }
}

Deployment

Deploy All Functions

firebase deploy --only functions

Deploy Specific Function

firebase deploy --only functions:processMagicImport

View Logs

firebase functions:log
Functions automatically scale based on traffic. Cold starts may add 1-2 seconds to first invocation.

Best Practices

1

Always Validate Input

Check authentication and validate all input parameters before processing:
if (!request.auth) {
  throw new HttpsError('unauthenticated', 'User must be logged in.');
}

if (!request.data.requiredField) {
  throw new HttpsError('invalid-argument', 'Missing required field.');
}
2

Use Structured Error Handling

Return HttpsError for client-friendly error messages:
try {
  // Function logic
} catch (error) {
  console.error('Function Error:', error);
  throw new HttpsError('internal', 'Operation failed.', error.message);
}
3

Set Appropriate Timeouts

AI operations need longer timeouts (60s), while API calls can use 30s.
4

Log for Debugging

Use console.log and console.error - logs appear in Cloud Functions dashboard.

Next Steps

Security Rules

Learn how functions interact with Firestore

Firebase Setup

Configure secrets and deployment

Build docs developers (and LLMs) love