AppForge Documentation
The complete self-hosted SaaS platform for converting websites into native iOS & Android apps.
Built with React, TypeScript, Express, Postgres, and Capacitor.
Quick Start — From Zero to Production
Follow these 5 phases in order. Each phase links to its detailed section.
Install & Configure
Clone repo → Install deps → Set up Postgres → Configure .env → Run migrations → Start dev server
Setup Wizard
Create admin account → Configure app name & branding → Set pricing plans → Launch
→ Wizard GuideConnect Services
Codemagic API token → Resend email → Payment gateways (Stripe/PayPal) → Storage
→ IntegrationsBuild Apps
Export to GitHub → Configure Codemagic → Build Android APK or iOS IPA → Download
→ Build PipelineDeploy to Production
Build for production → Configure Nginx/reverse proxy → SSL → Domain → Go live
→ DeploymentEach phase depends on the previous one. Don't skip ahead — e.g. Codemagic builds won't work without a GitHub export, and the setup wizard requires a running dev server with database migrations applied.
What is AppForge?
AppForge is a self-hosted platform that lets you convert any website into a native mobile app. It includes everything you need to run a SaaS business: user authentication, subscription billing, admin panel, credit system, and cloud build pipeline — all out of the box.
App Builder
4-step wizard: Enter URL → Configure → Preview → Build APK/IPA via Codemagic
Admin Panel
User management, analytics, payments, system settings, and more
Billing & Credits
Stripe, PayPal, Coinbase, bank transfers with subscription tiers
Workflow Roadmap
Follow these steps in order to go from a fresh download to a production-ready deployment:
Install & Configure Environment
Clone the repo, install dependencies, create a Postgres database, configure your .env file, apply database migrations, and start the dev server.
Run the Setup Wizard
On first launch, the 4-step setup wizard guides you through environment checks, admin account creation, and app configuration.
→ Setup Wizard GuideConfigure Admin Panel
Set up payment gateways, pricing plans, credit packs, email templates, integrations, and system settings from /admin.
Build Your First App
Navigate to the App Builder, enter a website URL, customize configuration, preview on device mockups, and generate your first APK/IPA.
→ First Build GuideDeploy to Production
Build for production, upload to your hosting (cPanel, VPS, or cloud), configure SSL, set up edge function secrets, and verify.
→ Deployment Guide · → Production ChecklistArchitecture Overview
AppForge is a client-side React application backed by a self-hosted Express + Postgres backend for auth, database, storage, and functions. Builds are compiled via Codemagic CI/CD.
Frontend (Client)
- React 18 — UI framework with TypeScript
- Vite — Build tool with code splitting
- Tailwind CSS + shadcn/ui — Styling & components
- Capacitor 8 — Native device API bridge
- TanStack Query — Server state management
- Zustand — Client state management
- Framer Motion — Animations
- React Router — Client-side routing
Backend (Express + Postgres)
- PostgreSQL — Database with RLS policies
- Better Auth — Email/password, Google OAuth, magic links
- Local file storage — File storage (builds, icons, avatars)
- Edge Functions — Deno serverless functions (auto-deployed)
- Realtime — Live database subscriptions
- Database Functions —
use_credits,add_credits,has_role,get_user_role
Features Overview
App Builder
4-step wizard that converts any website into a native mobile app:
Step 1: Enter URL
AI analyzes your site — extracts metadata, colors, favicon, and recommends features automatically.
Step 2: Configure
Set app name, colors, navigation style (tabs/drawer/bottom-nav), icon, splash screen, and toggle native features.
Step 3: Preview
Live device mockup preview with Appetize.io integration. Test on multiple device frames.
Step 4: Build & Download
Generate Android APK/AAB or iOS IPA via Codemagic cloud build. Real-time progress tracking.
Admin Panel
Full administration dashboard at /admin (requires admin role):
User Management
View, edit, assign roles (admin/moderator/user), manage credits.
Analytics
Build stats, revenue tracking, user growth, credit usage charts.
Build Monitoring
Real-time build status, error logs, queue management.
System Settings
App name, maintenance mode, demo mode, custom CSS, theme.
Payment Gateways
Configure Stripe, PayPal, Coinbase, bank transfers (sandbox/live).
Pricing Plans
Create/edit Free, Pro, Enterprise tiers with feature lists.
Credit Packs
Purchasable credit bundles with custom pricing.
Email Templates
Customize transactional emails (welcome, reset, build done).
Integrations
Resend, Appetize.io, AI providers, Codemagic CI/CD setup.
Credit & Subscription System
Credit-based billing model. Each build consumes credits (configurable).
| Setting | Default | Description |
|---|---|---|
| default_signup_credits | 5 | Free credits given to every new user on signup |
| credits_per_build | 1 | Credits consumed per app build |
Authentication & Roles
Better Auth with email/password, Google OAuth, and magic links. Role-based access control via user_roles table.
| Role | Access |
|---|---|
| admin | Full access — admin panel, user management, system settings, all CRUD |
| moderator | Limited admin — analytics, build management (no system settings) |
| user | Standard — app builder, own builds, subscription management, settings |
Dynamic Branding
The application name, tagline, logo, and colors are all configurable from Admin → System Settings. Changes propagate automatically to the navbar, auth pages, footer, help, and legal pages.
Demo Mode
Test environment with special behavior for demo accounts (admin@demo.com and user@demo.com).
VITE_DEMO_MODE env var takes priority over the database demo_mode system setting. If not set, database value is used.
Progressive Web App (PWA)
AppForge itself is a PWA with offline support and install prompts via vite-plugin-pwa.
- Auto-update service worker
- Precache static assets, runtime caching for fonts
- Install prompt via
usePWAInstallhook - Responsive manifest with 192px, 512px, and maskable icons
Technology Stack
React 18
UI Framework
Vite
Build Tool
Tailwind CSS
Styling
Capacitor 8
Native Bridge
TypeScript
Type Safety
PostgreSQL
Database
TanStack Query
Data Fetching
Zustand
State Mgmt
Getting Started
Complete step-by-step guide from fresh download to your first working app build.
Prerequisites
Required
- Node.js 18+ and npm (or bun) — install via nvm
- Git — to clone the repository
- PostgreSQL database — any managed or self-hosted Postgres instance
- Node.js 18+ — runs the Express backend and applies the schema via
npm run db:push - Modern browser — Chrome, Firefox, Safari, or Edge
For Cloud Builds
- Codemagic account — for Android/iOS cloud builds
- GitHub repository — connected to Codemagic for source code
- Google Play Developer account ($25 one-time fee) for Android publishing
- Apple Developer account ($99/year) for iOS publishing
Step 1: Clone & Install Dependencies
1 Clone the repository
git clone <YOUR_GIT_URL>
cd appforge
2 Install dependencies
npm install
# or: bun install
Step 2: Provision a PostgreSQL Database
1 Create a new project
Provision a PostgreSQL database (managed service or self-hosted) and note its connection details:
- Connection string — e.g.
postgres://user:pass@host:5432/postgres - Anon/Public Key — starts with
eyJ... - Project Reference ID — the
abcdefghpart of the URL - Service Role Key — for edge function secrets (keep this private!)
2 Enable Email Auth
In database admin → Authentication → Providers → Email: ensure email auth is enabled. Optionally enable Google OAuth.
3 Create Storage Buckets
In database admin → Storage, create these buckets:
| Bucket | Public | Purpose |
|---|---|---|
avatars | Yes | User profile pictures |
app-icons | Yes | Generated app icons |
splash-screens | Yes | Splash screen images |
apk-builds | Yes | APK/IPA build artifacts |
project-assets | No | Private project assets |
Step 3: Configure Environment Variables
1 Copy the environment template
cp .env.example .env
2 Fill in your environment variables
# Required — Your Postgres database URL
DATABASE_URL=postgres://user:password@host:5432/postgres
# Required — Better Auth secret (long random string)
BETTER_AUTH_SECRET=your-long-random-secret
# Required — Your Postgres database ID (the reference part of the URL)
BETTER_AUTH_URL=http://localhost:8080
.envOnly VITE_-prefixed variables are bundled into client JavaScript. Server-side keys (Stripe secret, Resend API key, etc.) must be configured as server environment variables in the .env file.
Step 4: Apply Database Migrations
The server/db/ directory contains the SQL schema (schema.sql + auth-schema.sql) for all tables, functions, and triggers.
1 Link your Postgres database
(set DATABASE_URL in your .env)
2 Push all migrations
npm run db:push
This creates all tables (profiles, user_roles, app_builds, subscription_plans, etc.), database functions (has_role, use_credits, add_credits, etc.), triggers, and RLS policies.
3 Deploy Edge Functions
npm run dev (backend functions run in the Express server)
Deploys all edge functions (stripe-checkout, paypal-checkout, send-email, analyze-website, ai-assistant, cloud-build, etc.).
4 Set Edge Function Secrets
In database admin → Settings → Secrets, add the keys your features need:
| Secret | When Needed |
|---|---|
STRIPE_SECRET_KEY | Stripe payments |
STRIPE_WEBHOOK_SECRET | Stripe webhooks |
RESEND_API_KEY | Transactional emails |
CODEMAGIC_API_TOKEN | Cloud builds via Codemagic |
CODEMAGIC_APP_ID | Codemagic app identifier |
Check the database admin → Table Editor to confirm all tables were created. You should see profiles, user_roles, app_builds, system_settings, and more.
Step 5: Start the Development Server
npm run dev
The app starts at http://localhost:8080. Since no admin exists yet, it automatically redirects to /setup.
Step 6: Complete the Setup Wizard
The streamlined 4-step setup wizard runs automatically on first launch when no admin account exists:
1 Welcome & Environment Check
Validates database connection, auth service, storage buckets, and system settings. Blocks progression on critical failures.
2 Super Admin Account
Create or sign in with the super admin account. Admin role is assigned automatically via RLS policy.
3 App Configuration
Set app name, tagline, support email, and default credits. Optionally seed demo data.
4 Launch
Success confirmation with link to launch the Admin Panel.
Email, security, and payment configuration are handled in the Admin Panel post-setup to keep the wizard fast and focused.
Step 7: Configure the Admin Panel
Log in and navigate to /admin to configure production settings:
A System Settings
Admin → System Settings: General (app name, tagline, maintenance mode), Appearance (theme, logo, custom CSS), Notifications, Builds (credits per build, max daily builds), and Storage.
B Payment Gateways
Admin → Payment Gateways. Configure one or more:
- Stripe — Publishable key, secret key, webhook secret. Toggle sandbox/live.
- PayPal — Client ID and secret. Create billing plans for subscriptions.
- Coinbase Commerce — API key and webhook secret for crypto payments.
- Bank Transfer — Manual transfers with admin approval workflow.
C Subscription Plans & Credit Packs
Admin → Pricing Plans: Create/edit Free, Pro, Enterprise tiers. Admin → Credit Packs: Create purchasable credit bundles.
D Integrations
Admin → Integrations. Configure third-party services:
- Resend — API key for transactional emails (welcome, password reset, build complete)
- Appetize.io — API key for interactive device previews
- AI Providers — OpenAI/Gemini keys for website analysis and AI assistant
- Codemagic — API token and app ID for cloud build pipeline
E Email Templates
Admin → Email Templates. Customize transactional emails with HTML and variable substitution.
Step 8: Build Your First App
1 Navigate to App Builder
Click "New App" from Dashboard or go to /builder.
2 Enter a Website URL
AI analyzes the page and extracts metadata (title, description, colors, favicon) automatically.
3 Customize Configuration
Configure app name, colors, navigation style, icon style, splash screen, and toggle native features.
4 Preview
Preview on device mockups. Interactive preview with Appetize.io if configured.
5 Build & Download
Select platform (Android APK or iOS IPA). Codemagic builds in the cloud; real-time progress in the Build Progress Panel. Download when complete.
Cloud builds require: Codemagic integration configured in Admin → Integrations, project exported to GitHub, and sufficient build credits.
API Reference
Hooks, functions, and services available in the codebase.
Native Hooks
React hooks wrapping Capacitor plugins. All have web fallbacks.
useCamera
Capture photos or pick from gallery.
import { useCamera } from '@/hooks/useCamera';
const { takePhoto, pickFromGallery, photo, isAvailable } = useCamera();
const result = await takePhoto(); // Returns base64 data
useBiometricAuth
Authenticate with fingerprint or Face ID.
import { useBiometricAuth } from '@/hooks/useBiometricAuth';
const { authenticate, isAvailable, biometryType } = useBiometricAuth();
const success = await authenticate('Verify your identity');
useHaptics
Trigger haptic feedback for tactile responses.
import { useHaptics } from '@/hooks/useHaptics';
const { impact, notification, vibrate } = useHaptics();
impact('light'); impact('medium'); impact('heavy');
notification('success'); notification('warning'); notification('error');
usePushNotifications
Register for push notifications (FCM/APNs).
import { usePushNotifications } from '@/hooks/usePushNotifications';
const { register, token, permission } = usePushNotifications();
const result = await register();
Application & Utility Hooks
React hooks for app-wide functionality, payments, and UI state.
usePWAInstall
Manages Progressive Web App install prompts and service worker registration.
import { usePWAInstall } from '@/hooks/usePWAInstall';
const { isInstallable, isInstalled, promptInstall } = usePWAInstall();
if (isInstallable) await promptInstall();
useAdminData & useAdminExists
Admin data fetching and admin existence detection for setup flow.
import { useAdminData } from '@/hooks/useAdminData';
import { useAdminExists } from '@/hooks/useAdminExists';
// Fetch admin panel data (users, builds, payments, settings)
const { data, loading, refresh } = useAdminData();
// Check if any admin account exists (for setup wizard routing)
const { adminExists, loading } = useAdminExists();
// Uses no_admin_exists() SECURITY DEFINER RPC for guest access
useSetupCheck
Validates system setup status. Redirects to /setup if no admin exists, or blocks setup if already configured.
import { useSetupCheck } from '@/hooks/useSetupCheck';
const { isSetupComplete, isChecking } = useSetupCheck();
// Used by PublicRoute and SetupRoute guards
useMobile & useToast
Responsive breakpoint detection and toast notification system.
import { useIsMobile } from '@/hooks/use-mobile';
import { useToast } from '@/hooks/use-toast';
const isMobile = useIsMobile(); // true when viewport < 768px
const { toast } = useToast();
toast({ title: 'Success', description: 'Operation completed' });
useBuildQueue
Manages build queue with concurrent limit enforcement and queue position tracking.
import { useBuildQueue } from '@/hooks/useBuildQueue';
const { queue, addToQueue, position, isProcessing } = useBuildQueue();
useBuilderKeyboardShortcuts
Keyboard shortcuts for the app builder. Navigation, refresh, screenshot, rotate, and comparison mode.
import { useBuilderKeyboardShortcuts } from '@/hooks/useBuilderKeyboardShortcuts';
useBuilderKeyboardShortcuts({
currentStep, onNextStep, onPrevStep,
onRefresh, onScreenshot, onRotate, onToggleComparison
});
useRealtime
Subscribes to backend polling channels for live database change events.
import { useRealtime } from '@/hooks/useRealtime';
useRealtime('app_builds', (payload) => {
console.log('Build updated:', payload);
});
usePayPalCheckout
Initiates PayPal checkout for subscriptions, credit packs, or invoices.
import { usePayPalCheckout } from '@/hooks/usePayPalCheckout';
const { initiatePayPalCheckout, loading } = usePayPalCheckout();
await initiatePayPalCheckout({ type: 'credits', creditPackId: '...' });
useCoinbaseCheckout
Initiates Coinbase Commerce crypto checkout. Redirects to hosted checkout page.
import { useCoinbaseCheckout } from '@/hooks/useCoinbaseCheckout';
const { initiateCoinbaseCheckout, loading } = useCoinbaseCheckout();
await initiateCoinbaseCheckout({ type: 'subscription', planId: '...' });
useSubscriptionPlans
Fetches active subscription plans with pricing and feature lists.
import { useSubscriptionPlans } from '@/hooks/useSubscriptionPlans';
const { plans, loading } = useSubscriptionPlans();
useBrowserNotifications & useNotificationSounds
Browser notification permission management and audio feedback for events.
import { useBrowserNotifications } from '@/hooks/useBrowserNotifications';
import { useNotificationSounds } from '@/hooks/useNotificationSounds';
const { requestPermission, sendNotification } = useBrowserNotifications();
const { playSound } = useNotificationSounds();
useStorage & useNavBadges
Storage quota tracking and navigation badge counts (unread notifications, pending builds).
import { useStorage } from '@/hooks/useStorage';
import { useNavBadges } from '@/hooks/useNavBadges';
const { usage, quota, percentUsed } = useStorage();
const { buildCount, notificationCount } = useNavBadges();
useDemoGuard & useAdminAuth
Demo mode mutation blocking and admin role verification hooks.
import { useDemoGuard } from '@/hooks/useDemoGuard';
import { useAdminAuth } from '@/hooks/useAdminAuth';
const { isDemoMode, guardAction } = useDemoGuard();
const { isAdmin, isLoading } = useAdminAuth();
useSystemSettings
Access global app settings (name, theme, maintenance mode, etc.) from the system_settings table. Cached globally.
import { useSystemSettings } from '@/hooks/useSystemSettings';
const { settings, loaded, refresh } = useSystemSettings();
// settings.app_name, settings.primary_color, settings.maintenance_mode, etc.
Edge Functions
Server-side functions in the Express backend. All support ?health=1 for health checking.
cloud-buildTriggers a Codemagic cloud build for Android APK or iOS IPA. Requires CODEMAGIC_API_TOKEN and CODEMAGIC_APP_ID.
cloud-build-statusChecks the status of a running Codemagic build. Returns progress, status, and artifact URLs.
send-emailSends transactional emails via Resend with HTML templates and variable substitution. Requires RESEND_API_KEY.
analyze-websiteFetches a URL and extracts metadata (title, description, colors, favicon, OG data). Uses AI for enhanced analysis.
ai-assistantAI chat assistant for app configuration guidance. Streams responses using OpenAI/Gemini.
stripe-checkout / stripe-webhook / stripe-portalStripe payments: checkout sessions, webhook processing, customer portal. Requires STRIPE_SECRET_KEY.
paypal-checkout / paypal-webhook / paypal-billingPayPal: orders, webhooks, billing plan management. Brand name pulled dynamically from system settings.
coinbase-checkout / coinbase-webhookCoinbase Commerce for cryptocurrency payments.
reset-demo-dataResets demo data (admin-only). Cleans and repopulates sample data for demo users.
appetize-uploadUploads APK/IPA to Appetize.io for interactive device preview. Requires APPETIZE_API_KEY.
storage-adminAdmin-only bucket management: list buckets with file counts/sizes, create new buckets.
test-storage-connectionValidates storage provider credentials (S3, GCS, R2) before saving configuration.
codemagic-webhookReceives Codemagic build completion webhooks. Updates build status and artifact URLs in database.
retry-webhookAdmin utility to re-trigger failed webhook events with original payload and X-Webhook-Retry header.
Edge Functions — Detailed Reference
Request/response formats, required secrets, and error codes for each function.
POST cloud-build
Triggers a Codemagic CI/CD build. Authenticates the user, validates credentials, waits for GitHub sync, then fires the build.
Request Body
{
"buildId": "uuid", // Required — app_builds record ID
"websiteUrl": "https://...", // Required — target site URL
"appName": "My App", // Required — display name
"platform": "android", // "android" | "ios" (default: "android")
"packageName": "com.app.my", // Optional — auto-sanitized if invalid
"config": { ... } // Optional — colors, features, workflowId
}
Response (200)
{ "success": true, "buildId": "uuid", "cloudBuildId": "cm-id", "message": "..." }
Errors
| Code | Reason |
|---|---|
| 400 | Missing required fields, or Codemagic token/app ID not configured |
| 401 | User not authenticated, or Codemagic token expired |
| 403 | Codemagic token has read-only scope (needs Owner or Builds) |
| 404 | Codemagic app or workflow not found |
Secrets: CODEMAGIC_API_TOKEN, CODEMAGIC_APP_ID
POST cloud-build-status
Polls Codemagic API for current build status. Maps Codemagic states to internal statuses. Extracts artifact URLs on completion.
Request Body
{ "buildId": "uuid" } // app_builds record ID
Response (200)
{
"id": "uuid", "status": "building", "progress": 45,
"download_url": null, "error_message": null,
"file_size_bytes": null, ...
}
On completion, download_url contains the artifact link. On failure, error_message includes step-level diagnostics.
POST codemagic-webhook
Receives POST callbacks from Codemagic with build status updates. No auth required — Codemagic sends directly.
Payload (from Codemagic)
{
"build": {
"_id": "cm-build-id", "status": "finished",
"artefacts": [{ "type": "apk", "url": "https://...", "size": 12345678 }],
"steps": [{ "name": "Build", "status": "success" }]
}
}
Automatically updates app_builds with status, progress, download URL, and failure diagnostics.
POST analyze-website
Uses AI (Gemini → OpenAI fallback chain) to analyze a URL and suggest app configuration.
Request / Response
// Request
{ "websiteUrl": "https://example.com" }
// Response (200)
{ "config": {
"app_name": "Example", "primary_color": "#3B82F6",
"accent_color": "#8B5CF6", "navigation_style": "bottom-nav",
"features": ["offline_mode", "push_notifications"],
"app_category": "utility", "icon_style": "modern",
"splash_screen_style": "centered-logo"
}}
AI provider priority: 1) AI Gateway (AI_API_KEY), 2) Admin-configured keys (api_configurations), 3) GEMINI_API_KEY env secret.
POST ai-assistant
Streaming AI chat assistant for app builder guidance. Returns Server-Sent Events (SSE).
Request Body
{
"message": "What navigation style works best for e-commerce?",
"currentStep": 2,
"config": { "appName": "ShopApp", "websiteUrl": "..." },
"conversationHistory": [{ "role": "user", "content": "..." }],
"aiProvider": "gemini" // optional: "openai" | "gemini"
}
Response: text/event-stream with OpenAI-compatible SSE chunks. Same AI fallback chain as analyze-website.
POST send-email
Sends transactional emails via Resend. Loads templates from email_templates table with {{variable}} substitution.
Request / Health Check
// Send email
{ "to": "user@example.com", "templateName": "welcome", "variables": { "app_name": "MyApp", "user_name": "John" } }
// Health check
GET /functions/v1/send-email?health=1
// → { "status": "ok", "env": { "RESEND_API_KEY": true, ... } }
Config priority: 1) RESEND_API_KEY env, 2) api_configurations table, 3) Legacy system_settings.
GETPOST storage-admin
Admin-only bucket management. Requires admin role verification.
// List buckets with stats
GET /functions/v1/storage-admin?action=list
// → [{ "name": "avatars", "public": true, "fileCount": 12, "totalSize": 4567890 }]
// Create bucket
POST /functions/v1/storage-admin?action=create
{ "name": "my-bucket", "isPublic": true, "fileSizeLimit": 10485760 }
POST test-storage-connection
Validates storage provider credentials. Admin-only. Supports: local, s3, gcs, cloudflare_r2.
// Test AWS S3
{ "provider": "s3", "config": { "s3_access_key": "AKIA...", "s3_secret_key": "...", "s3_bucket": "my-bucket", "s3_region": "us-east-1" } }
// → { "success": true, "message": "Configuration validated for bucket..." }
POST appetize-upload
Uploads APK/IPA to Appetize.io for interactive previews. Supports configurable retry (up to 10 attempts) and per-request timeout.
// Request
{ "buildId": "uuid", "downloadUrl": "https://...apk", "platform": "android" }
// Response (200)
{ "success": true, "publicKey": "abc123", "previewUrl": "https://appetize.io/app/abc123" }
Reads APPETIZE_API_KEY from api_configurations. Updates app_builds.config with the preview URL.
POST reset-demo-data
Admin-only. Resets all data for admin@demo.com and user@demo.com: deletes projects, builds, automations, chat messages, and templates. Resets credits (50 monthly + 10 bonus) and re-seeds sample projects.
POST retry-webhook
Admin-only. Re-sends a failed webhook event to the original gateway handler with the X-Webhook-Retry: true header. Logs the retry attempt in webhook_event_logs.
{ "webhook_log_id": "uuid" }
// → { "success": true, "response_status": 200, "processing_time_ms": 234 }
Gateway mapping: stripe→stripe-webhook, paypal→paypal-webhook, coinbase→coinbase-webhook.
POST stripe-checkout
Creates a Stripe Checkout session for subscriptions or credit pack purchases. Auto-creates/retrieves a Stripe customer.
Request Body
{
"type": "subscription" | "credits", // Required — purchase type
"itemId": "uuid", // plan_id or credit_pack_id
"billingCycle": "monthly" | "yearly",// For subscriptions only
"successUrl": "https://...", // Redirect after success
"cancelUrl": "https://..." // Redirect on cancel
}
Response (200)
{ "url": "https://checkout.stripe.com/c/pay/..." }
Errors
| Code | Reason |
|---|---|
| 400 | Invalid type, missing itemId, or plan/pack not found |
| 401 | Not authenticated |
| 500 | STRIPE_SECRET_KEY not configured |
Secrets: STRIPE_SECRET_KEY
POST stripe-portal
Creates a Stripe Billing Portal session for self-service subscription management (upgrades, downgrades, cancellations, payment method updates).
Request / Response
// Request
{ "returnUrl": "https://your-app.com/subscription" }
// Response (200)
{ "url": "https://billing.stripe.com/p/session/..." }
Requires user to have an existing stripe_customer_id in their profile. Returns 400 if no customer found.
POST stripe-webhook
Processes Stripe webhook events. Validates signatures, handles payment completions, subscription lifecycle, and credit allocation.
Handled Events
| Event | Action |
|---|---|
checkout.session.completed | Creates subscription record or adds credits depending on session metadata |
customer.subscription.updated | Updates subscription status, plan, and billing cycle |
customer.subscription.deleted | Marks subscription as canceled |
invoice.payment_succeeded | Records payment transaction, resets monthly credits on renewal |
invoice.payment_failed | Records failed payment, updates subscription status |
Secrets: STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET. Logs all events to webhook_event_logs.
POST paypal-checkout
Creates PayPal orders for credit pack purchases, subscription signups, and invoice payments. Supports sandbox and live modes via payment_gateway_configs.
Request Body
{
"type": "subscription" | "credits" | "invoice",
"plan_id": "uuid", // For subscriptions
"billing_cycle": "monthly", // "monthly" | "yearly"
"credit_pack_id": "uuid", // For credit purchases
"invoice_id": "uuid", // For invoice payments
"success_url": "https://...",
"cancel_url": "https://..."
}
Response (200)
{ "orderId": "PAY-...", "approvalUrl": "https://paypal.com/checkoutnow?token=..." }
Reads credentials from payment_gateway_configs (gateway = "paypal"). Brand name from system_settings.
POST paypal-billing
Manages PayPal billing plans and products. Creates products, plans with pricing intervals, and subscription links.
Actions
// Create a billing plan
{ "action": "create_plan", "plan_id": "uuid", "billing_cycle": "monthly" }
// Create a subscription
{ "action": "create_subscription", "plan_id": "uuid", "billing_cycle": "monthly",
"success_url": "...", "cancel_url": "..." }
// → { "subscriptionId": "I-...", "approvalUrl": "https://..." }
POST paypal-webhook
Processes PayPal webhook notifications. Handles payment captures, subscription activations, and cancellations.
Handled Events
PAYMENT.CAPTURE.COMPLETED— Adds credits or activates subscriptionBILLING.SUBSCRIPTION.ACTIVATED— Creates subscription recordBILLING.SUBSCRIPTION.CANCELLED— Marks subscription as canceledBILLING.SUBSCRIPTION.SUSPENDED— Suspends subscription
All events logged to webhook_event_logs with processing time.
POST coinbase-checkout
Creates Coinbase Commerce charges for cryptocurrency payments. Supports credit packs, subscriptions, and invoice payments.
Request / Response
// Request (same structure as paypal-checkout)
{ "type": "credits", "credit_pack_id": "uuid", "success_url": "...", "cancel_url": "..." }
// Response (200)
{ "chargeId": "...", "hostedUrl": "https://commerce.coinbase.com/charges/..." }
Reads API key from payment_gateway_configs (gateway = "coinbase").
POST coinbase-webhook
Processes Coinbase Commerce webhook events for charge completions and failures.
Handled Events
charge:completed— Adds credits or activates subscription based on charge metadatacharge:failed— Records failed payment transactioncharge:pending— Updates transaction status to pending
Validates webhook signature using webhook_secret from gateway config. Logs to webhook_event_logs.
Credits System
Credits via database RPCs. Users have monthly credits (reset on cycle) and bonus credits (permanent).
| Function | Parameters | Description |
|---|---|---|
use_credits | p_user_id, p_amount, p_action_type, p_description | Deducts credits (bonus first, then monthly). Returns false if insufficient. |
add_credits | p_user_id, p_amount, p_credit_type, p_action_type, p_description | Adds credits. p_credit_type: 'monthly' or 'bonus'. |
Frontend Hooks
useCredits()— Returns{ credits, totalCredits, useCredits, isLoading }useCreditHistory()— Paginated credit usage historyuseCreditPacks()— Available credit pack productsuseLowCreditsWarning()— Toast when credits drop below threshold
Admin API
Admin operations guarded by RLS policies requiring admin role.
Role Verification (Database Functions)
-- Check a user's role
SELECT get_user_role('user-uuid'); -- Returns 'admin', 'moderator', or 'user'
-- Check if user has specific role
SELECT has_role('user-uuid', 'admin'); -- Returns boolean
-- Check if any admin exists (used by setup wizard)
SELECT no_admin_exists(); -- Returns boolean
Admin-Only Tables
| Table | Admin Can | Description |
|---|---|---|
system_settings | Read/Write | App-wide configuration (name, theme, maintenance mode) |
email_templates | CRUD | HTML email templates with variable substitution |
subscription_plans | CRUD | Plan definitions and pricing tiers |
credit_packs | CRUD | Credit bundle products |
payment_gateway_configs | CRUD | Payment provider credentials (encrypted) |
user_roles | CRUD | Role assignments |
plugins | CRUD | Feature plugin registry |
api_configurations | CRUD | Integration API keys |
settings_audit_log | Read | Change tracking for all settings |
Authentication Context
Auth via src/contexts/AuthContext.tsx. Supports email/password, Google OAuth, and magic links.
import { useAuth } from '@/contexts/AuthContext';
const { user, session, signUp, signIn, signInWithGoogle, signInWithMagicLink, signOut, loading } = useAuth();
await signUp(email, password, displayName);
await signIn(email, password, rememberMe);
await signOut();
Route Protection
ProtectedRoute— Requires auth. Redirects to/auth. Also checks setup status.PublicRoute— Accessible by all. Redirects to/setupif no admin exists.SetupRoute— Only whenno_admin_exists()is true. Blocks re-entry after setup.
Native Features
Access powerful device capabilities through Capacitor plugins and web APIs.
Capacitor Overview
AppForge uses Capacitor 8 to bridge web code with native device APIs. Features toggled in the builder are included in the generated native project.
iOS
Swift/Obj-C bridge
Android
Java/Kotlin bridge
Web / PWA
Graceful fallback
📷 Camera
Photo capture, gallery picker, front/rear camera, base64 output.
🔐 Biometrics
Touch ID / Face ID / Fingerprint with passcode fallback.
📳 Haptics
Impact (light/medium/heavy), notification (success/warning/error), custom vibration.
🔔 Push Notifications
FCM (Android) / APNs (iOS). Rich notifications, deep linking, token management.
📍 Geolocation
Current position, continuous tracking, background updates.
📁 File System
Read/write files, directory management, sharing via native share sheet.
AdMob Advertising
Monetize apps with Google AdMob. Configured via Admin → System Settings.
| Type | Setting Key | Description |
|---|---|---|
| Banner | admob_banner_id | Rectangular ad at top/bottom |
| Interstitial | admob_interstitial_id | Full-screen ad between transitions |
| Rewarded | admob_rewarded_id | User watches ad for reward |
Database Schema
Complete list of database tables with RLS enabled on all:
| Table | Description | Key Columns |
|---|---|---|
profiles | User profiles (synced from auth.users) | id, email, display_name, avatar_url |
user_roles | Role assignments | user_id, role (admin/moderator/user) |
user_credits | Credit balances | user_id, monthly_credits, bonus_credits |
credit_usage_history | Credit transaction log | user_id, amount, action_type, description |
app_projects | App project configurations | user_id, website_url, app_name, features |
app_builds | Build records and artifacts | user_id, status, download_url, cloud_build_id |
app_templates | Saved project templates | user_id, name, config (JSON) |
chat_messages | AI assistant chat history | user_id, project_id, role, content |
automation_configs | Automation workflow definitions | project_id, workflow_type, is_enabled, config |
automation_logs | Automation execution history | automation_id, status, started_at, completed_at |
subscription_plans | Plan tier definitions | tier, price_monthly, monthly_credits |
user_subscriptions | Active user subscriptions | user_id, plan_id, status, billing_cycle |
payment_transactions | Payment history | user_id, amount, payment_method, status |
bank_transfer_requests | Manual bank transfer requests | user_id, amount, status, proof_of_payment_url |
invoices | User invoices | user_id, invoice_number, amount, status, items |
webhook_event_logs | Payment webhook event log | gateway, event_type, status, processing_time_ms |
consent_records | GDPR cookie consent records | user_id, consent_type, consented, ip_address |
system_settings | App-wide configuration | key, value, category |
payment_gateway_configs | Payment provider credentials | gateway, sandbox_config, live_config |
api_configurations | Integration API keys | provider, config, is_active |
credit_packs | Purchasable credit bundles | credits, price, is_active |
email_templates | Email HTML templates | name, subject, html_content |
plugins | Feature plugin registry | slug, type, is_active, version |
settings_audit_log | Settings change history | setting_key, old_value, new_value |
Environment Variables Reference
| Variable | Required | Description |
|---|---|---|
VITE_API_URL | Yes | Your Postgres database URL |
DATABASE_URL | Yes | Postgres connection string |
BETTER_AUTH_SECRET | Yes | Secret used to sign auth sessions |
VITE_DEMO_MODE | No | Enable demo mode (true/false) |
Edge Function Secrets (database admin)
| Secret | Used By |
|---|---|
STRIPE_SECRET_KEY | stripe-checkout, stripe-webhook, stripe-portal |
STRIPE_WEBHOOK_SECRET | stripe-webhook |
RESEND_API_KEY | send-email |
CODEMAGIC_API_TOKEN | cloud-build, cloud-build-status |
CODEMAGIC_APP_ID | cloud-build |
PUBLIC_SITE_URL | stripe-webhook (for email links) |
Codemagic Build Pipeline
Cloud-based CI/CD for compiling native Android APKs and iOS IPAs from your web application.
Build Architecture
AppForge converts websites into native apps by wrapping the target URL in a Capacitor WebView shell. The build pipeline works as follows:
1. Configuration Generation
The edge function (cloud-build) dynamically generates capacitor.config.ts, package.json, and platform-specific configs based on the user's builder selections.
2. Codemagic CI/CD
Codemagic pulls from the main branch, installs dependencies, adds the native platform, and compiles the binary on Mac Mini M2 instances.
3. Artifact Output
Android: APK (direct install) or AAB (Play Store). iOS: unsigned IPA for TestFlight distribution. Artifacts uploaded to Local file storage.
4. Real-Time Progress
The cloud-build-status edge function polls Codemagic for build status. The UI shows live progress with step-by-step updates.
The cloud-build edge function is hardcoded to trigger builds from the main branch. This ensures the pipeline always uses the latest configuration and sanitization logic synced from your development environment to GitHub.
Prerequisites
Required Accounts
- Codemagic account — Sign up at codemagic.io
- GitHub repository — Your AppForge project must be pushed to GitHub
- Codemagic API Token — Settings → Integrations → API tokens (requires Owner or Builds permission)
For App Store Publishing
- Google Play Developer — $25 one-time fee for Android publishing
- Apple Developer Program — $99/year for iOS App Store publishing
- Code signing certificates (Android keystore / iOS provisioning profile)
API Token Permissions
Codemagic API tokens require specific permission scopes. Restricted scopes return 403 Forbidden errors.
| Permission | Required | Purpose |
|---|---|---|
Owner | ✓ Recommended | Full access to trigger builds, read status, manage apps |
Builds | ✓ Minimum | Trigger new builds and read build status |
Read-only | ✗ Insufficient | Cannot trigger builds — will return 403 |
The cloud-build edge function prioritizes environment-level secrets (CODEMAGIC_API_TOKEN, CODEMAGIC_APP_ID) over values stored in the api_configurations database table. This prevents stale or swapped credentials from causing build failures.
codemagic.yaml Configuration
The codemagic.yaml file in the project root defines build pipelines. Runs on Mac Mini M2 instances.
Key Properties
| Property | Value | Description |
|---|---|---|
instance_type | mac_mini_m2 | Apple Silicon build machines |
max_build_duration | 30 min | Build timeout |
node | 18.x+ | Node.js for npm install |
java | 17 | JDK for Android Gradle |
xcode | latest | Xcode for iOS builds |
cocoapods | default | CocoaPods for iOS dependencies |
Pipeline Structure
# codemagic.yaml — simplified structure
workflows:
android-build:
name: Android Build
instance_type: mac_mini_m2
scripts:
- npm install
- npx cap add android
- npx cap sync android
- cd android && ./gradlew assembleDebug
artifacts:
- android/app/build/outputs/**/*.apk
ios-build:
name: iOS Build
scripts:
- npm install
- npx cap add ios --packagemanager Cocoapods
- npx cap sync ios
- xcodebuild build ...
artifacts:
- build/ios/ipa/*.ipa
Android Build Pipeline
Generates APK files for direct installation or AAB bundles for Google Play Store.
Build Steps
- Install dependencies —
npm install - Generate config — Dynamically creates
capacitor.config.tswith target URL, app name, package ID - Validate appId — Ensures Java-style package name (e.g.,
com.example.myapp) - Add Android —
npx cap add android - Sync assets —
npx cap sync android - Gradle build —
cd android && ./gradlew assembleDebug - Collect artifacts — APK from
android/app/build/outputs/
Output Formats
| Format | Extension | Use Case |
|---|---|---|
| Debug APK | .apk | Direct installation, testing |
| Release APK | .apk | Signed production builds |
| App Bundle | .aab | Google Play Store (required for new apps) |
iOS Build Pipeline
Generates unsigned IPA files for testing. Code signing handled separately for App Store distribution.
The iOS pipeline explicitly forces CocoaPods (--packagemanager Cocoapods) during platform addition. This resolves incompatibilities between certain plugins (e.g., @aparajita/capacitor-biometric-auth) and Capacitor 8's default Swift Package Manager (SPM) mode.
Build Steps
- Install dependencies —
npm install - Add iOS with CocoaPods —
npx cap add ios --packagemanager Cocoapods - Install pods —
cd ios/App && pod install - Sync assets —
npx cap sync ios - Xcode build —
xcodebuildwith archive → export - Collect artifacts — Unsigned IPA from build output
The default pipeline generates unsigned IPAs. To distribute via App Store or TestFlight, add your provisioning profile and signing certificate to the Codemagic workflow.
Build Troubleshooting
403 Forbidden on Build Trigger
API token has insufficient permissions. Generate a new token with Owner or Builds scope.
Build Stuck at "Queued"
Check Codemagic dashboard for concurrent build limits. Free accounts: 1 concurrent build.
iOS Pod Install Fails
Ensure --packagemanager Cocoapods flag is used. Clear cache: pod cache clean --all.
Invalid Package Name
Android requires Java-style names (e.g., com.company.app). Lowercase, letters/numbers/dots only.
Build Uses Wrong Config
Pipeline builds from main branch only. Push latest: git push origin main.
Swapped API Token / App ID
System auto-detects miswired configs and falls back to environment secrets. Verify values in the server .env file.
End-to-End Setup Guide
Complete walkthrough from zero to your first successful cloud build.
Phase 1: Codemagic Account & Token
- Create a Codemagic account at codemagic.io/signup. GitHub OAuth is the fastest method.
- Generate an API token: Navigate to
Teams → Settings → API tokens(or your personal settings). Create a new token with Owner or Builds permission scope. Copy the token — it's only shown once. - Connect your GitHub repo: In Codemagic, click "Add application" → select the GitHub repository containing your AppForge project → choose
codemagic.yamlas the configuration type. - Note your App ID: After the app is added, the App ID is visible in the URL or app settings (a 24-character hex string like
67abc1234def5678ghij9012).
Phase 2: Configure Secrets
You have two ways to provide credentials. Environment secrets take priority over database values:
Option A: Environment Secrets Recommended
Set in database admin → Settings → Secrets:
CODEMAGIC_API_TOKEN=your-token-here
CODEMAGIC_APP_ID=your-app-id-here
Option B: Admin Panel UI
Use the guided Setup Wizard:
Navigate to Admin → Integrations → Codemagic → Setup Wizard and follow the 6-step flow. The wizard validates tokens and auto-fetches available apps.
If both are set, environment secrets always override values in api_configurations. The system also detects "miswired" configs (swapped token/ID) and automatically falls back to secrets.
Phase 3: Push Code to GitHub
- Ensure
codemagic.yamlis committed and pushed to themainbranch. - The build pipeline always triggers from
main— make sure your latest app configuration is merged there. - The
cloud-buildedge function polls GitHub to verify themainbranch HEAD is recent (within 5 minutes) before triggering the Codemagic build, ensuring sync.
Phase 4: Trigger Your First Build
- Go to
/builder→ enter a website URL → configure → preview. - On Step 4 (Build), select Android or iOS platform.
- Click Build. The edge function:
- Resolves and validates Codemagic credentials
- Checks GitHub sync status (waits up to 60s for a fresh commit)
- Sanitizes the package name to valid Java/iOS format
- Triggers the Codemagic workflow with environment variables (
WEBSITE_URL,APP_NAME,PACKAGE_NAME, etc.) - Registers a webhook callback URL for real-time status updates
- Progress is tracked via the
codemagic-webhookendpoint andcloud-build-statuspolling. - On completion, the artifact (APK/IPA) URL is stored in
app_builds.download_url.
Build Environment Variables
The cloud-build function passes these variables to the Codemagic workflow:
| Variable | Source | Description |
|---|---|---|
WEBSITE_URL | User input | Target website to wrap in the native app |
APP_NAME | User input | Display name for the app |
PACKAGE_NAME | Auto-generated | Java-style package ID (e.g., com.app.mysite) |
BUNDLE_ID | Auto-generated | iOS bundle identifier (same format, used for iOS builds) |
BUILD_ID | System | Internal build record UUID for status tracking |
PRIMARY_COLOR | User config | App theme primary color hex |
ACCENT_COLOR | User config | App theme accent color hex |
CM_WEBHOOK_URL | System | Codemagic webhook callback for real-time updates |
DATABASE_URL | System | For the webhook to update build status |
Webhook Status Flow
The codemagic-webhook edge function provides real-time build updates, eliminating the need for aggressive polling.
Status Mapping
| Codemagic Status | App Status | Progress |
|---|---|---|
queued | building | 10% |
fetching | building | 15% |
preparing | building | 20% |
building | building | 30–85% |
finished / success | complete | 100% |
failed / canceled | failed | — |
Failure Diagnostics
The webhook extracts step-level failure details and provides actionable hints:
- CocoaPods errors → Suggests checking
--packagemanager Cocoapodsflag - Xcode build failures → Points to signing and provisioning issues
- SPM conflicts → Recommends using CocoaPods for Capacitor projects
- Missing Podfile → Indicates
npx cap add ioswasn't run beforepod install
Failed step name, message, and last 2000 chars of the log are stored in app_builds.config for the Build Details drawer.
Storage & File Management
Manage file storage, image optimization, CDN caching, and tiered quotas.
Bucket Management
Managed via Admin → Settings → Storage. Local file storage provides file hosting with per-bucket access controls.
Default Buckets
| Bucket | Public | Purpose | Typical Content |
|---|---|---|---|
avatars | ✓ Yes | User profile pictures | JPEG/PNG, max 2MB |
app-icons | ✓ Yes | Generated app icons | PNG, 48–512px sizes |
splash-screens | ✓ Yes | Splash screen images | PNG, various device sizes |
apk-builds | ✓ Yes | Build artifacts | APK/IPA, 10–100MB |
project-assets | ✗ No | Private project files | Source assets, certs |
RLS Policies
- Users — Upload/read/delete in own folder (
user_id/) - Admins — Full access to all buckets and folders
- Public buckets — Unauthenticated read access
Image Optimization
Configure via Admin → Settings → Storage → Optimization.
Auto-Resize
Resize uploads to max dimensions. Maintains aspect ratio.
Quality Control
Set JPEG/PNG quality (1–100).
WebP Conversion
Convert uploads to WebP for smaller files.
CDN Caching
Configure cache headers and TTL.
Settings Reference
| Setting | Default | Description |
|---|---|---|
auto_resize | true | Enable automatic resizing |
max_width | 1920 | Max width in pixels |
max_height | 1920 | Max height in pixels |
quality | 85 | Compression quality |
convert_webp | false | Auto-convert to WebP |
cache_ttl | 86400 | Cache TTL (24 hours) |
Access Control & Security
Signed URLs
Time-limited URLs for private bucket files. Configurable expiry (1 min – 7 days).
const { data } = await backend.storage
.from('project-assets')
.createSignedUrl(path, 3600);
Hotlink Protection
Restrict which domains can embed your files. Configure allowed origins to prevent bandwidth theft.
Storage Provider Configuration
Multiple backends supported. Configure via Admin → Settings → Storage → Provider.
| Provider | Required Config | Notes |
|---|---|---|
| Local file storage Default | None (built-in) | Built-in |
| AWS S3 | Bucket, Region, Access Key, Secret Key | S3 API compatible |
| Google Cloud Storage | Bucket, Service Account JSON | GCS with uniform access |
| Cloudflare R2 | Account ID, Bucket, Access Key, Secret Key | Zero egress fees |
| Local Storage | Absolute path (starts with /) | Self-hosted VPS only |
Use the Test Connection button to validate credentials via test-storage-connection edge function.
Tiered Storage Quotas
Configure via Admin → Settings → Storage → Quotas.
| Tier | Max Storage | Max File Size | Max Projects |
|---|---|---|---|
| Free | 500 MB | 10 MB | 3 |
| Pro | 5 GB | 50 MB | 25 |
| Enterprise | 50 GB | 200 MB | Unlimited |
Enforced at upload. Users warned at 80% capacity.
Storage API — Code Examples
The useStorage hook and storageApi wrapper provide full file management with validation and access control.
useStorage Hook
import { useStorage } from '@/hooks/useStorage';
const { upload, remove, getPublicUrl, getSignedUrl, listFiles, isUploading, uploadProgress } = useStorage();
// Upload a file (auto-validates type and size)
const result = await upload(file, {
bucket: 'app-icons', // 'avatars' | 'app-icons' | 'splash-screens' | 'apk-builds' | 'project-assets'
path: 'icons', // Optional subfolder within user's directory
maxSizeMB: 10, // Override default max size
allowedTypes: ['image/png'] // Override default mime types
});
// result: { url: 'https://...', path: 'user-id/icons/123-abc.png', error: null }
// Get public URL (public buckets only)
const url = getPublicUrl('avatars', 'user-id/avatar.jpg');
// Get signed URL (private buckets, time-limited access)
const signedUrl = await getSignedUrl('project-assets', 'path/file.pdf', 3600); // 1 hour
// List files in a bucket folder
const files = await listFiles('app-icons', 'icons');
// [{ name: 'icon.png', url: 'https://...' }]
// Delete a file
await remove('avatars', 'user-id/old-avatar.jpg');
Default File Limits
| Bucket | Max Size | Allowed Types |
|---|---|---|
avatars | 5 MB | JPEG, PNG, WebP, GIF |
app-icons | 10 MB | PNG, JPEG, WebP, SVG |
splash-screens | 10 MB | PNG, JPEG, WebP |
apk-builds | 500 MB | APK, IPA, ZIP |
project-assets | 50 MB | Images, PDF, JSON |
Low-Level storageApi
Direct backend client calls without validation or toast notifications:
import { storageApi } from '@/lib/api/rest-client';
// Upload with upsert
const { data, error } = await storageApi.upload('avatars', 'user-id/avatar.jpg', file);
// Delete
await storageApi.delete('avatars', 'user-id/avatar.jpg');
// List files in folder
const files = await storageApi.list('app-icons', 'user-id');
// Get public URL
const url = storageApi.getPublicUrl('avatars', 'user-id/avatar.jpg');
Admin Storage Management
Admin operations use the storage-admin edge function:
import { backend } from '@/lib/backend-client';
// List all buckets with stats
const { data } = await backend.functions.invoke('storage-admin', {
method: 'GET',
headers: { 'action': 'list' }
});
// [{ name: "avatars", public: true, fileCount: 12, totalSize: 4567890 }]
// Test connection to external provider
const { data: result } = await backend.functions.invoke('test-storage-connection', {
body: { provider: 's3', config: { s3_bucket: '...', s3_region: '...', ... } }
});
Integrations
Configure third-party services from Admin → Integrations.
Resend (Transactional Email)
Powers all transactional emails: welcome, password reset, build completion, subscription confirmations.
Setup
- Create an account at resend.com
- Generate an API key (starts with
re_) - Add
RESEND_API_KEYto the server .env file - Verify sending domain in Resend dashboard
- Configure sender address in
Admin → Integrations → Email
Test Connection
Validates API key format (re_ prefix) rather than making an API call, because browser requests to Resend are blocked by CORS. Edge functions handle sending server-side.
Email Templates
Customize at Admin → Email Templates. Templates support HTML with {{variable}} syntax. Available: {{app_name}}, {{user_name}}, {{user_email}}, {{action_url}}, {{support_email}}.
Appetize.io (Device Preview)
Interactive device previews in the browser — test apps on virtual iOS/Android devices before downloading.
Setup
- Create an account at appetize.io
- Get your API token from the Appetize dashboard
- Enter the token in
Admin → Integrations → Appetize.io - Builds automatically upload artifacts for live preview
When a build completes, the APK/IPA is uploaded to Appetize.io via the appetize-upload edge function. The embed URL appears in the Builder's Preview step.
AI Providers
Powers website analysis (metadata, colors, branding extraction) and the AI assistant (config guidance chat).
Supported Providers
| Provider | Secret Key | Models |
|---|---|---|
| OpenAI | OPENAI_API_KEY | GPT-4o, GPT-4o-mini |
| Google Gemini | GEMINI_API_KEY | Gemini Pro, Gemini Flash |
Enter keys in Admin → Integrations → AI Providers. Gemini validation uses the v1beta/models endpoint.
Codemagic Setup Wizard
Guided 6-step wizard in Admin → Integrations → Codemagic.
1 Overview
Introduction and prerequisites.
2 Account
Link Codemagic account.
3 API Token
Enter and validate token.
4 App Selection
Searchable app dropdown via API.
5 Verification
Test build trigger permissions.
6 Completion
Save config. Default workflow: android-build.
Step 4 includes a Refresh button to re-fetch Codemagic apps without re-testing the connection.
Payment Gateways
Configure payment providers from Admin → Payments. All gateways support sandbox/test mode.
Stripe
Primary gateway for card payments, subscriptions, and customer portal.
Edge Functions
| Function | Purpose |
|---|---|
stripe-checkout | Checkout Sessions for subscriptions and credit packs |
stripe-webhook | Payment success, subscription changes, cancellations |
stripe-portal | Customer Portal for self-service billing |
Required Secrets
| Secret | Format | Where to Get |
|---|---|---|
STRIPE_SECRET_KEY | sk_test_... / sk_live_... | Stripe → Developers → API keys |
STRIPE_WEBHOOK_SECRET | whsec_... | Stripe → Webhooks → Signing secret |
PUBLIC_SITE_URL | https://yourdomain.com | Your production domain |
Sandbox ↔ Live
Toggle in Admin → Payments → Stripe. Key format auto-validated (sk_test_ vs sk_live_).
Webhook Setup
# Webhook URL
https://YOUR_DOMAIN/api/functions/v1/stripe-webhook
# Required events
checkout.session.completed
customer.subscription.updated
customer.subscription.deleted
invoice.payment_succeeded
invoice.payment_failed
PayPal
One-time payments (orders) and recurring subscriptions (billing plans).
Edge Functions
| Function | Purpose |
|---|---|
paypal-checkout | PayPal orders for credit packs |
paypal-billing | Billing plans and subscription creation |
paypal-webhook | Payment capture, subscription events |
Configuration
- Client ID — PayPal REST API Client ID
- Client Secret — PayPal REST API Secret
- Mode — Sandbox or Live
Dynamic Branding
Brand name in PayPal checkout is pulled dynamically from system_settings.app_name. No hardcoded brand names.
Billing Plans
Managed at Admin → Payments → PayPal → Billing Plans. Stored in subscription_plans: paypal_product_id, paypal_plan_id, paypal_yearly_plan_id.
Coinbase Commerce
Cryptocurrency payments (Bitcoin, Ethereum, USDC, etc.).
Setup
- Create account at commerce.coinbase.com
- Generate API key (Settings → Security)
- Get webhook shared secret (Settings → Webhooks)
- Configure in
Admin → Payments → Coinbase - Add
COINBASE_API_KEYandCOINBASE_WEBHOOK_SECRETto the server .env file
Edge Functions
coinbase-checkout— Creates charges for credit packscoinbase-webhook— Processes charge:completed, charge:failed events
Bank Transfer
Manual wire transfer with admin verification workflow.
Workflow
- User selects Bank Transfer → receives bank details
- User makes transfer and uploads proof of payment
- Request enters
bank_transfer_requestswithpendingstatus - Admin reviews at
Admin → Payments → Bank Transfers - Approve → credits/subscription activated; Reject → user notified
Configure bank details (account name, IBAN, SWIFT, bank name) in Admin → Payments → Bank Transfer.
Deploy to Production
Deploy AppForge on shared hosting (cPanel), VPS, or cloud — from build to production.
Step 1: Build for Production
npm run build
Creates an optimized dist/ folder with code-split chunks, minified CSS/JS, and hashed filenames.
Step 2: Upload to Hosting
Upload the contents of dist/ (not the folder itself) to your web root:
- cPanel: File Manager →
public_html/→ Upload all files fromdist/ - VPS:
scp -r dist/* user@server:/var/www/html/ - Netlify/Vercel: Connect your Git repo; set build command to
npm run buildand publish directory todist
Step 3: Configure .htaccess (Apache/cPanel)
Required for SPA routing. The repo includes a pre-configured .htaccess file:
# SPA Routing — redirect all requests to index.html
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.html [L]
</IfModule>
# Force HTTPS
<IfModule mod_rewrite.c>
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>
# Gzip Compression
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/javascript application/json
</IfModule>
# Security Headers
<IfModule mod_headers.c>
Header set X-Content-Type-Options "nosniff"
Header set X-Frame-Options "SAMEORIGIN"
Header set X-XSS-Protection "1; mode=block"
Header set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>
Step 4: Enable SSL
HTTPS is required for service workers, push notifications, camera, and biometrics.
- AutoSSL: cPanel → SSL/TLS Status → "Run AutoSSL"
- Let's Encrypt: cPanel → Let's Encrypt → Issue for your domain
Step 5: Configure the Database for Production
- Add your production domain to database admin → Authentication → URL Configuration → Site URL
- Add the domain to Redirect URLs as well
- Verify edge function secrets are set (Dashboard → Settings → Secrets)
- Set
PUBLIC_SITE_URLsecret to your production domain (used in webhook emails)
Step 6: Verify Deployment
Check These
- App loads at your domain with HTTPS
- Deep links work on refresh (
/dashboard,/admin) - Login/signup functionality works
- Browser console shows no errors
- Setup wizard redirects correctly
Test Edge Functions
- Health check:
/functions/v1/cloud-build?health=1 - Create a test build
- Verify payment flow in test mode
- Send a test email from Admin → Integrations
Troubleshooting
404 on Page Refresh
Ensure .htaccess is configured and mod_rewrite is enabled. For Nginx, add try_files $uri /index.html;.
Blank White Page
Check browser console for JS errors. Common: missing .env variables, incomplete file upload, wrong base in vite.config.
CORS Errors
Add your production domain to database admin → Settings → API → Allowed Origins.
Auth Redirect Loops
Add your domain to Better Authentication → URL Configuration → Redirect URLs.
Updating & Redeployment
How to update an existing production installation to the latest version.
Export your Postgres database and download your .env file before performing any update.
Step 1: Pull Latest Code
# Navigate to your project directory
cd appforge
# Pull the latest changes
git pull origin main
# Install any new/updated dependencies
npm install
Step 2: Apply New Database Migrations
New versions may include database schema changes (new tables, columns, functions, or RLS policies).
# Ensure you're linked to the correct project
(set DATABASE_URL in your .env)
# Push any new migrations
npm run db:push
db push doesIt applies only the migration files that haven't been run yet. The schema is idempotent (CREATE ... IF NOT EXISTS), so re-running only creates what is missing. Your existing data is preserved.
Step 3: Deploy Updated Edge Functions
npm run dev (backend functions run in the Express server)
This redeploys all edge functions with the latest code. Existing secrets are preserved.
Step 4: Rebuild & Upload Frontend
# Build production bundle
npm run build
# Upload dist/ contents to your hosting
# cPanel: File Manager → public_html/ → Upload
# VPS: scp -r dist/* user@server:/var/www/html/
Step 5: Verify the Update
- Hard-refresh your browser (Ctrl+Shift+R) to clear cached assets
- Check that the app loads without console errors
- Verify login/signup still works
- Check Admin Panel → System Settings for any new options
- Test a sample build to verify edge functions are working
Quick Reference: Update Commands
# Complete update sequence (run from project root)
git pull origin main
npm install
npm run db:push
npm run dev (backend functions run in the Express server)
npm run build
# Then upload dist/ to your hosting
Updating Edge Function Secrets
If the changelog mentions new required secrets:
# Set a new secret via CLI
(set secrets in the server .env file)
# Or via database admin → Settings → Secrets
Production Guide
Security, performance, monitoring, and operational best practices.
Production Readiness Checklist
Security
Performance
Security Best Practices
Row Level Security (RLS)
All tables use RLS. Admin access is verified via has_role(auth.uid(), 'admin') — a SECURITY DEFINER function that cannot be bypassed client-side.
-- Users access own data only
CREATE POLICY "Users access own data"
ON public.app_builds FOR SELECT
USING (auth.uid() = user_id);
-- Admin-only tables use SECURITY DEFINER functions
CREATE POLICY "Admins only"
ON public.system_settings FOR ALL
USING (has_role(auth.uid(), 'admin'));
Payment Gateway Production Setup
- Stripe: Switch
sk_test_→sk_live_keys in the server .env file. Configure live webhook endpoint. - PayPal: Switch from sandbox to live credentials in Admin → Payments. Configure webhook URL in PayPal Dashboard.
- Coinbase: Set live API key and webhook secret.
- Bank Transfer: Update bank details in Admin → Payments → Bank Transfer.
Backup Strategy
- Database: Schedule regular
pg_dumpbackups (e.g. via cron) for your Postgres instance. - Storage: Download critical files periodically. Build artifacts can be regenerated.
- Settings:
settings_audit_logtracks all changes for recovery. - Code: Keep in Git. Tag releases before deploying.
Scaling
- Edge Functions: Run inside the Express backend; scale by running more backend instances behind a load balancer.
- Database: Monitor connections and query performance. Add indexes as needed.
- Storage: Use CDN (Cloudflare) in front of your hosting for static assets.
- Builds:
max_builds_per_daysetting prevents abuse. - Credits: Natural throttle. Adjust
credits_per_buildas needed.
Project Structure
File organization and architectural overview.
Directory Layout
appforge/
├── docs/ # Documentation (this site)
├── public/ # Static assets (robots.txt, favicon)
├── src/
│ ├── components/
│ │ ├── admin/ # Admin panel components (20+)
│ │ ├── builder/ # App builder wizard steps
│ │ │ └── configure/ # Builder configuration sub-components
│ │ ├── subscription/ # Billing & credit pack UI
│ │ └── ui/ # Shadcn/Radix design system components
│ ├── contexts/ # React context providers (AuthContext)
│ ├── hooks/ # Custom hooks (30+)
│ ├── lib/
│ │ ├── backend-client.ts # Backend client (auth/db/storage/functions)
│ │ ├── auth-client.ts # Better Auth browser client
│ │ └── api/ # REST API client wrappers
│ ├── pages/ # Route page components (15+)
│ ├── stores/ # Zustand state stores
│ ├── types/ # TypeScript type definitions
│ └── utils/ # Utility functions
├── server/
│ ├── src/ # Express backend (routes, auth, functions)
│ └── db/ # schema.sql & auth-schema.sql
├── .htaccess # Apache SPA routing & security
├── capacitor.config.ts # Capacitor native app config
├── codemagic.yaml # CI/CD build pipeline
└── vite.config.ts # Vite bundler configuration
Key Architecture Patterns
Lazy Loading
All page components use React.lazy() with Suspense for code splitting. Reduces initial bundle by ~60%.
Zustand Stores
useAppStore (app state), useThemeStore (theme), useUserPreferencesStore (preferences). Persistent via localStorage.
React Query
Server state management via @tanstack/react-query. Automatic caching, background refetching, and stale data handling.
RPC-First Database
Credit operations use SECURITY DEFINER database functions (use_credits, add_credits) for atomic, tamper-proof transactions.
Application Routes
All routes use the ProtectedRoute, PublicRoute, or SetupRoute guard components.
| Path | Component | Guard | Description |
|---|---|---|---|
/ | Index | Public | Landing page with hero, features, pricing |
/auth | Auth | Public | Login / signup / magic link |
/setup | AdminSetup | Setup | First-run wizard (only when no admin exists) |
/dashboard | Dashboard | Protected | User dashboard with projects, credits, builds |
/builder | AppBuilder | Protected | 4-step website-to-app wizard |
/settings | Settings | Protected | User profile, password, storage, preferences |
/subscription | Subscription | Protected | Plans, credit packs, payment methods |
/admin | Admin | Protected | Admin panel (requires admin role) |
/build-history | BuildHistory | Protected | All past builds with status and downloads |
/payment-history | PaymentHistory | Protected | Transaction records and invoices |
/help | Help | None | Help center and FAQ |
/privacy | Privacy | None | Privacy policy |
/terms | Terms | None | Terms of service |
/install | Install | None | PWA install instructions |
/style-guide | StyleGuide | None | Design system component showcase |
* | NotFound | None | 404 page |
Keyboard Shortcuts
Available in the App Builder. Press ? to show the shortcuts overlay.
| Shortcut | Action | Context |
|---|---|---|
| ← → | Navigate between steps | All steps |
| 1 – 4 | Jump to specific step | All steps (up to current + 1) |
| ⌘+R | Refresh preview | Preview step |
| ⌘+S | Take screenshot | Preview step |
| ⌘+O | Rotate device | Preview step |
| ⌘+G | Toggle comparison mode | Preview step |
| ? | Show shortcuts help | All steps |
Shortcuts are disabled when typing in input fields or textareas. ⌘ = Ctrl on Windows/Linux.
GDPR & Cookie Consent
Privacy compliance with granular cookie consent and audit trail.
Cookie Consent Banner
Displayed on first visit via CookieConsent component. Users can accept all, reject all, or customize preferences.
Cookie Categories
| Category | Default | Purpose | Can Disable |
|---|---|---|---|
| Necessary | Always on | Authentication, session management, CSRF protection | No |
| Analytics | Off | Usage tracking, error monitoring, performance metrics | Yes |
| Marketing | Off | Personalization, third-party ads, retargeting | Yes |
Implementation
- Preferences stored in
localStorageundercookie-consentkey - Custom event
cookieConsentChangeddispatched on preference update - Users can re-open settings dialog anytime from the footer
Consent Records Table
Server-side audit trail stored in consent_records table with RLS.
| Column | Type | Description |
|---|---|---|
user_id | uuid (nullable) | Linked to auth user (null for anonymous) |
consent_type | text | Category: necessary, analytics, marketing |
consented | boolean | Whether user accepted this category |
ip_address | text | IP at time of consent |
user_agent | text | Browser user agent string |
email | text | User email (if known) |
RLS Policies
- Users can insert records for themselves or anonymously (
user_id IS NULL) - Users can read/update only their own records
- No delete access (audit compliance)
Invoice System
Create, manage, and track invoices with multi-gateway payment support.
Invoice Table Schema
| Column | Type | Description |
|---|---|---|
invoice_number | text | Auto-generated unique number (e.g., INV-2026-001) |
user_id | uuid | Customer (linked to profiles) |
amount | numeric | Total invoice amount |
currency | text | Default: USD |
status | text | draft, pending, paid, overdue, cancelled |
items | jsonb | Array of line items: [{description, quantity, unit_price}] |
due_date | timestamp | Payment deadline |
paid_at | timestamp | When payment was received |
notes | text | Internal admin notes |
Admin Workflow
- Create invoice at
Admin → Payments → Invoices - Select user, add line items, set due date
- Invoice auto-calculates total from items
- Users see invoices at
/payment-history - Payment via any configured gateway (Stripe, PayPal, Coinbase)
- Status transitions:
draft → pending → paid(oroverdue/cancelled)
Webhook Event Logs
All incoming payment webhooks are logged to webhook_event_logs for debugging and auditing.
| Column | Type | Description |
|---|---|---|
gateway | text | stripe, paypal, coinbase |
event_type | text | e.g., checkout.session.completed |
event_id | text | Gateway's unique event identifier |
status | text | received, processed, failed |
payload | jsonb | Full webhook payload |
error_message | text | Error details (if failed) |
processing_time_ms | integer | Time to process the event |
response_status | integer | HTTP status returned |
Retry Mechanism
Failed webhooks can be retried from Admin → Payments → Webhooks. The retry-webhook edge function resends the original payload to the gateway handler with an X-Webhook-Retry: true header.
Automation System
Configurable workflows for automated build triggers, notifications, and maintenance tasks.
System Overview
The automation system enables per-project workflows that execute on schedules or events. Automations are stored in automation_configs with execution history in automation_logs.
Per-Project
Each automation is linked to an app_project via project_id.
Toggle On/Off
is_enabled flag lets users pause automations without deleting.
Run Tracking
run_count, last_run_at, and next_run_at for monitoring.
Workflow Types
| Type | Description | Config Example |
|---|---|---|
auto_build | Automatically trigger a build when source changes are detected | { "trigger": "push", "branch": "main", "platform": "android" } |
scheduled_build | Rebuild on a cron-like schedule | { "cron": "0 2 * * 1", "platform": "android" } |
notify_on_change | Send email notification when the target website content changes | { "check_interval_hours": 24, "notify_email": "user@..." } |
scheduled_check | Periodic health check on the target website URL | { "interval_minutes": 60, "alert_on_downtime": true } |
auto_update | Auto-rebuild when a new app version is available | { "check_interval_hours": 12 } |
Automation API
Client-side API via automationApi from @/lib/api/rest-client.
import { automationApi } from '@/lib/api/rest-client';
// List automations (for current user, optionally filtered by project)
const { data } = await automationApi.list(projectId);
// data.automations: Array of automation configs
// Create a new automation
await automationApi.create(projectId, 'auto_build', {
trigger: 'push',
branch: 'main',
platform: 'android'
});
// Toggle enabled/disabled
await automationApi.toggle(automationId, false);
// Update config
await automationApi.updateConfig(automationId, { cron: '0 3 * * *' });
// Get execution logs
const { data: logs } = await automationApi.getLogs(automationId);
// logs.logs: [{ status, started_at, completed_at, message, metadata }]
// Trigger manual execution
await automationApi.execute(automationId);
// Delete an automation
await automationApi.delete(automationId);
Database Schema
automation_configs
| Column | Type | Description |
|---|---|---|
id | uuid | Primary key |
user_id | uuid | Owner (references auth.users) |
project_id | uuid | Linked app project (FK → app_projects) |
workflow_type | text | e.g., auto_build, scheduled_check, notify_on_change |
is_enabled | boolean | Toggle on/off (default: true) |
config | jsonb | Workflow-specific parameters |
last_run_at | timestamp | Last execution time |
next_run_at | timestamp | Scheduled next run |
run_count | integer | Total executions (default: 0) |
automation_logs
| Column | Type | Description |
|---|---|---|
id | uuid | Primary key |
automation_id | uuid | FK → automation_configs |
user_id | uuid | Owner |
status | text | pending, running, success, failed |
started_at | timestamp | Execution start |
completed_at | timestamp | Execution end (null if running) |
message | text | Result or error message |
metadata | jsonb | Additional execution data (build ID, check results, etc.) |
RLS Policies
- automation_configs — Users can CRUD their own configs. Admins can view all.
- automation_logs — Users can read their own logs. Admins can read all. Insert/update is server-side only.
Nginx Configuration
Server block configuration for VPS/Nginx deployments (alternative to Apache/.htaccess).
Complete Nginx Server Block
server {
listen 443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
root /var/www/html;
index index.html;
# SSL (Let's Encrypt / Certbot)
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
# SPA Routing — send all requests to index.html
location / {
try_files $uri $uri/ /index.html;
}
# Cache static assets (JS, CSS, images)
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
# Security headers
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Gzip compression
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml;
gzip_min_length 1000;
}
# HTTP → HTTPS redirect
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
return 301 https://$host$request_uri;
}
Key Differences from Apache
| Feature | Apache (.htaccess) | Nginx |
|---|---|---|
| SPA routing | RewriteRule ^ index.html [L] | try_files $uri /index.html |
| Compression | mod_deflate | gzip on |
| Caching | mod_expires | expires directive |
| Config location | Per-directory (.htaccess) | Centralized (/etc/nginx/) |
| Hot reload | Automatic | Requires nginx -s reload |
Run sudo certbot --nginx -d yourdomain.com to automatically configure SSL and the redirect block.
Changelog
Version history with features, improvements, and bug fixes.
Dynamic Branding, Streamlined Setup, Cloud Build Pipeline & Documentation
🆕 New Features
- Fully Dynamic Branding — App name is pulled from the
system_settingsdatabase table everywhere: navbar, auth, footer, help, legal pages, and PayPal checkout. No hardcoded brand names remain. - Streamlined Setup Wizard (4 Steps) — Consolidated from 8 steps to 4: Welcome & Environment Check → Admin Account → App Configuration → Launch. Advanced settings deferred to Admin Panel.
- Codemagic Cloud Builds — Android APK and iOS IPA builds via Codemagic CI/CD pipeline with real-time progress tracking. Requires GitHub repo connection.
- Integrations Manager — Unified UI for configuring Resend, Appetize.io, AI providers (OpenAI/Gemini), and Codemagic with test connection utilities.
- Enhanced AI Edge Functions — analyze-website and ai-assistant support OpenAI & Gemini with automatic fallback.
- Demo Mode Read-Only Admin — All admin panel mutations are blocked in demo/test mode with user-friendly toast notifications.
- Codemagic App ID Auto-Sync — Admin → Integrations includes a sync button to auto-resolve the App ID from the active Codemagic token.
🔧 Improvements
- Generic Storage Keys — localStorage keys renamed from brand-specific (
appforge-*) to generic (app-theme,app-storage,app-user-preferences). - Edge Function Cleanup — Removed all hardcoded
appforge.devreferences from send-email, stripe-webhook, and cloud-build functions. - Dynamic PayPal Brand Name — PayPal checkout function reads brand name from system_settings at runtime.
- Generic Build Metadata — Vite and Capacitor configs use generic app IDs and descriptions.
- Codemagic Setup Wizard — Admin → Integrations includes a guided setup flow for connecting Codemagic.
- Integration Key Format Validation — CORS-safe client-side validation for Resend, Appetize, and AI API keys.
- Codemagic App ID Fallback — Cloud build edge function validates the configured App ID and auto-falls back to the accessible app if the saved ID is stale.
- Improved Build Error Messages — More accurate diagnostics distinguishing token scope issues from stale App ID mismatches.
🐛 Bug Fixes
- Setup Wizard Route Guard —
/setupnow correctly blocks re-entry once an admin exists, usingno_admin_exists()RPC. - Gemini API Key Validation — Fixed invalid key error by using correct v1beta/models endpoint.
- Resend Test Connection — Resolved CORS "Failed to fetch" error with format-only validation.
- Logo Variable Reference — Fixed build error from renamed import variable in Auth and AdminSetup pages.
- Codemagic 403 False Positive — Fixed misleading "token lacks permission" error when the real cause was a stale/inaccessible App ID.
- vite-plugin-pwa Compatibility — Updated to v1.2.0+ for Vite 7 peer dependency support.
📚 Documentation
- Codemagic End-to-End Setup Guide — Complete 4-phase walkthrough: account creation, secret configuration (env vs UI), GitHub sync, first build trigger, with build environment variables reference table.
- Webhook Status Flow — Detailed Codemagic webhook status mapping, failure diagnostics (CocoaPods, Xcode, SPM), and step-level error extraction.
- Edge Functions Detailed Reference — Full request/response schemas, error codes, and required secrets for all 19 edge functions including payment gateways (Stripe, PayPal, Coinbase).
- Storage API Usage — Code examples for
useStoragehook,storageApiwrapper, file upload/download/signed URLs, default bucket limits table, and admin bucket management. - Automation System Expansion — Workflow types reference table, full
automationApicode examples, complete database schema for both tables, and RLS policy documentation.
🧹 Cleanup
- Removed Active Builds Panel — Deleted
BuildProgressPanelcomponent anduseBuildProgresshook. Build status is tracked via the builder's Build step and Build History page.
📋 Migration Notes
- Existing users will have their theme/preferences reset on first visit due to localStorage key rename. One-time only.
- Run
npm run db:pushto apply new migrations. - Run
npm run dev (backend functions run in the Express server)to update edge functions. - Set
PUBLIC_SITE_URLsecret in database admin if using Stripe webhooks.
Build Pipeline, Preview Dialog & Dashboard UX Improvements
🆕 New Features
- Buy Credits Dashboard Button — Quick access to credit pack purchases from Dashboard header.
- Binary AndroidManifest.xml — APK builds include valid binary manifest with proper resource IDs.
- App Version Auto-Increment — Rebuild actions automatically bump version numbers.
🐛 Bug Fixes
- Preview Dialog Overflow — Responsive sizing with proper max dimensions.
- IPA Bundle Layout — Correct Payload/*.app structure with valid Info.plist.
- Build History Status Filter — Fixed to recognize both
completeandcompletedstatuses.
Documentation Overhaul, Demo Mode & Edge Function Health
- Environment-Based Demo Mode Control —
VITE_DEMO_MODEoverrides database setting. - Edge Function Health Checks — All functions support
?health=1parameter. - Dark Mode Visibility Fixes — Separate CSS variables for light/dark themes.
Payment Gateway Admin Enhancements
- Stripe Sandbox/Live Mode Toggle — Switch modes from admin panel.
- Key Format Validation — Auto-validates Stripe key formats.
- Transactional Email System — Automated emails via Resend.
Multi-Payment Gateway Support
- PayPal Integration — Orders, webhooks, billing plans.
- Coinbase Commerce — Cryptocurrency payments.
- Bank Transfer Support — Manual wire with admin approval.
- Credit Packs — One-time purchasable credit bundles.
Admin Panel & User Management
- Role-Based Access Control — Admin, moderator, user roles.
- Credit System — Monthly credits with reset, bonus credits from purchases.
- Setup Wizard — Guided first-run configuration.
- Demo Mode — Full demo experience with guided tour.
Initial Release
- Website to App Conversion — 4-step wizard for native iOS/Android apps.
- AI-Powered Analysis — Automatic metadata and color extraction.
- Native Feature Hooks — Camera, biometrics, haptics, push notifications.
- Device Preview — Phone mockups with comparison mode.
- Stripe Payments — Subscription plans with checkout and webhooks.
- PWA Support — Offline caching, install prompt, service worker.
Help Center
Frequently asked questions and troubleshooting.
Setup & Configuration
/setup when no admin exists. It's a 4-step process: Welcome & Environment Check → Admin Account → App Configuration → Launch.DATABASE_URL, BETTER_AUTH_SECRET, and BETTER_AUTH_URL. Copy .env.example to .env and fill in your values.npm run db:push — it applies server/db/schema.sql and server/db/auth-schema.sql to the database in DATABASE_URL.git pull origin main && npm install && npm run db:push && npm run dev (backend functions run in the Express server) && npm run build. Then upload dist/ to your hosting. See the Updating guide for details.Building Apps
cloud-build) triggers Codemagic, which compiles the Capacitor project into an APK or IPA. Progress is tracked in real-time.Billing & Credits
Admin & Security
/admin. You must be logged in with the admin role. The admin role is assigned during the setup wizard.SECURITY DEFINER functions.has_role() — a SECURITY DEFINER database function that runs with elevated privileges. This cannot be bypassed from the client side. Roles are stored in the separate user_roles table, not in the user profile.Still Need Help?
Check the documentation sections above or reach out to the development team.