Облачные функции
Облачная функция выполняет серверный код в ответ на событие или запрос — своего сервера для этого не нужно. Так обрабатывают данные, вызывают внешние API, рассылают уведомления, запускают работу с ИИ и, что важнее всего, держат ключи и бизнес-логику подальше от клиента.
FlutterFlow поддерживает и Firebase Cloud Functions, и Supabase Edge Functions.
Firebase Cloud Functions
Firebase Cloud Functions выполняют код на Node.js по событиям Firebase и HTTPS-запросам: отправить письмо, обработать загруженный файл, сгенерировать содержимое, среагировать на изменение в базе.
Создавать, править, разворачивать и вызывать их можно прямо из FlutterFlow.
Подборка сценариев применения — в документации Firebase.
Как добавить
Разберём на примере: функция генерирует логотип по текстовому описанию.
Функция берёт текст из виджета TextField, вызывает API генерации изображений и возвращает ссылку на картинку — её показывает виджет Image.
- Проект Firebase на тарифе Blaze.
- Пройдены все шаги подключения Firebase.
1. Переменные состояния страницы
Понадобятся две переменные состояния страницы:
- generatingImage (Boolean) — управляет показом индикатора загрузки: становится True перед вызовом и False после получения результата.
- logoImage (ImagePath) — сюда ложится ссылка на сгенерированную картинку.

2. Страница
Нужна страница с полем ввода. Быстрее всего взять шаблон или сгенерировать её; собрать с нуля — см. сборку раскладки.

Что здесь важно:
- Индикатор загрузки показывается через ConditionalBuilder по переменной generatingImage. В ветке Else лежит ProgressBar в контейнере с зацикленной анимацией вращения.
- Виджет Image берёт адрес из переменной logoImage.
3. Создание и развёртывание
- Откройте Cloud Functions в меню навигации слева.
- Нажмите + Add — добавится
newCloudFunction. - Задайте Cloud Function Name.
Настройки заготовки
Справа настраивается следующее:
-
Memory Allocation — сколько памяти отводится функции. Больше памяти — быстрее работа тяжёлых задач, но дороже каждый вызов.
-
Timeout (s) — сколько секунд функции разрешено работать до принудительной остановки. Оплата идёт за время выполнения, поэтому большой таймаут стоит ставить осознанно.
-
Require Authentication — вызывать функцию смогут только авторизованные пользователи.
-
Cloud Function Region — где физически выполняется функция. Значение должно совпадать с Default GCP resource location и с регионом в расширенных настройках Firebase.

Вход и выход
-
Чтобы функция что-то возвращала, включите Return Value и выберите тип. В примере это ImagePath — ссылка на сгенерированный логотип.
-
Чтобы передать данные, нажмите + Add parameters: задайте имя, тип, отметьте Is List для списка и снимите Nullable, если значение обязательно. В примере это параметр
promptтипа String. -
Собственные типы данных передаются в виде JSON: каждое поле типа — пара «ключ-значение». Для списка функция ждёт массив таких объектов. Скажем, для типа
Personс полямиNameиAge:
// JSON:
{ "Name": "John", "Age": 30 }
// Код функции:
return {
"name": person.name,
"age": person.age
};
Для списка:
// JSON
[ { "Name": "John", "Age": 30 }, { "Name": "Jane", "Age": 25 } ]
// Код функции:
return filteredpersons.map(filteredpersons => {
return {
"name": filteredpersons.name,
"age": filteredpersons.age
};
});
Развёртывание
-
Нажмите значок
[</>]— откроется заготовка кода, затем</> Copy to Editor. Полезно сначала развернуть пустую заготовку и убедиться, что развёртывание вообще проходит. -
Допишите в редакторе код функции.
-
Нажмите Save Cloud Function.
-
Нажмите Deploy.
Код из примера:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const https = require('https');
exports.logoMaker = functions.region('us-central1')
.runWith({
timeoutSeconds: 10,
memory: '512MB'
}).https.onCall((data, context) => {
return new Promise((resolve, reject) => {
const prompt = data.prompt;
if (!prompt) {
reject(new functions.https.HttpsError('invalid-argument', 'No prompt provided'));
return;
}
const postData = JSON.stringify({
model: "dall-e-3",
prompt: prompt,
n: 1,
size: "1024x1024"
});
const options = {
hostname: 'api.openai.com',
port: 443,
path: '/v1/images/generations',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer YOUR-APIKEY`,
'Content-Length': postData.length
}
};
const req = https.request(options, (res) => {
let responseBody = '';
res.on('data', (chunk) => {
responseBody += chunk;
});
res.on('end', () => {
try {
const responseJSON = JSON.parse(responseBody);
if (responseJSON.data && responseJSON.data.length > 0) {
// Берём ссылку на первое изображение
const firstImageUrl = responseJSON.data[0].url;
resolve(firstImageUrl);
} else {
reject(new functions.https.HttpsError('not-found', 'No images found'));
}
} catch (error) {
reject(new functions.https.HttpsError('internal', 'Error processing response', error));
}
});
});
req.on('error', (error) => {
reject(new functions.https.HttpsError('internal', 'Error generating image', error));
});
req.write(postData);
req.end();
});
});
После любой правки настроек заготовки или параметров пересоздайте заготовку кода — или поправьте свой код руками. Иначе сигнатура функции разойдётся с тем, что вызывает приложение.
Функции могут понадобиться сторонние библиотеки. Любой пакет npm подключается через файл package.json — в нём же лежат метаданные проекта, скрипты развёртывания и допустимые версии Node.js.
Впишите пакет в раздел dependencies.

4. Вызов функции
Созданная функция появляется в списке действий. В примере по нажатию кнопки сначала выставляется generatingImage = True, затем вызывается Cloud Function Action.
5. Использование результата
Чтобы работать с результатом, задайте при добавлении действия Action Output Variable Name — дальше значение доступно в Set from Variable > Action Outputs > [имя переменной].
В примере полученная ссылка на логотип записывается в переменную logoImage.
Проверка функции
Развёрнутую функцию можно вызвать прямо из консоли Google Cloud — не записывая ничего в Firestore и не запуская приложение.
Разберём на встроенной функции FlutterFlow sendUserPushNotificationsTrigger:
-
Откройте адрес:
https://console.cloud.google.com/functions/details/us-central1/sendUserPushNotificationsTrigger?env=gen1&project=<projectID>&tab=testing
Здесь:<projectID>замените на идентификатор своего проекта GCP или Firebase;- для другой функции замените
sendUserPushNotificationsTriggerна её имя.
-
Вставьте в поле Configure Triggering Event такой JSON:
{ "value": { "name": "projects/<projectID>/databases/(default)/documents/sendUserPushNotificationsTrigger/<documentID>", "fields": { "scheduled_time": { "stringValue": "" }, "initial_page_name": { "stringValue": "" }, "notification_title": { "stringValue": "Your friends are missing you!" }, "notification_text": { "stringValue": "Please come back to Nanochat" }, "user_refs": { "stringValue": "users/VXu6EvFMl5M8KMXriYRvFEWTFHA2" } } } } -
В свойстве
name:- замените
<projectID>на свой проект; - замените
<documentID>на идентификатор документа — документ должен уже существовать в Firestore; - для другой функции подставьте её коллекцию вместо
sendUserPushNotificationsTrigger.
- замените
-
Заполните
fieldsпод своё сообщение. Приведённый набор полей относится к встроенной функцииsendUserPushNotificationsTrigger; у вашей функции поля будут свои. -
Нажмите TEST THE FUNCTION.
Функция выполнится, а результат осядет в журналах Google Cloud Logging.
Частые вопросы
Почему развёртывание не проходит в только что созданном проекте?
Потому что в новом проекте Google Cloud ещё не включены нужные API и не выданы права.
- Откройте адрес:
https://console.cloud.google.com/functions/list?referrer=search&hl=en&project=<projectID>, подставив свой идентификатор проекта. - Нажмите Create Function — GCP предложит включить Cloud Build и Cloud Functions.
- После Next появится предложение включить Cloud Run Admin API.

- Дальше нужно выдать права служебному аккаунту сборки. На следующей странице разверните пример функции вроде
helloHttp— появится запрос:You need to grant the following roles to the build service account to deploy a function: roles/cloudbuild.builds.builder to <projectID>-compute@developer.gserviceaccount.com. - Нажмите Grant и разверните пример. После этого пример можно удалить.
Теперь функции из FlutterFlow будут разворачиваться нормально.
Ошибка CORS при вызове функции
В ответе не хватает заголовка **Access-Control-Allow-Origin**. Такое бывает с новыми функциями независимо от того, разворачивались они из FlutterFlow или нет.
Что делать:
- Откройте список функций своего проекта Google Cloud.
- Выберите нужную функцию.
- Перейдите на вкладку Permissions.
- Откройте VIEW BY ROLES.
- Убедитесь, что есть строка
Cloud Functions Invokerс принципаломallUsers. Если её нет, нажмите Grant Access и добавьтеallUsersс рольюCloud Functions Invoker.

Supabase Edge Functions
Supabase Edge Functions выполняют серверный код на Deno и TypeScript в инфраструктуре Supabase. Их берут для работы с ИИ, обёрток над внешними API, вебхуков, платежей и любой обработки на стороне сервера.
В отличие от функций Firebase, они тесно связаны с вашим проектом Supabase и выполняются ближе к пользователю.
Проект должен быть подключён к Supabase — см. настройку Supabase.
Как добавить
Разберём на примере: функция составляет краткую сводку по отзывам о товаре.
Она принимает список отзывов, отправляет их модели и возвращает JSON со сводкой и общей тональностью. Здесь же виден главный смысл таких функций: ключ доступа к API лежит на стороне Supabase, а не в приложении.
1. Создание и развёртывание
-
Откройте раздел Cloud Functions в меню навигации.
-
Нажмите + и выберите Supabase Edge Function.
-
Задайте имя — в примере это
getAIReviewsSummary. -
Настройте функцию. В примере она принимает список отзывов и возвращает JSON со сводкой и тональностью.
Что ещё настраивается:
- Verify JWT — проверять токен из заголовка запроса. Выключите, чтобы разрешить вызовы без авторизации.
- Enable CORS — добавлять заголовки CORS и обрабатывать предварительные запросы. Обязательно для вызова из веб-приложения.
- Return Value — тип возвращаемого значения.
- Define Parameters — параметры тела запроса.
-
Нажмите кнопку генерации кода и скопируйте заготовку в редактор. Дальше заготовку можно отдать ИИ-помощнику вместе с описанием задачи, а полученный код проверить — сверить логику и формат ответа.
-
Вставьте готовый код обратно в редактор.
-
Нажмите Save Edge Function.
-
Нажмите Deploy.
-
FlutterFlow покажет список функций, доступных для развёртывания.
-
Нажмите Deploy у нужной — она уйдёт в подключённый проект Supabase.
Внешние пакеты Deno, npm и JSR подключаются на вкладке Dependencies (deno.json).
Например, для пакета lodash:
{
"imports": {
"lodash": "npm:lodash@4.17.21"
}
}После этого в коде функции:
import _ from "lodash"
2. Хранение ключей
Ключи и токены нельзя прописывать в коде функции. Для них есть отдельное место — секреты Supabase: там они хранятся зашифрованными и не попадают ни в приложение, ни в репозиторий.
Откройте проект Supabase, перейдите в Edge Functions > Secrets, введите имя и значение и нажмите Save:
ANTHROPIC_KEY=your-api-key
В функции значение читается через Deno.env.get():
const apiKey = Deno.env.get("ANTHROPIC_KEY")
if (!apiKey) {
return new Response("Missing ANTHROPIC_KEY", {
status: 500,
headers: { ...corsHeaders, "Content-Type": "text/plain" },
})
}

3. Вызов и результат
Развёрнутая функция вызывается действием Edge Function — по нажатию кнопки, при загрузке страницы или откуда угодно ещё. Передайте ей нужные параметры, в примере это список отзывов.

Если функция возвращает значение, задайте Action Output Variable Name. Дальше результат доступен в Set from Variable > Action Outputs > [имя переменной].
В примере поля summary и sentiment из ответа записываются в переменные состояния и выводятся на экран.

