Skip to content

Miosa-osa/whitelabel-react-python

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

White-label MIOSA Starter — React + FastAPI

Drop-in white-label SaaS starter built on MIOSA. Fork this repo to give your existing users sandboxed compute environments under your own brand — no MIOSA UI exposed, no infrastructure to manage. Shipping time: one afternoon.


Architecture

sequenceDiagram
    actor User as End-user browser
    participant FE as Your React frontend
    participant BE as Your FastAPI backend
    participant MIOSA as MIOSA API

    User->>FE: Visits your app (your domain, your brand)
    FE->>BE: POST /api/auth/login (your JWT auth)
    BE-->>FE: { access_token: "eyJ..." }

    User->>FE: Clicks "Open sandbox"
    FE->>BE: POST /api/sandboxes/{id}/preview-token
    note over BE,MIOSA: msk_* key stays server-side
    BE->>MIOSA: sandboxes.preview_token(id, expires_in=3600)
    MIOSA-->>BE: { value: "mp_...", expires_at }
    BE-->>FE: { token: "mp_...", expires_at }

    FE->>FE: <MiosaPreview token="mp_..." />
    note over FE,MIOSA: @miosa/react opens WebSocket using mp_* token
    FE-->>User: Live sandbox UI — your brand, your layout
Loading

The three rules this architecture enforces:

  1. The msk_* API key lives only in your FastAPI process. Never in the browser.
  2. Preview tokens (mp_*) are short-lived (1 h) and scoped to a single sandbox.
  3. Every MIOSA resource is tagged with external_user_id — your user, your data.

Quickstart

# 1. Clone and enter
git clone https://github.com/Miosa-osa/whitelabel-react-python
cd whitelabel-react-python

# 2. Copy env and fill in the 3 required values
cp .env.example .env
# Edit .env:
#   MIOSA_API_KEY  →  from miosa.app → Settings → API Keys
#   JWT_SECRET     →  python -c "import secrets; print(secrets.token_urlsafe(32))"
#   (MIOSA_WEBHOOK_SECRET is optional for local dev)

# 3. Start the stack
docker compose up

# 4. Open the app
open http://localhost:5173

FastAPI Swagger UI is at http://localhost:8000/docs — useful for exploring the API.


What you customize

What File Notes
Brand colors frontend/src/styles.css:root CSS vars Change --color-primary and friends
App name + logo frontend/public/logo.svg, frontend/index.html <title> Drop in your SVG
Auth provider backend/app/routes/auth.py Swap for Auth0/Clerk/Supabase
Sandbox images backend/app/routes/sandboxes.pyCreateSandboxRequest.image Expose your templates
Layout frontend/src/pages/Studio.tsx Rearrange the three panel components
Admin controls frontend/src/pages/Admin.tsx Show/hide tabs your users need
Database .envDATABASE_URL SQLite by default; swap for postgresql+asyncpg://

See docs/CUSTOMIZE.md for before/after code for each change.


Security model

Token hierarchy

msk_w_live_*          Master key — your server only, never browser
  └─ mp_preview_*     Short-lived (1 h), single sandbox — goes to browser
       └─ share_*     Read-only share links — optional, time-limited

Why this design

  • msk_* can create/delete sandboxes and list all tenant resources. Leaking it would compromise your entire tenant. It lives in your FastAPI process only.
  • mp_* tokens are minted on demand, scoped to one sandbox, and expire in 1 hour. Even if intercepted, blast radius is one sandbox for one hour.
  • Your JWT is separate from both MIOSA token types. MIOSA never sees your user credentials.

Webhook verification

MIOSA signs every webhook payload with HMAC-SHA256. The backend verifies the signature before trusting the event:

# backend/app/routes/webhooks.py
expected = hmac.new(settings.MIOSA_WEBHOOK_SECRET.encode(), body, hashlib.sha256).hexdigest()
if not hmac.compare_digest(f"sha256={expected}", x_miosa_signature):
    raise HTTPException(401, "bad signature")

Production deploy

Backend (FastAPI)

Render / Railway / Fly.io — simplest path:

# Render: set env vars in dashboard, point to ./backend, start command:
uvicorn app.main:app --host 0.0.0.0 --port $PORT

# Fly.io:
fly launch --dockerfile backend/Dockerfile
fly secrets set MIOSA_API_KEY=msk_w_live_... JWT_SECRET=...

Before going to production:

  • Replace SQLite with PostgreSQL: DATABASE_URL=postgresql+asyncpg://user:pass@host/db
  • Add Alembic migrations — remove create_all() from lifespan()
  • Add rate limiting (e.g., slowapi) to /api/auth/* endpoints
  • Enable HTTPS and set FRONTEND_ORIGIN to your production domain

Frontend (React/Vite)

Vercel — recommended:

cd frontend
vercel deploy
# Set VITE_API_BASE=https://your-api.onrender.com

Or build and serve static files:

cd frontend && npm run build
# Copy dist/ to any static host (Cloudflare Pages, S3, nginx)

In production, configure your reverse proxy (nginx/Caddy) to forward /api/* to your FastAPI backend instead of relying on Vite's dev proxy.


Common changes

See docs/CUSTOMIZE.md for detailed before/after code for:

  • Swapping auth to Auth0, Supabase, or Clerk
  • Adding a custom sandbox image / template
  • Migrating from Vite to Next.js App Router
  • Replacing FastAPI with Flask or Django
  • Adding managed databases or deployments from MIOSA
  • Multi-tenant subdomain routing

Project layout

.
├── .env.example                  # 5 vars — fill in 3, you're running
├── docker-compose.yml
├── backend/
│   ├── Dockerfile
│   ├── pyproject.toml
│   └── app/
│       ├── main.py               # FastAPI app + lifespan
│       ├── settings.py           # Pydantic settings from env
│       ├── deps.py               # current_user + miosa_client DI
│       ├── models.py             # ORM + Pydantic schemas
│       ├── database.py           # SQLAlchemy async engine
│       └── routes/
│           ├── auth.py           # /auth/login /auth/register /auth/me
│           ├── sandboxes.py      # CRUD scoped to current user
│           ├── tokens.py         # POST preview-token (ownership verified)
│           ├── shares.py         # POST share link
│           ├── usage.py          # GET /me/usage
│           ├── webhooks.py       # POST /webhooks/miosa (HMAC verified)
│           └── admin.py          # /admin/* tenant controls
├── frontend/
│   ├── Dockerfile
│   ├── nginx.conf
│   ├── vite.config.ts
│   ├── tsconfig.json
│   └── src/
│       ├── main.tsx
│       ├── App.tsx               # Router
│       ├── api.ts                # Typed client → YOUR backend only
│       ├── auth.tsx              # AuthContext (your JWT, not MIOSA)
│       ├── styles.css            # One file, easy to swap
│       └── pages/
│           ├── Login.tsx
│           ├── Login.test.tsx    # Component tests (vitest + RTL)
│           ├── Dashboard.tsx     # Sandbox list
│           ├── Studio.tsx        # MiosaPreview + MiosaTerminal + MiosaFileTree
│           └── Admin.tsx         # Tenant admin panel
└── docs/
    └── CUSTOMIZE.md

Development without Docker

# Backend
cd backend
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
cp ../.env.example .env  # fill in values
uvicorn app.main:app --reload

# Frontend (separate terminal)
cd frontend
npm install
npm run dev
# Vite proxies /api → http://localhost:8000

# Tests
cd backend && pytest tests/ -v
cd frontend && npm test

About

White-label MIOSA starter — React + FastAPI Lovable-style AI app builder with the MIOSA Agent. msk_* stays server-side; browser gets short-lived mp_* preview tokens.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors