'use client'; import { useState } from 'react'; export default function SetupPage() { const [tab, setTab] = useState<'github' | 'google' | 'apple' | 'env'>('github'); const [copied, setCopied] = useState(''); const copyToClipboard = (text: string, label: string) => { navigator.clipboard.writeText(text).then(() => { setCopied(label); setTimeout(() => setCopied(''), 2000); }).catch(() => { // Fallback const ta = document.createElement('textarea'); ta.value = text; document.body.appendChild(ta); ta.select(); document.execCommand('copy'); document.body.removeChild(ta); setCopied(label); setTimeout(() => setCopied(''), 2000); }); }; const tabs = [ { id: 'github' as const, label: 'GitHub', icon: '🐙' }, { id: 'google' as const, label: 'Google', icon: '🔵' }, { id: 'apple' as const, label: 'Apple', icon: '🍎' }, { id: 'env' as const, label: 'Apply', icon: '⚡' }, ]; return (

⚡ SSO Setup Guide

Create OAuth credentials for Google, Apple, and GitHub SSO. Each takes ~5 minutes.

{/* Tab bar */}
{tabs.map(t => ( ))}
{/* GitHub Tab */} {tab === 'github' && (

Create a GitHub OAuth App

Open this link in your browser:

Click "New OAuth App" button (top right).

Click "Register application".

You will see:

  • Client ID — copy this
  • Client Secret — click "Generate a new client secret" and copy it

Paste them below when you have them:

GITHUB_CLIENT_ID=your_client_id_here
GITHUB_CLIENT_SECRET=your_client_secret_here
"\nGITHUB_CLIENT_SECRET=""`} label="github-template" copied={copied} onCopy={copyToClipboard} />
)} {/* Google Tab */} {tab === 'google' && (

Create Google OAuth 2.0 Client

If you don't have a project, click "Create Project" and name it "FalahOS".

Click "OAuth consent screen" (left sidebar).

  • Choose External user type
  • App name: FalahOS
  • User support email: your email
  • Developer Contact: your email
  • Add scopes: email, profile, openid
  • Add test users: your email

Click "Create Credentials" → "OAuth client ID".

Click "Create" and copy the popup values:

GOOGLE_CLIENT_ID=xxxxxxxxx.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-xxxxxxxx
"\nGOOGLE_CLIENT_SECRET=""`} label="google-template" copied={copied} onCopy={copyToClipboard} />
)} {/* Apple Tab */} {tab === 'apple' && (

Set Up Sign In with Apple

⚠️ Requires an Apple Developer account ($99/year).

  • Click "+""Service IDs"
  • Description: FalahOS Auth
  • Identifier: com.falahos.auth
  • Click "Continue""Register"
  • Click on your new Service ID
  • Check "Sign in with Apple""Configure"
  • Select "Use as default" or create a new Service
  • Web Domain: falahos.my
  • Return URLs: https://falahos.my/mobile/api/auth/apple/callback
  • Click "Save"
  • Go to Keys"+"
  • Select "Sign in with Apple"
  • Configure with your Service ID
  • Download the .p8 key file
  • Note the Key ID
APPLE_CLIENT_ID=com.falahos.auth (your Service ID)
APPLE_CLIENT_SECRET= (generated JWT, not needed immediately)
)} {/* Apply Tab */} {tab === 'env' && (

Apply Credentials & Deploy

Once you have your credentials from all providers, paste them below and we'll configure the server.

)}

✅ Quick Summary

After creating all 3 OAuth apps, you'll have:

Contact me on Telegram with the values and I'll apply them instantly. Or use the SSH command below to configure yourself.

); } function Step({ number, title, children }: { number: number; title: string; children: React.ReactNode }) { return (
{number}

{title}

{children}
); } function FormField({ label, value }: { label: string; value: string }) { return (
{label}
{value}
); } function CodeBlock({ text, label, copied, onCopy }: { text: string; label: string; copied: string; onCopy: (text: string, label: string) => void; }) { return (
{text}
); } function CopyButton({ text, label, copied, onCopy }: { text: string; label: string; copied: string; onCopy: (text: string, label: string) => void; }) { return ( ); } function EnvForm() { const [ghId, setGhId] = useState(''); const [ghSecret, setGhSecret] = useState(''); const [glId, setGlId] = useState(''); const [glSecret, setGlSecret] = useState(''); const [apId, setApId] = useState(''); const [apSecret, setApSecret] = useState(''); const [submitted, setSubmitted] = useState(false); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); // Build the env var text for copying const text = `# Paste these into your VPS:\ncd /root/falah-mobile\ncat >> .env << 'EOF'\nGOOGLE_CLIENT_ID="${glId}"\nGOOGLE_CLIENT_SECRET="${glSecret}"\nAPPLE_CLIENT_ID="${apId}"\nAPPLE_CLIENT_SECRET="${apSecret}"\nGITHUB_CLIENT_ID="${ghId}"\nGITHUB_CLIENT_SECRET="${ghSecret}"\nEOF\ndocker compose up -d --build`; navigator.clipboard.writeText(text).then(() => { setSubmitted(true); setTimeout(() => setSubmitted(false), 3000); }).catch(() => setSubmitted(true)); }; return (

🐙 GitHub

🔵 Google

🍎 Apple

This copies the deployment command to your clipboard. Send it to me on Telegram and I'll run it on the VPS.

); } function InputField({ label, value, onChange, placeholder, secret }: { label: string; value: string; onChange: (v: string) => void; placeholder: string; secret?: boolean; }) { return (
{label}
onChange(e.target.value)} placeholder={placeholder} style={{ width: '100%', padding: '8px 10px', background: '#0a0a0a', border: '1px solid #333', borderRadius: '6px', fontSize: '14px', color: '#fff', fontFamily: 'monospace', outline: 'none', boxSizing: 'border-box', }} />
); }