Featurama

SDK setup

Set up React Native / Expo or the Flutter, Swift, Android and .NET MAUI source previews with your app's API key and API origin.

The SDK uses the app's API key (fm_live_…). An agent token (fm_dev_…) is only for the CLI or MCP and must never ship in an app. Create an app in Apps, in the setup or through the CLI first. Copy its key when created; existing keys cannot be retrieved later.

Availability and API origin

React Native / Expo is published on npm. Flutter, Swift, Android and .NET MAUI are source previews: they are not on a package registry yet, so you build them from a local checkout of the SDK. Use the matching repository: Flutter, Swift, Android or .NET MAUI. The paths below assume the checkout sits next to your app. Adjust them to your folder layout.

Every example must use the API origin that issued the project key. The hosted Preview is https://newapi.featurama.app; the legacy API remains https://api.featurama.app. Use a Preview-issued key with the Preview origin and a legacy-issued key with the explicit legacy origin. The SDK does not migrate keys or data, and does not automatically retry against the other origin. Changing a default or a URL does not transfer a project. The setup code in the dashboard already pairs a new key with the right origin.

For local development, the API may be http://localhost:3000. On a physical device, localhost is the device itself; use a reachable development host. An Android emulator normally reaches the host at http://10.0.2.2:3000. Native HTTP restrictions may require a development-only transport exception. Prefer HTTPS and do not disable transport security in production.

SDKPlatforms
FlutteriOS, Android and web.
SwiftSwiftUI on iOS 16+.
AndroidNative Jetpack Compose, API 21+. Not Kotlin Multiplatform.
.NET MAUIAndroid, iOS and Mac Catalyst on .NET 10. No Windows target.

React Native / Expo

Install the published package and its peer dependencies:

npm install @vibelabsdotto/featurama-rn-expo @react-native-async-storage/async-storage react-native-svg
# Expo only, for device-language detection:
npx expo install expo-localization

In Expo, supply the project key through your build configuration. EXPO_PUBLIC_ values are bundled into the app, so this is not a secret-storage mechanism. The API key is scoped to one app; do not use an agent token here.

import { FeaturamaProvider, FeatureRequestsScreen } from '@vibelabsdotto/featurama-rn-expo';

const apiKey = process.env.EXPO_PUBLIC_FEATURAMA_API_KEY;
if (!apiKey) throw new Error('Set EXPO_PUBLIC_FEATURAMA_API_KEY');

export default function Feedback() {
  return (
    <FeaturamaProvider config={{ apiKey, baseUrl: 'https://newapi.featurama.app' }}>
      <FeatureRequestsScreen colorScheme="light" accentColor="#6366f1" />
    </FeaturamaProvider>
  );
}

The URL above is for the new Preview. Set baseUrl to the API origin that issued this project's key. The RN SDK otherwise defaults to https://api.featurama.app. The API origin is not the dashboard URL and has no /mcp suffix. For bare React Native, supply the key from your own app configuration instead of Expo's environment mechanism.

Swift

Add the local featurama-swift checkout with Xcode's Add Local package option and link the FeaturamaSdk product to your app target. For a Swift package, add the local dependency to Package.swift:

dependencies: [
    .package(path: "../featurama-swift")
]

Configure once during app startup, and handle configuration errors. This example uses a placeholder, not a real key:

import Foundation
import FeaturamaSdk

try FeaturamaSdk.configure(
    apiKey: "[REDACTED]",
    baseURL: URL(string: "https://newapi.featurama.app")!
)

Supply a project key from the same instance. Pass baseURL explicitly rather than relying on defaults from a different release. Existing published Swift tags do not include uncommitted preview changes. Import SwiftUI and embed FeaturamaView(accentColor: .indigo) in a view after configuration.

Flutter

Reference the local package from your app's pubspec.yaml, then run flutter pub get:

dependencies:
  featurama:
    path: ../featurama-flutter

Create one client for the lifetime of the feedback route. Pass it to FeaturamaScreen and close it when the route is disposed:

import 'package:flutter/material.dart';
import 'package:featurama/featurama.dart';

class FeedbackPage extends StatefulWidget {
  const FeedbackPage({super.key});

  @override
  State<FeedbackPage> createState() => _FeedbackPageState();
}

class _FeedbackPageState extends State<FeedbackPage> {
  final _client = FeaturamaClient(
    apiKey: "fm_live_your_project_key",
    baseUrl: "https://newapi.featurama.app",
  );

  @override
  void dispose() {
    _client.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) => FeaturamaScreen(
    client: _client,
    accentColor: const Color(0xFF6366F1),
    brightness: Theme.of(context).brightness,
  );
}

Render FeedbackPage inside your existing MaterialApp or CupertinoApp. Do not create a new client on each widget rebuild. The current client accepts HTTPS origins and loopback HTTP only. For an Android emulator, use adb reverse tcp:3000 tcp:3000 with http://127.0.0.1:3000; plain HTTP to 10.0.2.2 or a LAN IP is rejected. Physical devices need a reachable HTTPS origin.

Android

Use a local Gradle composite build. In the host app's settings.gradle.kts:

includeBuild("../featurama-android") {
    dependencySubstitution {
        substitute(module("io.featurama:featurama-android"))
            .using(project(":featurama"))
    }
}

In app/build.gradle.kts:

android {
    compileOptions {
        isCoreLibraryDesugaringEnabled = true
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    kotlinOptions { jvmTarget = "1.8" }
    buildFeatures { compose = true }
    composeOptions { kotlinCompilerExtensionVersion = "1.5.10" }
}

dependencies {
    implementation("io.featurama:featurama-android")
    coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.4")
}

This dependency resolves to the local :featurama project, not to a claimed Maven release. Match the checkout's Gradle 8.5, Android Gradle Plugin 8.3.2 and Kotlin 1.9.22 toolchain. The SDK supports API 21 and requires core-library desugaring in the host app. The SDK manifest includes the internet permission. Keep your app's own dependencies, including activity-compose for the Activity example below.

Initialize before rendering FeaturamaScreen. This standalone Activity example can be adapted to your existing Activity or Application startup:

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.ui.graphics.Color
import io.featurama.sdk.Featurama
import io.featurama.sdk.ui.FeaturamaScreen

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Featurama.init("fm_live_your_project_key") {
            baseUrl("https://newapi.featurama.app")
        }
        setContent {
            FeaturamaScreen(accentColor = Color(0xFF6366F1))
        }
    }
}

.NET MAUI

Use .NET SDK and workload set 10.0.401 with MAUI Controls 10.0.110. Apple builds require Xcode 26.6 with the matching Apple workload 26.5.10318. The checkout's scripts/setup-toolchain.sh and scripts/dotnet-local.sh install and run its pinned toolchain without changing system-wide workloads.

Set your app's native targets to net10.0-android, net10.0-ios26.5 and net10.0-maccatalyst26.5 as needed. Add a source project reference and match the explicit Controls version inside your MAUI app's .csproj:

<ItemGroup>
  <ProjectReference Include="../featurama-maui/src/Featurama.Maui/Featurama.Maui.csproj" />
  <PackageReference Include="Microsoft.Maui.Controls" Version="10.0.110" />
</ItemGroup>

Update an existing Controls reference rather than adding a duplicate. Do not suppress package-downgrade or Xcode-version checks. The portable net10.0 target provides the HTTP client without MAUI UI. This is a source reference, not a dotnet add package instruction for a published NuGet release.

using Featurama.Maui.UI;
using Microsoft.Maui.Graphics;
using FeaturamaSdk = Featurama.Maui.Featurama;

public static class FeedbackSetup
{
    public static void Configure()
    {
        FeaturamaSdk.Init(options => options
            .ApiKey("fm_live_your_project_key")
            .BaseUrl("https://newapi.featurama.app"));
    }

    public static FeaturamaPage CreatePage() => new(new FeaturamaPageOptions
    {
        AccentColor = Color.FromArgb("#6366F1")
    });
}

Call FeedbackSetup.Configure() once during startup. Show the result of FeedbackSetup.CreatePage() through your app's existing navigation. See SDK UI for screen options.

Configuration and key rotation

OptionReact NativeSwiftPurpose
Project keyapiKeyapiKeyRequired project-scoped credential
API originbaseUrlbaseURLInstance that issued the key
TimeouttimeouttimeoutIntervalPer-request timeout
App metadataappVersion, appBuildappVersion, appBuildOptional overrides

The source previews use FeaturamaClient(apiKey: ..., baseUrl: ...) in Flutter, Featurama.init(key) { baseUrl(origin) } in Android, and Featurama.Init(options => options.ApiKey(key).BaseUrl(origin)) in MAUI. Each expects the origin only, without /api/public or /mcp. Their clients append the public API paths.

The dashboard only shows an existing key's prefix. Regenerating a project key invalidates the old one immediately. Update your app builds when rotating it; do not rotate a working key as a setup shortcut.

The RN SDK sends device metadata with submissions when available, including platform, OS, model, locale, and app version. It supports Expo Go and development builds. See the package README for optional native safe-area behavior.

On this page