A production-ready Go backend for integrating Figma designs with CaptureCraft. Includes a complete REST API server, SQLite database layer, rate limiting, webhook processing, and real-time synchronization.
Production-Ready Backend Infrastructure:
- ✅ REST API Server with 20+ endpoints
- ✅ SQLite Database with auto-migration
- ✅ Rate Limiting (token bucket algorithm)
- ✅ Webhook Processing & File Sync
- ✅ Structured Logging with Context Support
- ✅ OAuth 2.0 Token Management
- ✅ Comprehensive Documentation & Examples
- ✅ Docker & docker-compose Setup
- ✅ Hot-reload Development Mode
- ✅ Ready for Kubernetes Deployment
- QUICKSTART.md - Get running in 5 minutes
- API.md - Complete REST API reference (50+ examples)
- DEPLOYMENT.md - Production deployment guide (Docker, K8s, bare metal)
- INTEGRATION.md - Frontend integration with React/TypeScript
- OPTIMIZATION.md - Performance tuning and caching strategies
- 20+ Endpoints covering all Figma operations
- Authentication - Bearer token & OAuth 2.0
- Health Checks - Liveness and readiness probes
- Consistent Responses - Standardized JSON format
- Error Handling - Typed errors with HTTP status codes
- SQLite - Lightweight, embedded database
- Auto-migration - Schema created on startup
- Connection Pooling - Configurable pool size
- 8 Data Models - OAuth tokens, webhooks, exports, metadata, sync jobs, logs
- Token Bucket - Configurable RPM limits
- Per-user Tracking - Individual user rate limits
- Exponential Backoff - Retry logic with max wait time
- Circuit Breaker - Graceful degradation on failures
- Background Service - Processes events in batches
- Event Types - FILE_UPDATE, FILE_DELETE, LIBRARY_PUBLISH
- Automatic Caching - Stores file and component data
- Configurable Intervals - Tune sync frequency
- Hot-reload - Automatic restart on code changes (air)
- Structured Logging - Context-aware logging with multiple levels
- Docker Compose - One-command local development
- SQLite Browser - Visual database inspection at :8080
- Make Targets - Common tasks (build, test, run, lint)
# Start all services with docker-compose
docker-compose up
# API: http://localhost:3000
# Dev API (hot-reload): http://localhost:3001
# SQLite Browser: http://localhost:8080# Setup
go mod download
cp .env.example .env
# Run with hot-reload
make dev-server
# API: http://localhost:3000# Health check
curl http://localhost:3000/health
# Get file with authentication
curl http://localhost:3000/api/files/{fileKey} \
-H "Authorization: Bearer $FIGMA_ACCESS_TOKEN"See QUICKSTART.md for complete getting started guide.
GET /health- Server health checkGET /status- Detailed server status
GET /auth/callback- OAuth 2.0 callback handler
GET /api/files- List all accessible filesGET /api/files/{fileKey}- Get file detailsGET /api/files/{fileKey}/versions- Get version historyGET /api/files/{fileKey}/components- Get all components
GET /api/exports/node- Export single nodePOST /api/exports/batch- Batch export multiple nodes
GET /api/components/search- Search components across files
GET /api/webhooks- List active webhooksPOST /api/webhooks- Create webhookPOST /api/webhooks/event- Process webhook event (internal)
GET /api/sync/file- Manually sync fileGET /api/sync/status- Get sync service statusGET /api/cache/clear- Clear local cache
See API.md for complete endpoint documentation with examples.
┌─────────────────────────────┐
│ CaptureCraft Web UI │
│ (React/Vue/Angular etc) │
└──────────────┬──────────────┘
│ HTTP/REST
│
┌──────────────▼──────────────┐
│ Figma API Server (Go) │
│ - REST API │
│ - Rate Limiting │
│ - Webhook Processing │
│ - Sync Service │
└──────────────┬──────────────┘
┌─────┴─────┐
│ │
┌────▼───┐ ┌───▼─────────────┐
│ Figma │ │ SQLite Database │
│ API │ │ - Tokens │
│ │ │ - Webhooks │
└────────┘ │ - Cache │
│ - Metadata │
└─────────────────┘
capturecrafy-api/
├── Core Components
│ ├── main.go # Application entry point
│ ├── server.go # REST API server (900 lines, 20+ endpoints)
│ ├── db.go # SQLite database layer (~560 lines)
│ ├── models.go # Database models (9 structs)
│ ├── figma-api-client.go # Figma API client (OAuth, files, exports, webhooks)
│
├── Infrastructure
│ ├── config.go # Environment configuration
│ ├── logger.go # Structured logging
│ ├── errors.go # Custom error types
│ ├── ratelimit.go # Rate limiting + retry + circuit breaker
│ ├── sync.go # Webhook processor + sync service
│ ├── utils.go # Helper utilities
│
├── DevOps & Build
│ ├── Dockerfile # Multi-stage Docker build
│ ├── docker-compose.yml # Local dev + prod services
│ ├── .air.toml # Hot-reload configuration
│ ├── Makefile # Build automation
│ ├── .env.example # Configuration template
│ ├── go.mod/go.sum # Dependencies
│
├── Documentation
│ ├── README.md # This file
│ ├── QUICKSTART.md # 5-minute setup guide
│ ├── API.md # REST API reference (50+ examples)
│ ├── DEPLOYMENT.md # Production deployment guide
│ ├── INTEGRATION.md # Frontend integration guide
│ ├── OPTIMIZATION.md # Performance tuning guide
│
└── Tests
├── main_test.go # Integration tests
├── db_test.go # Database tests
├── server_test.go # API endpoint tests
└── ...
All configuration via environment variables (no config files needed):
# Server
SERVER_PORT=3000
SERVER_HOST=0.0.0.0
SERVER_READ_TIMEOUT=30s
SERVER_WRITE_TIMEOUT=30s
# Figma API
FIGMA_CLIENT_ID=your_client_id
FIGMA_CLIENT_SECRET=your_client_secret
FIGMA_REDIRECT_URI=http://localhost:3000/auth/callback
FIGMA_ACCESS_TOKEN=optional_personal_token
# Database
DATABASE_DSN=/app/data/capturecrafy.db
DATABASE_MAX_OPEN_CONNS=25
DATABASE_MAX_IDLE_CONNS=5
DATABASE_CONN_MAX_LIFETIME=5m
# Rate Limiting
RATE_LIMIT_ENABLED=true
RATE_LIMIT_RPM=600
RATE_LIMIT_WINDOW=1m
# Logging
LOG_LEVEL=info
LOG_FORMAT=text
# Sync Service
SYNC_ENABLED=true
SYNC_BATCH_SIZE=50
SYNC_INTERVAL=30s
SYNC_MAX_RETRIES=3
# Webhooks
WEBHOOK_SECRET=optional_secretSee .env.example for all available options.
docker build -t capturecrafy-api:latest .
docker run -d -p 3000:3000 \
-e FIGMA_ACCESS_TOKEN=your_token \
capturecrafy-api:latestkubectl apply -f k8s/deployment.yamldocker service create --name figma-api \
-p 3000:3000 \
-e FIGMA_ACCESS_TOKEN=your_token \
capturecrafy-api:latest# Build
go build -o figma-api main.go
# Run with systemd
sudo cp figma-api /usr/local/bin/
sudo tee /etc/systemd/system/figma-api.service > /dev/null <<EOF
[Unit]
Description=Figma API Server
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/figma-api
Restart=always
Environment="FIGMA_ACCESS_TOKEN=your_token"
EOF
# Enable and start
sudo systemctl enable figma-api
sudo systemctl start figma-apiSee DEPLOYMENT.md for comprehensive deployment guide.
# Run all tests
make test
# Run with coverage report
make coverage
# Run specific test
go test -run TestGetFile -v
# Run benchmarks
make bench
# Load test with Apache Bench
ab -n 1000 -c 100 http://localhost:3000/healthBenchmarks (on MacBook Pro M1, 16GB RAM):
| Operation | Latency | Memory |
|---|---|---|
| GET /health | < 1ms | < 0.1MB |
| GET /api/files/:key | 45-60ms | 2-3MB |
| GET /api/components/search | 80-120ms | 3-5MB |
| POST /api/exports/batch | 60-100ms | 5-8MB |
| Rate limit check | 0.5-1ms | < 0.05MB |
See OPTIMIZATION.md for detailed performance analysis and tuning guide.
- ✅ OAuth 2.0 for user authentication
- ✅ Rate limiting to prevent abuse
- ✅ HTTPS support (via reverse proxy/load balancer)
- ✅ Input validation on all endpoints
- ✅ SQL injection prevention (parameterized queries)
- ✅ CORS configuration per environment
- ✅ API key rotation support
- ✅ Encrypted token storage in database
The project also includes a comprehensive Go client library for direct Figma API integration.
go get github.com/zynorex/capturecrafy-apiconfig := &FigmaConfig{
ClientID: "YOUR_CLIENT_ID",
ClientSecret: "YOUR_CLIENT_SECRET",
RedirectURI: "http://localhost:3000/auth/callback",
}
client, err := NewFigmaClient(config)
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
// Get a file
file, err := client.GetFile(ctx, "fileKey")
if err != nil {
log.Fatal(err)
}
fmt.Println(file.Name)See Library section below for complete client documentation.
A comprehensive Go client for the Figma API, designed to communicate with the CaptureCraft application. This library provides full support for file access, component management, design exports, real-time webhooks, and more.
config := &FigmaConfig{
ClientID: "YOUR_CLIENT_ID",
ClientSecret: "YOUR_CLIENT_SECRET",
RedirectURI: "http://localhost:3000/auth/callback",
}
client, err := NewFigmaClient(config)
if err != nil {
log.Fatal(err)
}
// Get authorization URL
authURL := client.GetAuthURL("random-state")
// Direct user to authURL...
// After user authorizes, exchange code for token
token, err := client.ExchangeCodeForToken(context.Background(), code)ctx := context.Background()
// Get a file
file, err := client.GetFile(ctx, "fileKey")
if err != nil {
log.Fatal(err)
}
fmt.Println(file.Name)
fmt.Println(file.Document)// Get all components in a file
components, err := client.GetFileComponents(ctx, "fileKey")
if err != nil {
log.Fatal(err)
}
for key, component := range components {
fmt.Printf("%s: %s\n", key, component.Name)
}// Export as PNG
pngURL, err := client.ExportPNG(ctx, "fileKey", "nodeID")
if err != nil {
log.Fatal(err)
}
// Export as SVG
svgURL, err := client.ExportSVG(ctx, "fileKey", "nodeID")
// Export with custom scale
imageURL, err := client.GetNodeAsImageURL(ctx, "fileKey", "nodeID", ExportFormatPNG, 2.0)// Create a webhook
webhook, err := client.CreateWebhook(ctx, "teamID",
"https://yourapp.com/webhook", "FILE_UPDATE", "Listen for changes")
if err != nil {
log.Fatal(err)
}
// In your webhook handler
http.HandleFunc("/webhook", func(w http.ResponseWriter, r *http.Request) {
HandleWebhookRequest(r, "webhookSecret", func(event *WebhookEvent, err error) {
if err != nil {
http.Error(w, "Invalid webhook", http.StatusBadRequest)
return
}
// Process file update event
if event.Event == "FILE_UPDATE" {
fmt.Printf("File %s was updated at %d\n",
event.FileID, event.Timestamp)
}
})
})GetAuthURL(state string) string- Get OAuth authorization URLExchangeCodeForToken(ctx context.Context, code string) (*oauth2.Token, error)- Exchange auth code for tokenSetAccessToken(token string)- Set access token directly
GetFile(ctx, fileKey) (*File, error)- Get file by keyGetFileVersion(ctx, fileKey, versionID) (*File, error)- Get specific versionGetVersionHistory(ctx, fileKey) (*VersionHistory, error)- Get version historyGetTeamFiles(ctx, teamID) (*TeamFiles, error)- Get all team filesGetProjectFiles(ctx, projectID) (*ProjectFiles, error)- Get project filesGetFileNodes(ctx, fileKey, nodeIDs) (map[string]*Node, error)- Get specific nodesGetComments(ctx, fileKey) (*CommentThreads, error)- Get file commentsPostComment(ctx, fileKey, message, parentID) (*Comment, error)- Post commentResolveComment(ctx, fileKey, commentID) error- Mark comment as resolvedDeleteComment(ctx, fileKey, commentID) error- Delete comment
GetFileComponents(ctx, fileKey) (map[string]*Component, error)- Get all componentsGetComponent(ctx, componentKey) (*Component, error)- Get single componentGetComponentSets(ctx, fileKey) (map[string]*ComponentSet, error)- Get component setsGetComponentUsages(ctx, componentFileKey) (map[string][]string, error)- Get instancesGetTeamComponents(ctx, teamID) (map[string]*Component, error)- Get team componentsSearchComponents(ctx, teamID, query) (map[string]*Component, error)- Search componentsUpdateComponentDescription(ctx, componentKey, description) error- Update metadata
ExportSVG(ctx, fileKey, nodeID) (string, error)- Export as SVGExportPNG(ctx, fileKey, nodeID) (string, error)- Export as PNGExportJPG(ctx, fileKey, nodeID) (string, error)- Export as JPGExportPDF(ctx, fileKey, nodeID) (string, error)- Export as PDFGetNodeAsImageURL(ctx, fileKey, nodeID, format, scale) (string, error)- Export with scaleGetMultipleDesignExports(ctx, fileKey, nodeIDs, format) (*ImageExport, error)- Batch exportRenderImageTile(ctx, fileKey, nodeID, tileX, tileY, zLevel) (string, error)- Render tile
CreateWebhook(ctx, teamID, url, event, description) (*Webhook, error)- Create webhookListWebhooks(ctx, teamID) ([]*Webhook, error)- List webhooksGetWebhook(ctx, teamID, webhookID) (*Webhook, error)- Get webhookUpdateWebhook(ctx, teamID, webhookID, url, event) (*Webhook, error)- Update webhookDeleteWebhook(ctx, teamID, webhookID) error- Delete webhook
ColorToHex(color) string- Convert to hex colorColorToRGB(color) string- Convert to RGBColorToRGBA(color) string- Convert to RGBAExportNodeTree(node, results) []*Node- Flatten node treeFindNodeByName(root, name) *Node- Find node by nameFindNodeByID(root, id) *Node- Find node by IDGetNodePath(root, target) string- Get node pathFilterNodesByType(root, type) []*Node- Filter by typeGetBoundingBox(node) (minX, minY, maxX, maxY)- Calculate boundsCountNodesByType(root, type) int- Count nodes
File - Represents a Figma design file
type File struct {
Key string
Name string
LastModified string
ThumbnailURL string
Version string
Document *Node
Components map[string]*Component
ComponentSets map[string]*Component
Styles map[string]*Style
}Node - Represents an element in the design
type Node struct {
ID string
Name string
Type string
X, Y float64
Width, Height float64
Children []*Node
Fills []Paint
Strokes []Paint
Effects []Effect
// ... more properties
}Component - Represents a reusable component
type Component struct {
Key string
FileKey string
NodeID string
Name string
Description string
ThumbnailURL string
}WebhookEvent - Represents a webhook event
type WebhookEvent struct {
Event string
FileID string
FileKey string
Timestamp int64
VersionID string
InitiatedBy *User
Collections []Collection
LibraryChanges *LibraryChange
}Create a .env file:
FIGMA_CLIENT_ID=your_client_id
FIGMA_CLIENT_SECRET=your_client_secret
FIGMA_REDIRECT_URI=http://localhost:3000/auth/callback
FIGMA_ACCESS_TOKEN=optional_access_token
WEBHOOK_SECRET=your_webhook_secretSee examples.go for comprehensive examples including:
- OAuth flow
- File operations
- Component management
- Design exports
- Webhook setup
- Comment management
- Node tree navigation
- Color utilities
- Go to Figma Developer Settings
- Create a new app
- Copy your Client ID and Client Secret
- Set up OAuth redirect URI
- Use in your configuration
Supported webhook events:
FILE_UPDATE- File content was modifiedFILE_DELETE- File was deletedFILE_VERSION_UPDATE- New version createdLIBRARY_PUBLISH- Components published as library
All methods return errors for better error handling:
file, err := client.GetFile(ctx, "fileKey")
if err != nil {
switch err.(type) {
case *url.Error:
// Network error
default:
// API error or parsing error
}
}Figma API has rate limits. Implement exponential backoff:
retries := 3
backoff := time.Second
for i := 0; i < retries; i++ {
file, err := client.GetFile(ctx, fileKey)
if err == nil {
break
}
time.Sleep(backoff)
backoff *= 2
}- Cache tokens - Store OAuth tokens securely
- Use webhooks - Don't poll; use webhooks for updates
- Batch operations - Use batch export for multiple nodes
- Handle rate limits - Implement backoff strategies
- Verify signatures - Always verify webhook signatures
- Minimize exports - Export only needed formats/scales
Contributions are welcome! Please submit issues and pull requests.
MIT
For issues or questions:
- Check Figma API Documentation
- Review examples.go
- Open an issue on GitHub