You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Rio is a production-grade full-stack Figma plugin that bridges the gap between natural language and pixel-perfect design. It combines a conversational AI engine (supporting 7+ model providers), a personal cloud UI component library, and a Stripe-powered billing system into a single Figma plugin.
The system comprises two independent sub-projects that communicate over HTTP:
Sub-project
Role
backend/
Node.js REST API — auth, AI orchestration, billing, storage
figma-plugin/
Figma sandbox + React iframe — design creation and UI
2. Features
Feature
Description
API Endpoint
AI Generate
Chat with AI to generate new Figma designs from natural language
POST /api/designs/generate-from-conversation
AI Edit
Modify a selected Figma node with a follow-up prompt
POST /api/designs/edit-with-ai
AI Variant
Generate a design variant from an existing Figma selection
POST /api/designs/generate-based-on-existing
AI Prototype
Auto-generate Figma prototype connections
POST /api/designs/generate-prototype
Paste JSON
Convert any structured JSON blob into live Figma nodes
Plugin-side only
Export JSON
Export any Figma selection to a clean, portable JSON
Plugin-side only
Design Versions
Save & restore design snapshots to the cloud
GET/POST /api/design-generations
UI Library
Manage reusable components in named projects with S3 image previews
CRUD /api/ui-library
Points (Pay-per-use)
Purchase AI generation credits with Stripe one-time checkout
POST /api/payments/create-checkout
Subscriptions
Monthly subscription plans with daily point allocations
POST /api/subscriptions/create-checkout
Google OAuth
One-click login via Google — JWT issued on completion
sequenceDiagram
autonumber
actor User
participant Plugin as Figma Plugin\n(main.ts)
participant UI as Plugin UI\n(React)
participant Browser as Browser Tab
participant API as Backend API
participant Google as Google OAuth
User->>UI: Clicks "Sign in with Google"
UI->>Plugin: postMessage(OPEN_AUTH)
Plugin->>Browser: figma.openExternal(authURL)
Browser->>API: GET /auth/google
API->>Google: Redirect to Google consent screen
Google-->>API: GET /auth/google/callback?code=...
API->>Google: Exchange code for user info
Google-->>API: { email, name, picture, googleId }
API->>API: Upsert user in DB
API->>API: Generate JWT (30-day expiry)
API->>API: Store token in memory (TokenStore)
API-->>Browser: Redirect → success page
Browser-->>User: "Login successful, return to Figma"
loop Poll every 2 seconds (max 60s)
Plugin->>API: GET /auth/poll
alt Token ready
API-->>Plugin: { token: "eyJ..." }
Plugin->>Plugin: figma.clientStorage.set('token')
Plugin->>UI: postMessage(AUTH_SUCCESS, user)
else Not ready yet
API-->>Plugin: { token: null }
end
end
UI->>UI: Render HomeScreen
Loading
9.2 AI Design Generation Flow
sequenceDiagram
autonumber
actor Designer
participant UI as Plugin UI (React)
participant Plugin as Plugin Sandbox
participant API as Backend API
participant AIOrch as AI Orchestrator\n(AiGenerateDesignService)
participant AIProvider as AI Provider\n(OpenAI/Claude/Gemini/...)
participant DB as PostgreSQL
participant Canvas as Figma Canvas
Designer->>UI: Types prompt, selects model, hits Generate
UI->>API: POST /api/designs/generate-from-conversation\n{ prompt, modelId, conversationHistory }
API->>API: Validate JWT + deduct points check
API->>AIOrch: execute(prompt, model, history)
AIOrch->>AIOrch: Build system prompt\n(load design system template)
AIOrch->>AIProvider: chat.completions(messages)
alt Success
AIProvider-->>AIOrch: { designJson, aiMessage, tokens }
AIOrch->>AIOrch: Extract icons from JSON
AIOrch->>AIOrch: Calculate cost & points
AIOrch-->>API: { resultDesign, inputTokens, outputTokens, cost }
API->>DB: INSERT design_generations (status=success)
API->>DB: UPDATE users SET pointsBalance -= deducted
API-->>UI: 200 { design, aiMessage, pointsBalance }
else AI Error
AIProvider-->>AIOrch: Error / malformed JSON
AIOrch-->>API: throw AiGenerationError
API->>DB: INSERT design_generations (status=failed)
API-->>UI: 422 { error: "Generation failed" }
end
UI->>Plugin: postMessage(IMPORT_DESIGN, { design })
Plugin->>Canvas: Create Figma nodes\n(FrameCreator, TextCreator, ...)
Canvas-->>Plugin: Nodes created
Plugin-->>UI: postMessage(IMPORT_COMPLETE)
UI->>Designer: Show success toast + updated points balance
Loading
9.3 Payment & Points Flow
sequenceDiagram
autonumber
actor User
participant UI as Plugin UI
participant API as Backend API
participant Stripe as Stripe API
participant Webhook as Stripe Webhook
participant DB as PostgreSQL
User->>UI: Clicks "Buy Points" → selects package
UI->>API: POST /api/payments/create-checkout\n{ packageId }
API->>Stripe: sessions.create({ price, metadata })
Stripe-->>API: { sessionId, url }
API-->>UI: { checkoutUrl, sessionId }
UI->>UI: Open Stripe checkout in browser
User->>Stripe: Completes payment
Stripe->>Webhook: POST /api/payments/webhook\n(checkout.session.completed)
Webhook->>Webhook: Verify Stripe signature
Webhook->>DB: UPDATE payment_transactions SET status=completed
Webhook->>DB: UPDATE users SET pointsBalance += purchased
Webhook-->>Stripe: 200 OK
loop Poll every 2s (max 60s)
UI->>API: GET /api/payments/poll/:sessionId
alt Payment confirmed
API-->>UI: { status: 'completed', newBalance: 3750 }
UI->>UI: Update displayed points balance
UI->>User: "Points added successfully!"
else Pending
API-->>UI: { status: 'pending' }
end
end
Loading
9.4 Subscription Flow
flowchart TD
A([User selects plan]) --> B[POST /api/subscriptions/create-checkout]
B --> C[Stripe subscription checkout]
C --> D{User completes\npayment?}
D -->|Yes| E[Stripe webhook fires\nsubscription.created]
D -->|No| F([Checkout abandoned])
E --> G[Insert subscription record\nstatus=active]
G --> H[Set dailyPointsLimit\nper plan tier]
H --> I([Daily AI usage])
I --> J{dailyPointsUsed\n< dailyPointsLimit?}
J -->|Yes| K[Allow AI generation\nIncrement dailyPointsUsed]
J -->|No| L[Return 429 Daily limit reached]
K --> M{Next calendar day?}
M -->|Yes| N[Reset dailyPointsUsed = 0\nUpdate lastUsageResetDate]
N --> I
O([User cancels]) --> P[POST /api/subscriptions/cancel]
P --> Q[Stripe: cancelAtPeriodEnd = true]
Q --> R[Subscription expires at\ncurrentPeriodEnd]
R --> S[status = expired]
Loading
9.5 UI Library Component Flow
flowchart LR
subgraph Figma["Figma Canvas"]
SEL["User selects\nnodes"]
end
subgraph Plugin["Plugin Sandbox"]
EXP["NodeExporter\n(Figma → JSON)"]
IMG["ImageOptimizer\n(rasterize preview)"]
end
subgraph API["Backend API"]
direction TB
UP["POST /components\n(save JSON)"]
S3U["POST /upload-image\n(S3 upload)"]
LIST["GET /projects/:id/components"]
DEL["DELETE /components/:id\n+ S3 delete"]
end
subgraph Storage["External Storage"]
S3[("AWS S3\nbucket")]
PG[("PostgreSQL\nui_library_components")]
end
SEL --> EXP --> Plugin
Plugin -->|exportJson| UP --> PG
Plugin -->|previewPng| S3U --> S3
PG -->|previewImage URL| LIST
LIST --> SEL2["User views\ncomponent grid"]
DEL --> PG & S3
Loading
9.6 Plugin Build Pipeline
flowchart TD
A([npm run build]) --> B{Mode?}
B -->|--prod| C[minify: true\ndrop console logs]
B -->|default| D[minify: false\nkeep logs]
C & D --> E[esbuild: bundle UI\nentryPoint: index.jsx\nbundle: true\nloader: jsx,tsx,css,js,ts]
E --> F[Inline CSS into\n<style> tag]
F --> G[Escape </script>\ninjection sequences]
G --> H["Write dist/ui.html\n(self-contained)"]
C & D --> I[esbuild: bundle Plugin\nentryPoint: main.ts\nplatform: browser\ntarget: es2017]
I --> J[Write dist/code.js]
H & J --> K([Load in Figma\nDesktop App])
git clone https://github.com/Rezkaudi/task-creator.git
cd task-creator
Step 2 — Backend
cd backend
npm install
# Copy and fill in environment variables
cp .env.example .env
# Edit .env with your credentials# Run database migrations
npm run migration:run
# Start development server (nodemon + ts-node)
npm run dev
# → API running at http://localhost:5000# → Swagger UI at http://localhost:5000/api-docs
Step 3 — Figma Plugin
cd ../figma-plugin
npm install
# Development build with watch mode
npm run dev
# → Outputs dist/code.js and dist/ui.html
Step 4 — Load Plugin in Figma
Open Figma Desktop
Menu → Plugins → Development → Import plugin from manifest…
Select figma-plugin/manifest.json
Run the plugin — it will connect to http://localhost:5000
Step 5 — Stripe Webhooks (local)
# Forward Stripe events to local server
stripe listen --forward-to http://localhost:5000/api/payments/webhook
# Test a payment event
stripe trigger checkout.session.completed
Set all env vars in Render dashboard (never commit secrets)
NODE_ENV=production
Use a strong random JWT_SECRET (≥ 64 chars)
Register Stripe production webhook pointing to https://...onrender.com/api/payments/webhook
Verify AWS S3 bucket CORS policy allows Figma plugin origin
Figma Plugin
# Build for production (minified, points to production API)cd figma-plugin
npm run build
# Distribute via Figma Community# Or share manifest.json + dist/ folder
Plugin checklist:
Set BACKEND_URL in .env.production
Run npm run build (not build:local)
Update manifest.json version number
Submit to Figma Community or share dist/ + manifest.json