Admin Portal Setup Guide
Last Updated: 2026-01-27
This guide covers setting up and running the Lantern Admin Portal, an internal-only application for managing documentation and platform data.
Overview
The admin portal is a separate Vite + React application that:
- Uses Firebase Auth with admin role checking
- Links to StackEdit or GitHub.dev for markdown editing
- Edits sync directly to GitHub (no intermediate service)
- Deploys to
admin.ourlantern.app(prod) /admin.dev.ourlantern.app(dev)
Tech Stack:
- Vite + React (same as main app)
- StackEdit / GitHub.dev (external editors with GitHub integration)
- Firebase Auth (admin role required)
- Cloudflare Pages (admin portal deployment)
Quick Start (Local Development)
# From repo root
npm install
npm run admin:devThe admin portal runs on http://localhost:3001 (separate from main app on 3000).
Note: Uses the root .env.local file - same Firebase config as main app.
Architecture
admin/
├── src/
│ ├── App.jsx # Main app with auth flow
│ ├── firebase.js # Firebase config + admin role checking
│ ├── main.jsx # React entry point
│ ├── styles.css # Dark theme (matches main app)
│ └── components/
│ ├── AdminDashboard.jsx # Feature dashboard
│ ├── DocsEditor.jsx # Links to StackEdit/GitHub.dev
│ ├── LoadingScreen.jsx
│ ├── LoginScreen.jsx # Email/passphrase login
│ └── AccessDenied.jsx # Non-admin rejection
├── public/
│ ├── _headers # Cloudflare security headers
│ ├── _redirects # SPA routing
│ └── icons/ # App icons
├── vite.config.mjs # Uses root .env.local
└── package.json # Workspace packageAuthentication Flow
- User clicks "Sign in with GitHub"
- Firebase Auth redirects to GitHub OAuth
- On success, Firebase returns user + GitHub token
- App checks Firestore
users/{uid}forrole: 'admin' - If admin → show dashboard; else → show "Access Denied"
Setting Up Admin Users
To grant admin access, add role: 'admin' to the user's Firestore document:
// Firestore path: users/{userId}
{
email: "admin@example.com",
displayName: "Admin User",
role: "admin", // <-- This field grants admin access
// ... other fields
}You can do this via:
- Firebase Console → Firestore → users collection
- Firebase Admin SDK script
- The main app's user management (if implemented)
Documentation Editing
The admin portal provides links to external editors that integrate directly with GitHub. No self-hosted services required!
Editor Options
| Editor | Best For | Dark Mode | Setup |
|---|---|---|---|
| StackEdit | Non-technical users | ✅ | One-time GitHub link |
| GitHub.dev | Developers | ✅ | None (press . on GitHub) |
| GitHub | Quick edits | ✅ | None |
StackEdit Setup (One-time)
StackEdit is a WYSIWYG markdown editor with dark mode support.
Go to: https://stackedit.io/app
Click the folder icon in the sidebar
Click "Add a GitHub workspace"
Link your GitHub account if prompted
Configure:
Field Value Repository URL https://github.com/cattreedev/lantern_appBranch devPath docsClick OK - your docs folder will appear!
GitHub.dev (Zero Setup)
GitHub.dev is VS Code in your browser.
- Direct link: https://github.dev/cattreedev/lantern_app/tree/dev/docs
- Shortcut: Press
.on any GitHub page to open in github.dev - Use
Ctrl/Cmd + Shift + Vto preview markdown
How Changes Are Saved
- Edit a file in StackEdit or GitHub.dev
- Commit changes (both editors have commit UI)
- Changes go directly to the
devbranch - CI/CD automatically deploys updates
VitePress Integration
Documentation edits in /docs are used by VitePress to generate public documentation.
New Docs Not Appearing?
When you add a new page, VitePress needs to know about it:
If VitePress auto-discovers files:
- New
.mdfiles appear automatically on next build/deploy
If VitePress has manual sidebar config:
- Update
docs/.vitepress/config.jsto add new pages to navigation
Recommended Workflow
- Create/edit doc in StackEdit or GitHub.dev
- Commit changes to
devbranch - Update VitePress sidebar if needed (for new pages)
- CI/CD deploys automatically
Deployment
The admin portal is deployed automatically via GitHub Actions when changes are pushed to dev or main.
Cloudflare Pages Projects
| Environment | Project Name | URL |
|---|---|---|
| Development | lantern-admin-dev | admin.dev.ourlantern.app |
| Production | lantern-admin | admin.ourlantern.app |
Creating the Cloudflare Pages Project
If the project doesn't exist yet:
- Go to Cloudflare Dashboard → Pages → Create a project
- Select "Direct Upload" (we deploy via GitHub Actions)
- Name:
lantern-admin-dev(orlantern-adminfor prod) - Create project
- Go to Custom domains → Add:
admin.dev.ourlantern.app
Build Settings (If Using Git Integration)
If you connect via GitHub instead of "Direct Upload", use these settings:
| Setting | Value |
|---|---|
| Framework preset | Vite |
| Build command | npm run build |
| Build output directory | dist |
| Root directory | admin |
| Node.js version | 18 (or 20) |
Environment Variables (set in Cloudflare Pages Settings → Environment Variables):
| Variable | Description |
|---|---|
VITE_FIREBASE_API_KEY | Firebase API key |
VITE_FIREBASE_AUTH_DOMAIN | Firebase auth domain |
VITE_FIREBASE_PROJECT_ID | lantern-app-dev (dev) or lantern-app-prod (prod) |
VITE_FIREBASE_STORAGE_BUCKET | Firebase storage bucket |
VITE_FIREBASE_APP_ID | Firebase app ID |
VITE_RECAPTCHA_SITE_KEY | reCAPTCHA v3 site key for App Check (see Security Considerations) |
VITE_APP_ENV | development (dev) or production (prod) |
Note: We typically use "Direct Upload" with GitHub Actions for more control over the deploy process. The build settings above are for reference if connecting Cloudflare directly to GitHub.
Manual Build & Deploy
# Build
npm run admin:build
# Deploy (requires wrangler CLI + auth)
npx wrangler pages deploy admin/dist --project-name=lantern-admin-devSecurity Considerations
Firebase App Check (reCAPTCHA v3)
The admin portal uses Firebase App Check with reCAPTCHA v3 to verify that requests to Cloud Functions come from legitimate app instances, not from attackers using stolen API keys.
How It Works
- When the admin portal loads, App Check obtains a reCAPTCHA token from Google
- This token is automatically attached to all Firebase callable function requests
- Cloud Functions verify the token via
consumeAppCheckToken: trueoption - Requests without valid tokens are rejected
reCAPTCHA v3 Setup
Step 1: Create reCAPTCHA Keys
- Go to Google reCAPTCHA Admin Console
- Click Create (+ icon)
- Configure:
- Label:
Lantern Admin Portal - reCAPTCHA type: reCAPTCHA v3 (score-based, invisible)
- Domains: Add all domains where the admin portal runs:
localhostweb.app(covers Firebase preview URLs like*.web.app)admin.ourlantern.appadmin.dev.ourlantern.appourlantern.app
- Label:
- Accept Terms of Service and click Submit
- Copy the Site Key and Secret Key
Step 2: Register App Check Provider in Firebase
- Go to Firebase Console → Your Project
- Navigate to Build → App Check
- Click on your Web app
- Select reCAPTCHA v3 as the provider
- Paste the Secret Key from Step 1
- Click Save
Step 3: Configure Environment Variables
For local development, add to admin/.env.local:
VITE_RECAPTCHA_SITE_KEY=your-recaptcha-site-key-hereFor GitHub Actions deployments, add repository secrets:
| Secret Name | Description |
|---|---|
VITE_RECAPTCHA_SITE_KEY_DEV | reCAPTCHA site key for dev environment |
VITE_RECAPTCHA_SITE_KEY_PROD | reCAPTCHA site key for prod environment |
Go to: GitHub → Repository → Settings → Secrets and variables → Actions → New repository secret
Note: You can use the same reCAPTCHA site key for both dev and prod if all domains are registered, or create separate reCAPTCHA entries for each environment.
Verifying App Check is Working
- Open browser DevTools → Network tab
- Trigger a Cloud Function call (e.g., create admin user)
- Look for the request to your function
- The request headers should include
X-Firebase-AppCheck
If App Check is misconfigured, you'll see errors like:
AppCheck: ReCAPTCHA error- Domain not registered in reCAPTCHA consoleUNAUTHENTICATED- App Check token missing or invalid on server
Cloud Functions Configuration
All admin Cloud Functions have App Check enabled via:
const callableOptions = {
cors: [...],
invoker: 'public',
consumeAppCheckToken: true // Requires valid App Check token
};Access Control
- Firebase Auth - User must be signed in to admin portal
- Admin Role Check - User must have
role: 'admin'in Firestore - GitHub Auth - StackEdit/GitHub.dev use GitHub OAuth
- No Public Links - Admin portal is never linked from the main app
Headers & CSP
The admin/public/_headers file sets security headers:
X-Frame-Options: DENY
X-Robots-Tag: noindex, nofollow
Content-Security-Policy: ...Preventing Public Access
- Admin portal:
X-Robots-Tag: noindex, nofollow - Docs editing: Requires GitHub account with repo access
- No links from main app or public documentation
Troubleshooting
Admin Portal Issues
"Access Denied" even though I'm an admin
Check that your Firestore user document has role: "admin" (exact string match).
Admin portal won't load
- Check browser console for errors
- Verify Firebase config is correct
- Check that the deployment has the right environment variables
StackEdit Issues
Can't connect to GitHub
- Make sure you've authorized StackEdit for your GitHub account
- Check that your GitHub account has access to the repository
- Try unlinking and re-linking your GitHub account
Changes not saving
- Make sure you've committed your changes (click the sync icon)
- Check that you have write access to the repository
- Verify the branch name is correct (
dev)
Future Expansion (Phase 3)
The admin dashboard is designed for expansion. Future features may include:
- 📊 Analytics Dashboard - Firebase Analytics integration
- 🏪 Merchant Management - View/approve merchant applications
- 👥 User Management - View, disable, delete users
- 🔧 System Health - Service status monitoring
- 💡 Feature Tracker - GitHub issues integration
These features are marked as "Coming Soon" in the dashboard.
Related Documentation
- SCAFFOLD.md - Project architecture overview
- ENVIRONMENT_SETUP.md - Environment configuration
- GitHub Actions Workflows - CI/CD configuration
- StackEdit - StackEdit documentation
- GitHub.dev - VS Code in browser