Custom Apps
Custom apps allow you to extend Flows with your own functionality by writing TypeScript/JavaScript code that implements the Flows app SDK. This guide covers how to create, develop, and deploy custom apps using flowctl, the official CLI tool for Flows app development.
Prerequisites
Section titled “Prerequisites”- Node.js 18 or later
- A Flows account with appropriate permissions
- Basic knowledge of TypeScript/JavaScript
Installing flowctl
Section titled “Installing flowctl”Install the flowctl CLI globally using npm:
npm install -g @useflows/flowctlVerify the installation:
flowctl --versionAuthentication
Section titled “Authentication”Before creating or managing apps, authenticate with Flows:
flowctl auth loginThis will open your browser to complete the authentication flow. Once authenticated, you can manage apps and versions.
To logout:
flowctl auth logoutCreating Your First App
Section titled “Creating Your First App”1. Create the app
Section titled “1. Create the app”Create a new app in Flows:
flowctl app createThis command will prompt you for:
- App name: Display name for your app
- Description: Brief description of what your app does
- Block color: Color theme for your app’s blocks (e.g.,
#3B82F6) - Icon URL: Optional URL to an icon for your app
- Project ID: Optional project to associate the app with (use
-pflag to specify)
The command creates the app and returns an app ID that you’ll use for version management.
2. Create the app code
Section titled “2. Create the app code”Create a TypeScript file (e.g., main.ts) that defines your app using the Flows SDK:
import { defineApp, events } from "@slflows/sdk/v1";
export default defineApp({ name: "Hello World App",
config: { message: { name: "Greeting Message", type: "string", required: true, default: "Hello, World!", }, },
blocks: { greeter: { name: "Greeter", description: "Emits a greeting message",
outputs: { default: { name: "Greeting", description: "The greeting message", type: "string", }, },
schedules: { greet: { description: "Send greeting every hour", definition: { type: "frequency", frequency: { interval: 1, unit: "hours", }, }, onTrigger: async (input) => { await events.emit({ message: input.app.config.message, timestamp: new Date().toISOString(), }); }, }, }, }, },});3. Create the first version
Section titled “3. Create the first version”Create an initial version of your app:
flowctl version create -e main.tsOptions:
-e, --entrypoint: Path to your app’s entry file (required)-a, --app: App ID (if not specified, will prompt or use the most recent)-v, --version: Version number (if not specified, will prompt for SemVer bump)--ui-entrypoint: Optional path to UI entry file for custom interfaces
The version is created in draft state, which means it’s not yet visible to users.
4. Develop with watch mode
Section titled “4. Develop with watch mode”During development, use watch mode to automatically update your draft version when files change:
flowctl version update -e main.ts --watchThis monitors your files and automatically uploads changes to the draft version, enabling rapid iteration.
5. Publish the version
Section titled “5. Publish the version”When your app is ready, publish the draft version to make it available:
flowctl version publishThis makes the version visible and installable in Flows.
App Structure
Section titled “App Structure”A Flows app consists of several key components:
App metadata
Section titled “App metadata”name: Display name shown in the UIinstallationInstructions: Markdown text shown during installationconfig: Configuration fields set during installationsignals: Values exposed by the app to blocks
Blocks
Section titled “Blocks”Blocks are the entities users place on the canvas. Each block can have:
- Inputs: Receive events from other blocks
- Outputs: Emit events to other blocks
- Config: Block-specific configuration fields
- Lifecycle:
onSyncandonDrainhandlers for state management - HTTP: Handle incoming HTTP requests
- Schedules: Periodic or cron-based triggers
- Timers: Handle one-time delayed execution
App-level handlers
Section titled “App-level handlers”onSync: Called when the app needs to synchronize (e.g., provision resources)onDrain: Called when the app is being removed (cleanup)onInternalMessage: Receive messages from blocksonTimer: Handle app-level timershttp.onRequest: Handle app-level HTTP requests
See the Building Apps section for comprehensive documentation on all app components and services.
Version Management
Section titled “Version Management”Semantic versioning
Section titled “Semantic versioning”Flows apps use semantic versioning (SemVer): MAJOR.MINOR.PATCH
- MAJOR: Breaking changes
- MINOR: New features, backwards compatible
- PATCH: Bug fixes, backwards compatible
Creating new versions
Section titled “Creating new versions”Create a new version with an explicit version number:
flowctl version create -e main.ts -v 1.2.0Or use interactive SemVer bump selection:
flowctl version create -e main.ts# Will prompt: major, minor, or patch?Listing versions
Section titled “Listing versions”View all versions of an app:
flowctl version list -a <app-id>Draft workflow
Section titled “Draft workflow”When you create a version, it starts as a draft:
- Create:
flowctl version create- Creates a draft version - Develop:
flowctl version update --watch- Iterate on the draft - Publish:
flowctl version publish- Make it available to users
Draft versions are only visible to developers and are not installable by users.
App Scoping
Section titled “App Scoping”Project-scoped apps
Section titled “Project-scoped apps”By default, apps are scoped to a specific project:
flowctl app create -p my-project-idProject-scoped apps are only visible within that project.
Organization-wide apps
Section titled “Organization-wide apps”To make an app available across your entire organization, create it without specifying a project, or contact your Flows administrator to promote an existing project-scoped app to organization-wide visibility.