Skip to content

magikrun/magik.run

Repository files navigation

Beemesh Portal

Lightweight SPA for managing Beemesh clusters. Designed for Cloudflare Pages hosting.

Tech Stack

  • Vite + React - Fast, lightweight build
  • TypeScript - Type safety
  • Tailwind CSS - Utility-first styling
  • Google OIDC (PKCE) - Secure auth without secrets

Architecture

┌─────────────────────┐         ┌─────────────────────┐
│  Cloudflare Pages   │         │    Machineplane     │
│  (Static SPA)       │◄───────►│    (REST API)       │
│                     │  JWT    │                     │
│  - React UI         │         │  - Validates token  │
│  - Google OAuth     │         │  - K8s-compatible   │
└─────────────────────┘         └─────────────────────┘

Local Development

# Install dependencies
npm install

# Start mock API server
npm run mock

# Start dev server (separate terminal)
npm run dev

Open http://localhost:3000 and use "Dev Login" (no Google OAuth needed).

Production Setup

1. Google OAuth Configuration

Create OAuth credentials at Google Cloud Console:

  1. Create OAuth 2.0 Client ID (Web application)
  2. Add authorized redirect URI: https://your-portal.pages.dev/auth/callback
  3. Copy the Client ID

2. Cloudflare Pages Deployment

# Build
npm run build

# Deploy via Cloudflare dashboard or CLI
npx wrangler pages deploy dist

Set environment variables in Cloudflare Pages:

  • VITE_GOOGLE_CLIENT_ID - Your Google OAuth Client ID
  • VITE_API_URL - Machineplane API endpoint

3. Machineplane CORS

Machineplane must allow requests from your portal domain:

Access-Control-Allow-Origin: https://your-portal.pages.dev
Access-Control-Allow-Headers: Authorization, Content-Type

Security

  • No secrets in SPA - Uses PKCE flow (public client)
  • JWT validation - Machineplane validates Google ID tokens
  • HTTPS only - Cloudflare enforces TLS
  • Security headers - CSP, X-Frame-Options via _headers

File Structure

portal/
├── public/
│   ├── _headers        # Cloudflare security headers
│   ├── _redirects      # SPA routing
│   └── beemesh.svg     # Logo
├── src/
│   ├── api/
│   │   └── client.ts   # API client with Bearer auth
│   ├── auth/
│   │   ├── AuthContext.tsx
│   │   ├── config.ts
│   │   ├── google.ts   # OIDC implementation
│   │   └── pkce.ts     # PKCE utilities
│   ├── components/
│   ├── pages/
│   ├── App.tsx
│   └── main.tsx
├── .env.example
├── package.json
└── vite.config.ts