'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:
- 🐙 GitHub: Client ID + Secret
- 🔵 Google: Client ID + Secret
- 🍎 Apple: Service ID (Client ID) + Key
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 (
);
}
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 (
);
}
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',
}}
/>
);
}