Compare commits
11 commits
main
...
content-de
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0e605c10d4 | ||
|
|
dff8b2ecb1 | ||
|
|
4216430546 | ||
|
|
07dd8be820 | ||
|
|
e19d4ba859 | ||
|
|
b80c0c5d19 | ||
|
|
28d9410a9f | ||
|
|
e6b1617b43 | ||
|
|
e633079933 | ||
|
|
5a9487f148 | ||
|
|
859f69a245 |
102
README.md
|
|
@ -1,45 +1,54 @@
|
|||
# AeThex Forge - Local Development Setup
|
||||
# AeThex Forge – Local Development Setup
|
||||
|
||||
## Quick Start Guide
|
||||
|
||||
This guide will help you set up and run the AeThex platform locally on your machine.
|
||||
This guide will help you set up and run the AeThex Developer Platform locally.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. **Node.js** (v18 or higher)
|
||||
- Download from: https://nodejs.org/
|
||||
- This will also install npm (Node Package Manager)
|
||||
- [Download Node.js](https://nodejs.org/)
|
||||
- Includes npm (Node Package Manager)
|
||||
|
||||
2. **Git** (optional, if you want to clone updates)
|
||||
- Download from: https://git-scm.com/
|
||||
2. **Git** (recommended for updates)
|
||||
- [Download Git](https://git-scm.com/)
|
||||
|
||||
## Installation Steps
|
||||
|
||||
### 1. Install Node.js
|
||||
- Visit https://nodejs.org/ and download the LTS version
|
||||
- Run the installer and follow the setup wizard
|
||||
- Restart your terminal/PowerShell after installation
|
||||
|
||||
- Download and install the LTS version from [nodejs.org](https://nodejs.org/)
|
||||
- Follow the setup wizard
|
||||
- Restart your terminal after installation
|
||||
|
||||
### 2. Verify Installation
|
||||
Open PowerShell or Command Prompt and run:
|
||||
```powershell
|
||||
|
||||
Open your terminal and run:
|
||||
|
||||
```bash
|
||||
node --version
|
||||
npm --version
|
||||
```
|
||||
|
||||
You should see version numbers (e.g., v20.x.x and 10.x.x)
|
||||
|
||||
### 3. Install Project Dependencies
|
||||
|
||||
Navigate to the project folder and install dependencies:
|
||||
```powershell
|
||||
cd C:\Users\PCOEM\Downloads\aethex-forge\aethex-forge
|
||||
|
||||
```bash
|
||||
cd /path/to/aethex-forge
|
||||
npm install
|
||||
```
|
||||
|
||||
This may take a few minutes as it downloads all required packages.
|
||||
|
||||
### 4. Set Up Environment Variables
|
||||
Create a `.env` file in the root directory (`aethex-forge` folder) with the following variables:
|
||||
|
||||
Create a `.env` file in the root directory (`aethex-forge/`) with the following variables:
|
||||
|
||||
**Minimum Required (to run the app):**
|
||||
|
||||
```env
|
||||
# Supabase Configuration (Required)
|
||||
VITE_SUPABASE_URL=your_supabase_url_here
|
||||
|
|
@ -52,6 +61,7 @@ VITE_API_BASE=http://localhost:5000
|
|||
```
|
||||
|
||||
**Optional (for full functionality):**
|
||||
|
||||
```env
|
||||
# Discord Integration
|
||||
DISCORD_CLIENT_ID=your_discord_client_id
|
||||
|
|
@ -76,54 +86,59 @@ VITE_GHOST_API_URL=your_ghost_api_url
|
|||
GHOST_ADMIN_API_KEY=your_ghost_admin_key
|
||||
```
|
||||
|
||||
**Note:** You can start with just the Supabase variables to get the app running. Other features will work once you add their respective credentials.
|
||||
**Note:** You can start with just the Supabase variables to get the app running. Add other credentials as needed for full functionality.
|
||||
|
||||
### 5. Run the Development Server
|
||||
```powershell
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
The application will start on **http://localhost:5000**
|
||||
The application will start on **[http://localhost:5000](http://localhost:5000)** (or the port set in your config).
|
||||
|
||||
Open your browser and navigate to that URL to view the application.
|
||||
|
||||
## Available Commands
|
||||
|
||||
- `npm run dev` - Start development server (port 5000)
|
||||
- `npm run build` - Build for production
|
||||
- `npm start` - Start production server
|
||||
- `npm run typecheck` - Check TypeScript types
|
||||
- `npm test` - Run tests
|
||||
- `npm run dev` – Start development server (default: port 5000)
|
||||
- `npm run build` – Build for production
|
||||
- `npm start` – Start production server
|
||||
- `npm run typecheck` – Check TypeScript types
|
||||
- `npm test` – Run tests
|
||||
|
||||
aethex-forge/
|
||||
aethex-forge/
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
```text
|
||||
aethex-forge/
|
||||
├── client/ # React frontend (pages, components)
|
||||
├── client/ # React SPA frontend (pages, components, UI)
|
||||
├── server/ # Express backend API
|
||||
├── api/ # API route handlers
|
||||
├── shared/ # Shared types between client/server
|
||||
├── discord-bot/ # Discord bot integration
|
||||
└── supabase/ # Database migrations
|
||||
├── api/ # API route handlers (modular)
|
||||
├── shared/ # Shared types/interfaces (client/server)
|
||||
├── supabase/ # Database migrations & SQL
|
||||
├── docs/ # Project documentation
|
||||
└── ... # Other supporting folders
|
||||
```
|
||||
|
||||
## Getting Supabase Credentials
|
||||
|
||||
If you don't have Supabase credentials yet:
|
||||
|
||||
1. Go to https://supabase.com/
|
||||
2. Create a free account
|
||||
3. Create a new project
|
||||
4. Go to Project Settings → API
|
||||
5. Copy:
|
||||
1. Go to [supabase.com](https://supabase.com/)
|
||||
2. Create a free account and project
|
||||
3. In your project, go to **Settings → API**
|
||||
4. Copy:
|
||||
- Project URL → `VITE_SUPABASE_URL` and `SUPABASE_URL`
|
||||
- `anon` `public` key → `VITE_SUPABASE_ANON_KEY`
|
||||
- `service_role` `secret` key → `SUPABASE_SERVICE_ROLE`
|
||||
- `anon` public key → `VITE_SUPABASE_ANON_KEY`
|
||||
- `service_role` secret key → `SUPABASE_SERVICE_ROLE`
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Port Already in Use
|
||||
|
||||
If port 5000 is already in use, you can change it in `vite.config.ts`:
|
||||
|
||||
```typescript
|
||||
server: {
|
||||
port: 5001, // Change to any available port
|
||||
|
|
@ -131,21 +146,24 @@ server: {
|
|||
```
|
||||
|
||||
### Module Not Found Errors
|
||||
|
||||
Try deleting `node_modules` and `package-lock.json`, then run `npm install` again:
|
||||
```powershell
|
||||
Remove-Item -Recurse -Force node_modules
|
||||
Remove-Item package-lock.json
|
||||
|
||||
```bash
|
||||
rm -rf node_modules package-lock.json
|
||||
npm install
|
||||
```
|
||||
|
||||
### Environment Variables Not Loading
|
||||
- Make sure `.env` file is in the root `aethex-forge` directory
|
||||
|
||||
- Ensure `.env` is in the root `aethex-forge` directory
|
||||
- Restart the dev server after adding new environment variables
|
||||
- Variables starting with `VITE_` are exposed to the client
|
||||
|
||||
## Need Help?
|
||||
|
||||
- Check the `docs/` folder for detailed documentation
|
||||
- Review `AGENTS.md` for architecture details
|
||||
- See `replit.md` for deployment information
|
||||
- See the `docs/` folder for detailed documentation
|
||||
- Review `AGENTS.md` for architecture and tech stack
|
||||
- See `replit.md` for cloud deployment info
|
||||
- For advanced troubleshooting, check `DEPLOYMENT_CHECKLIST.md` and `PHASE1_IMPLEMENTATION_SUMMARY.md`
|
||||
|
||||
|
|
|
|||
BIN
aethex-dev-docs.zip
Normal file
BIN
aethex-logos.zip
Normal file
BIN
aethex-logos/arms/corp-512.png
Normal file
|
After Width: | Height: | Size: 221 KiB |
BIN
aethex-logos/arms/devlink-512.png
Normal file
|
After Width: | Height: | Size: 197 KiB |
BIN
aethex-logos/arms/foundation-512.png
Normal file
|
After Width: | Height: | Size: 266 KiB |
BIN
aethex-logos/arms/gameforge-512.png
Normal file
|
After Width: | Height: | Size: 183 KiB |
BIN
aethex-logos/arms/labs-512.png
Normal file
|
After Width: | Height: | Size: 282 KiB |
BIN
aethex-logos/arms/nexus-512.png
Normal file
|
After Width: | Height: | Size: 202 KiB |
BIN
aethex-logos/arms/staff-512.png
Normal file
|
After Width: | Height: | Size: 267 KiB |
BIN
aethex-logos/icons/1024x1024.png
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
aethex-logos/icons/128x128.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
aethex-logos/icons/16x16.png
Normal file
|
After Width: | Height: | Size: 491 B |
BIN
aethex-logos/icons/256x256.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
aethex-logos/icons/32x32.png
Normal file
|
After Width: | Height: | Size: 1,021 B |
BIN
aethex-logos/icons/48x48.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
aethex-logos/icons/512x512.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
aethex-logos/icons/64x64.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
aethex-logos/icons/favicon.ico
Normal file
|
After Width: | Height: | Size: 9.3 KiB |
BIN
aethex-logos/icons/icon.ico
Normal file
|
After Width: | Height: | Size: 111 KiB |
16
aethex-logos/icons/icon.svg
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512">
|
||||
<defs>
|
||||
<linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#1e3a5f;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#0f172a;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient id="accent" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#3b82f6;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#8b5cf6;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="512" height="512" rx="80" fill="url(#bg)"/>
|
||||
<path d="M256 100 L380 380 L256 320 L132 380 Z" fill="url(#accent)" opacity="0.9"/>
|
||||
<path d="M256 140 L350 340 L256 295 L162 340 Z" fill="#0f172a" opacity="0.3"/>
|
||||
<circle cx="256" cy="220" r="30" fill="#fff" opacity="0.9"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 861 B |
BIN
aethex-logos/main/aethex-logo-1200.png
Normal file
|
After Width: | Height: | Size: 887 KiB |
BIN
aethex-logos/main/aethex-logo-512.png
Normal file
|
After Width: | Height: | Size: 222 KiB |
|
|
@ -13,11 +13,9 @@ export default async function handler(req: any, res: any) {
|
|||
if (method === "GET") {
|
||||
const { user_id, project_id, role, limit = 50, offset = 0 } = query;
|
||||
|
||||
// Fix: Use correct join syntax for Supabase/Postgres foreign table
|
||||
let dbQuery = supabase.from("gameforge_team_members").select(
|
||||
`
|
||||
*,
|
||||
user_profiles(id, full_name, avatar_url, email)
|
||||
`,
|
||||
`*,user_profiles:users(id, full_name, avatar_url, email)`,
|
||||
{ count: "exact" },
|
||||
);
|
||||
|
||||
|
|
@ -30,7 +28,10 @@ export default async function handler(req: any, res: any) {
|
|||
.order("joined_date", { ascending: false })
|
||||
.range(Number(offset), Number(offset) + Number(limit) - 1);
|
||||
|
||||
if (error) throw error;
|
||||
if (error) {
|
||||
console.error("[GameForge Team SQL]", error);
|
||||
throw error;
|
||||
}
|
||||
return res.json({
|
||||
data: user_id ? data : data,
|
||||
total: count,
|
||||
|
|
|
|||
|
|
@ -16,10 +16,15 @@ export default async (req: Request) => {
|
|||
return new Response("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
||||
// Pagination support
|
||||
const url = new URL(req.url);
|
||||
const limit = Math.max(1, Math.min(100, parseInt(url.searchParams.get("limit") || "50")));
|
||||
const offset = Math.max(0, parseInt(url.searchParams.get("offset") || "0"));
|
||||
|
||||
const start = Date.now();
|
||||
const { data: directory, error } = await supabase
|
||||
.from("staff_members")
|
||||
.select(
|
||||
`
|
||||
.select(`
|
||||
id,
|
||||
user_id,
|
||||
full_name,
|
||||
|
|
@ -32,9 +37,11 @@ export default async (req: Request) => {
|
|||
location,
|
||||
username,
|
||||
created_at
|
||||
`,
|
||||
)
|
||||
.order("full_name", { ascending: true });
|
||||
`)
|
||||
.order("full_name", { ascending: true })
|
||||
.range(offset, offset + limit - 1);
|
||||
const elapsed = Date.now() - start;
|
||||
console.log(`[staff/directory] Query took ${elapsed}ms (limit=${limit}, offset=${offset})`);
|
||||
|
||||
if (error) {
|
||||
console.error("Directory fetch error:", error);
|
||||
|
|
|
|||
|
|
@ -16,10 +16,15 @@ export default async (req: Request) => {
|
|||
return new Response("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
||||
// Add a limit to prevent timeouts
|
||||
const url = new URL(req.url);
|
||||
const limit = Math.max(1, Math.min(100, parseInt(url.searchParams.get("limit") || "50")));
|
||||
const offset = Math.max(0, parseInt(url.searchParams.get("offset") || "0"));
|
||||
|
||||
const start = Date.now();
|
||||
const { data: invoices, error } = await supabase
|
||||
.from("contractor_invoices")
|
||||
.select(
|
||||
`
|
||||
.select(`
|
||||
id,
|
||||
user_id,
|
||||
invoice_number,
|
||||
|
|
@ -29,10 +34,12 @@ export default async (req: Request) => {
|
|||
due_date,
|
||||
description,
|
||||
created_at
|
||||
`,
|
||||
)
|
||||
`)
|
||||
.eq("user_id", userData.user.id)
|
||||
.order("date", { ascending: false });
|
||||
.order("date", { ascending: false })
|
||||
.range(offset, offset + limit - 1);
|
||||
const elapsed = Date.now() - start;
|
||||
console.log(`[staff/invoices] Query took ${elapsed}ms (limit=${limit}, offset=${offset})`);
|
||||
|
||||
if (error) {
|
||||
console.error("Invoices fetch error:", error);
|
||||
|
|
|
|||
|
|
@ -16,10 +16,10 @@ export default async (req: Request) => {
|
|||
return new Response("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
||||
const start = Date.now();
|
||||
const { data: staffMember, error } = await supabase
|
||||
.from("staff_members")
|
||||
.select(
|
||||
`
|
||||
.select(`
|
||||
id,
|
||||
user_id,
|
||||
full_name,
|
||||
|
|
@ -31,10 +31,11 @@ export default async (req: Request) => {
|
|||
salary,
|
||||
avatar_url,
|
||||
created_at
|
||||
`,
|
||||
)
|
||||
`)
|
||||
.eq("user_id", userData.user.id)
|
||||
.single();
|
||||
const elapsed = Date.now() - start;
|
||||
console.log(`[staff/me] Query took ${elapsed}ms`);
|
||||
|
||||
if (error && error.code !== "PGRST116") {
|
||||
console.error("Staff member fetch error:", error);
|
||||
|
|
|
|||
|
|
@ -16,10 +16,15 @@ export default async (req: Request) => {
|
|||
return new Response("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
||||
// Add a limit to prevent timeouts
|
||||
const url = new URL(req.url);
|
||||
const limit = Math.max(1, Math.min(100, parseInt(url.searchParams.get("limit") || "50")));
|
||||
const offset = Math.max(0, parseInt(url.searchParams.get("offset") || "0"));
|
||||
|
||||
const start = Date.now();
|
||||
const { data: okrs, error } = await supabase
|
||||
.from("staff_okrs")
|
||||
.select(
|
||||
`
|
||||
.select(`
|
||||
id,
|
||||
user_id,
|
||||
objective,
|
||||
|
|
@ -34,10 +39,12 @@ export default async (req: Request) => {
|
|||
target_value
|
||||
),
|
||||
created_at
|
||||
`,
|
||||
)
|
||||
`)
|
||||
.eq("user_id", userData.user.id)
|
||||
.order("created_at", { ascending: false });
|
||||
.order("created_at", { ascending: false })
|
||||
.range(offset, offset + limit - 1);
|
||||
const elapsed = Date.now() - start;
|
||||
console.log(`[staff/okrs] Query took ${elapsed}ms (limit=${limit}, offset=${offset})`);
|
||||
|
||||
if (error) {
|
||||
console.error("OKRs fetch error:", error);
|
||||
|
|
|
|||
|
|
@ -56,6 +56,11 @@ import GameJoltIntegration from "./pages/docs/integrations/GameJolt";
|
|||
import ItchIoIntegration from "./pages/docs/integrations/ItchIo";
|
||||
import DocsCurriculum from "./pages/docs/DocsCurriculum";
|
||||
import DocsCurriculumEthos from "./pages/docs/DocsCurriculumEthos";
|
||||
import DocsLangOverview from "./pages/docs/lang/DocsLangOverview";
|
||||
import DocsLangQuickstart from "./pages/docs/lang/DocsLangQuickstart";
|
||||
import DocsLangSyntax from "./pages/docs/lang/DocsLangSyntax";
|
||||
import DocsLangCli from "./pages/docs/lang/DocsLangCli";
|
||||
import DocsLangExamples from "./pages/docs/lang/DocsLangExamples";
|
||||
import EthosGuild from "./pages/community/EthosGuild";
|
||||
import TrackLibrary from "./pages/ethos/TrackLibrary";
|
||||
import ArtistProfile from "./pages/ethos/ArtistProfile";
|
||||
|
|
@ -179,6 +184,7 @@ import MarketplaceItemDetail from "./pages/dev-platform/MarketplaceItemDetail";
|
|||
import CodeExamples from "./pages/dev-platform/CodeExamples";
|
||||
import ExampleDetail from "./pages/dev-platform/ExampleDetail";
|
||||
import DeveloperPlatform from "./pages/dev-platform/DeveloperPlatform";
|
||||
import AethexLang from "./pages/dev-platform/AethexLang";
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
|
|
@ -663,6 +669,12 @@ const App = () => (
|
|||
path="integrations/itchio"
|
||||
element={<ItchIoIntegration />}
|
||||
/>
|
||||
{/* AeThex Language Docs */}
|
||||
<Route path="lang" element={<DocsLangOverview />} />
|
||||
<Route path="lang/quickstart" element={<DocsLangQuickstart />} />
|
||||
<Route path="lang/syntax" element={<DocsLangSyntax />} />
|
||||
<Route path="lang/cli" element={<DocsLangCli />} />
|
||||
<Route path="lang/examples" element={<DocsLangExamples />} />
|
||||
</Route>
|
||||
<Route path="/tutorials" element={<Tutorials />} />
|
||||
<Route path="/community/*" element={<Community />} />
|
||||
|
|
@ -891,6 +903,7 @@ const App = () => (
|
|||
<Route path="/dev-platform/marketplace/:id" element={<MarketplaceItemDetail />} />
|
||||
<Route path="/dev-platform/examples" element={<CodeExamples />} />
|
||||
<Route path="/dev-platform/examples/:id" element={<ExampleDetail />} />
|
||||
<Route path="/lang" element={<AethexLang />} />
|
||||
|
||||
{/* Explicit 404 route for static hosting fallbacks */}
|
||||
<Route path="/404" element={<FourOhFourPage />} />
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import { Button } from "@/components/ui/button";
|
|||
import { Badge } from "@/components/ui/badge";
|
||||
import {
|
||||
Music,
|
||||
Toggle,
|
||||
ToggleLeft,
|
||||
ToggleRight,
|
||||
ExternalLink,
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ const BlogEditor = ({ onPublish, initialData }: BlogEditorProps) => {
|
|||
|
||||
const handlePublish = async () => {
|
||||
if (!title.trim() || !html.trim()) {
|
||||
toast.error("Title and body are required");
|
||||
toast.error({ title: "Title and body are required" });
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -95,7 +95,7 @@ const BlogEditor = ({ onPublish, initialData }: BlogEditorProps) => {
|
|||
}
|
||||
|
||||
const data = await response.json();
|
||||
toast.success(`Post published: ${data.url}`);
|
||||
toast.success({ title: `Post published: ${data.url}` });
|
||||
onPublish?.(true);
|
||||
|
||||
// Reset form
|
||||
|
|
@ -108,7 +108,7 @@ const BlogEditor = ({ onPublish, initialData }: BlogEditorProps) => {
|
|||
setMetaTitle("");
|
||||
setMetaDescription("");
|
||||
} catch (error: any) {
|
||||
toast.error(error.message || "Failed to publish post");
|
||||
toast.error({ title: error.message || "Failed to publish post" });
|
||||
onPublish?.(false);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ export default function AdminFoundationManager() {
|
|||
const data = await response.json();
|
||||
setMentors(data || []);
|
||||
} catch (error) {
|
||||
aethexToast.error("Failed to load mentors");
|
||||
aethexToast.error({ title: "Failed to load mentors" });
|
||||
console.error(error);
|
||||
} finally {
|
||||
setLoadingMentors(false);
|
||||
|
|
@ -116,7 +116,7 @@ export default function AdminFoundationManager() {
|
|||
const data = await response.json();
|
||||
setCourses(data || []);
|
||||
} catch (error) {
|
||||
aethexToast.error("Failed to load courses");
|
||||
aethexToast.error({ title: "Failed to load courses" });
|
||||
console.error(error);
|
||||
} finally {
|
||||
setLoadingCourses(false);
|
||||
|
|
@ -133,7 +133,7 @@ export default function AdminFoundationManager() {
|
|||
const data = await response.json();
|
||||
setAchievements(data || []);
|
||||
} catch (error) {
|
||||
aethexToast.error("Failed to load achievements");
|
||||
aethexToast.error({ title: "Failed to load achievements" });
|
||||
console.error(error);
|
||||
} finally {
|
||||
setLoadingAchievements(false);
|
||||
|
|
@ -154,14 +154,14 @@ export default function AdminFoundationManager() {
|
|||
);
|
||||
|
||||
if (!response.ok) throw new Error("Failed to update mentor");
|
||||
aethexToast.success(
|
||||
`Mentor ${approvalAction === "approve" ? "approved" : "rejected"}`,
|
||||
);
|
||||
aethexToast.success({
|
||||
title: `Mentor ${approvalAction === "approve" ? "approved" : "rejected"}`,
|
||||
});
|
||||
setApprovalDialogOpen(false);
|
||||
setSelectedMentor(null);
|
||||
fetchMentors();
|
||||
} catch (error) {
|
||||
aethexToast.error("Failed to update mentor");
|
||||
aethexToast.error({ title: "Failed to update mentor" });
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
|
@ -178,10 +178,10 @@ export default function AdminFoundationManager() {
|
|||
);
|
||||
|
||||
if (!response.ok) throw new Error("Failed to update course");
|
||||
aethexToast.success(`Course ${publish ? "published" : "unpublished"}`);
|
||||
aethexToast.success({ title: `Course ${publish ? "published" : "unpublished"}` });
|
||||
fetchCourses();
|
||||
} catch (error) {
|
||||
aethexToast.error("Failed to update course");
|
||||
aethexToast.error({ title: "Failed to update course" });
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
|
@ -196,10 +196,10 @@ export default function AdminFoundationManager() {
|
|||
);
|
||||
|
||||
if (!response.ok) throw new Error("Failed to delete course");
|
||||
aethexToast.success("Course deleted");
|
||||
aethexToast.success({ title: "Course deleted" });
|
||||
fetchCourses();
|
||||
} catch (error) {
|
||||
aethexToast.error("Failed to delete course");
|
||||
aethexToast.error({ title: "Failed to delete course" });
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ export default function AdminNexusManager() {
|
|||
const data = await response.json();
|
||||
setOpportunities(data || []);
|
||||
} catch (error) {
|
||||
aethexToast.error("Failed to load opportunities");
|
||||
aethexToast.error({ title: "Failed to load opportunities" });
|
||||
console.error(error);
|
||||
} finally {
|
||||
setLoadingOpp(false);
|
||||
|
|
@ -120,7 +120,7 @@ export default function AdminNexusManager() {
|
|||
const data = await response.json();
|
||||
setDisputes(data || []);
|
||||
} catch (error) {
|
||||
aethexToast.error("Failed to load disputes");
|
||||
aethexToast.error({ title: "Failed to load disputes" });
|
||||
console.error(error);
|
||||
} finally {
|
||||
setLoadingDisputes(false);
|
||||
|
|
@ -135,7 +135,7 @@ export default function AdminNexusManager() {
|
|||
const data = await response.json();
|
||||
setCommissions(data || []);
|
||||
} catch (error) {
|
||||
aethexToast.error("Failed to load commissions");
|
||||
aethexToast.error({ title: "Failed to load commissions" });
|
||||
console.error(error);
|
||||
} finally {
|
||||
setLoadingCommissions(false);
|
||||
|
|
@ -157,10 +157,10 @@ export default function AdminNexusManager() {
|
|||
);
|
||||
|
||||
if (!response.ok) throw new Error("Failed to update opportunity");
|
||||
aethexToast.success(`Opportunity marked as ${status}`);
|
||||
aethexToast.success({ title: `Opportunity marked as ${status}` });
|
||||
fetchOpportunities();
|
||||
} catch (error) {
|
||||
aethexToast.error("Failed to update opportunity");
|
||||
aethexToast.error({ title: "Failed to update opportunity" });
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
|
@ -180,12 +180,12 @@ export default function AdminNexusManager() {
|
|||
);
|
||||
|
||||
if (!response.ok) throw new Error("Failed to update opportunity");
|
||||
aethexToast.success(
|
||||
`Opportunity ${featured ? "featured" : "unfeatured"}`,
|
||||
);
|
||||
aethexToast.success({
|
||||
title: `Opportunity ${featured ? "featured" : "unfeatured"}`,
|
||||
});
|
||||
fetchOpportunities();
|
||||
} catch (error) {
|
||||
aethexToast.error("Failed to update opportunity");
|
||||
aethexToast.error({ title: "Failed to update opportunity" });
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
|
@ -207,15 +207,15 @@ export default function AdminNexusManager() {
|
|||
);
|
||||
|
||||
if (!response.ok) throw new Error("Failed to update dispute");
|
||||
aethexToast.success(
|
||||
`Dispute ${disputeAction === "resolve" ? "resolved" : "escalated"}`,
|
||||
);
|
||||
aethexToast.success({
|
||||
title: `Dispute ${disputeAction === "resolve" ? "resolved" : "escalated"}`,
|
||||
});
|
||||
setDisputeDialogOpen(false);
|
||||
setSelectedDispute(null);
|
||||
setDisputeResolution("");
|
||||
fetchDisputes();
|
||||
} catch (error) {
|
||||
aethexToast.error("Failed to update dispute");
|
||||
aethexToast.error({ title: "Failed to update dispute" });
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,20 +12,20 @@ export default function MaintenanceToggle() {
|
|||
|
||||
const handleToggle = async () => {
|
||||
if (!canBypass) {
|
||||
aethexToast.error("Only admins can toggle maintenance mode");
|
||||
aethexToast.error({ title: "Only admins can toggle maintenance mode" });
|
||||
return;
|
||||
}
|
||||
|
||||
setToggling(true);
|
||||
try {
|
||||
await toggleMaintenanceMode();
|
||||
aethexToast.success(
|
||||
isMaintenanceMode
|
||||
aethexToast.success({
|
||||
title: isMaintenanceMode
|
||||
? "Maintenance mode disabled - site is now live"
|
||||
: "Maintenance mode enabled - visitors will see maintenance page"
|
||||
);
|
||||
});
|
||||
} catch (error: any) {
|
||||
aethexToast.error(error?.message || "Failed to toggle maintenance mode");
|
||||
aethexToast.error({ title: error?.message || "Failed to toggle maintenance mode" });
|
||||
} finally {
|
||||
setToggling(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,11 +27,11 @@ export function DevConnectLinkModal({
|
|||
}: DevConnectLinkModalProps) {
|
||||
const [username, setUsername] = useState("");
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const { toast } = useAethexToast();
|
||||
const toast = useAethexToast();
|
||||
|
||||
const handleLink = async () => {
|
||||
if (!username.trim()) {
|
||||
toast("Please enter your DevConnect username", "error");
|
||||
toast.error({ title: "Please enter your DevConnect username" });
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -41,17 +41,16 @@ export function DevConnectLinkModal({
|
|||
devconnect_username: username.trim(),
|
||||
devconnect_profile_url: `https://devconnect.sbs/${username.trim()}`,
|
||||
});
|
||||
toast("DevConnect account linked successfully!", "success");
|
||||
toast.success({ title: "DevConnect account linked successfully!" });
|
||||
setUsername("");
|
||||
onOpenChange(false);
|
||||
onSuccess?.();
|
||||
} catch (error) {
|
||||
toast(
|
||||
error instanceof Error
|
||||
toast.error({
|
||||
title: error instanceof Error
|
||||
? error.message
|
||||
: "Failed to link DevConnect account",
|
||||
"error",
|
||||
);
|
||||
});
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
// Export layout components
|
||||
export { default as DevPlatformLayout } from './layouts/DevPlatformLayout';
|
||||
export { default as ThreeColumnLayout } from './layouts/ThreeColumnLayout';
|
||||
export { DevPlatformLayout } from './layouts/DevPlatformLayout';
|
||||
export { ThreeColumnLayout } from './layouts/ThreeColumnLayout';
|
||||
|
||||
// Export UI components
|
||||
export { default as CodeBlock } from './ui/CodeBlock';
|
||||
export { default as Callout } from './ui/Callout';
|
||||
export { default as StatCard } from './ui/StatCard';
|
||||
export { default as ApiEndpointCard } from './ui/ApiEndpointCard';
|
||||
export { CodeBlock } from './ui/CodeBlock';
|
||||
export { Callout } from './ui/Callout';
|
||||
export { StatCard } from './ui/StatCard';
|
||||
export { ApiEndpointCard } from './ui/ApiEndpointCard';
|
||||
|
||||
// Export feature components
|
||||
export { default as DevPlatformNav } from './DevPlatformNav';
|
||||
export { default as DevPlatformFooter } from './DevPlatformFooter';
|
||||
export { default as Breadcrumbs } from './Breadcrumbs';
|
||||
export { default as CodeTabs } from './CodeTabs';
|
||||
export { default as TemplateCard } from './TemplateCard';
|
||||
export { default as MarketplaceCard } from './MarketplaceCard';
|
||||
export { default as ExampleCard } from './ExampleCard';
|
||||
export { default as ApiKeyCard } from './ApiKeyCard';
|
||||
export { default as CreateApiKeyDialog } from './CreateApiKeyDialog';
|
||||
export { default as UsageChart } from './UsageChart';
|
||||
export { DevPlatformNav } from './DevPlatformNav';
|
||||
export { DevPlatformFooter } from './DevPlatformFooter';
|
||||
export { Breadcrumbs } from './Breadcrumbs';
|
||||
export { CodeTabs } from './CodeTabs';
|
||||
export { TemplateCard } from './TemplateCard';
|
||||
export { MarketplaceCard } from './MarketplaceCard';
|
||||
export { ExampleCard } from './ExampleCard';
|
||||
export { ApiKeyCard } from './ApiKeyCard';
|
||||
export { CreateApiKeyDialog } from './CreateApiKeyDialog';
|
||||
export { UsageChart } from './UsageChart';
|
||||
|
|
|
|||
|
|
@ -81,6 +81,12 @@ const docNavigation: DocNavItem[] = [
|
|||
icon: <BookOpen className="h-5 w-5" />,
|
||||
description: "Learning paths",
|
||||
},
|
||||
{
|
||||
title: "AeThex Language",
|
||||
path: "/docs/lang",
|
||||
icon: <Code2 className="h-5 w-5" />,
|
||||
description: "AeThex programming language",
|
||||
},
|
||||
];
|
||||
|
||||
interface DocsLayoutProps {
|
||||
|
|
|
|||
|
|
@ -47,20 +47,20 @@ export const WalletVerification = ({
|
|||
|
||||
const handleConnect = async () => {
|
||||
if (!walletInput.trim()) {
|
||||
aethexToast.warning("Please enter a wallet address");
|
||||
aethexToast.warning({ title: "Please enter a wallet address" });
|
||||
return;
|
||||
}
|
||||
|
||||
const normalized = walletInput.trim().toLowerCase();
|
||||
if (!isValidEthereumAddress(normalized)) {
|
||||
aethexToast.warning(
|
||||
"Invalid Ethereum address. Must be 0x followed by 40 hexadecimal characters.",
|
||||
);
|
||||
aethexToast.warning({
|
||||
title: "Invalid Ethereum address. Must be 0x followed by 40 hexadecimal characters.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!user?.id) {
|
||||
aethexToast.error("User not authenticated");
|
||||
aethexToast.error({ title: "User not authenticated" });
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -86,16 +86,16 @@ export const WalletVerification = ({
|
|||
const data = await response.json();
|
||||
setConnectedWallet(normalized);
|
||||
setWalletInput("");
|
||||
aethexToast.success("✅ Wallet connected successfully!");
|
||||
aethexToast.success({ title: "✅ Wallet connected successfully!" });
|
||||
|
||||
if (onWalletUpdated) {
|
||||
onWalletUpdated(normalized);
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error("[Wallet Verification] Error:", error?.message);
|
||||
aethexToast.error(
|
||||
error?.message || "Failed to connect wallet. Please try again.",
|
||||
);
|
||||
aethexToast.error({
|
||||
title: error?.message || "Failed to connect wallet. Please try again.",
|
||||
});
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
|
|
@ -123,16 +123,16 @@ export const WalletVerification = ({
|
|||
}
|
||||
|
||||
setConnectedWallet(null);
|
||||
aethexToast.success("Wallet disconnected");
|
||||
aethexToast.success({ title: "Wallet disconnected" });
|
||||
|
||||
if (onWalletUpdated) {
|
||||
onWalletUpdated(null);
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error("[Wallet Verification] Error:", error?.message);
|
||||
aethexToast.error(
|
||||
error?.message || "Failed to disconnect wallet. Please try again.",
|
||||
);
|
||||
aethexToast.error({
|
||||
title: error?.message || "Failed to disconnect wallet. Please try again.",
|
||||
});
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,18 +124,14 @@ export default function About() {
|
|||
{/* Hero */}
|
||||
<section className="py-16 lg:py-24 border-b border-gray-800">
|
||||
<div className="container mx-auto max-w-6xl px-4">
|
||||
<h1 className="text-5xl lg:text-7xl font-black mb-6">
|
||||
<h1 className="text-4xl lg:text-5xl font-bold mb-6">
|
||||
Building an Integrated{" "}
|
||||
<span className="bg-gradient-to-r from-yellow-300 via-blue-300 to-red-300 bg-clip-text text-transparent">
|
||||
Ecosystem
|
||||
</span>
|
||||
</h1>
|
||||
<p className="text-xl text-gray-300 max-w-3xl">
|
||||
AeThex operates as a unified four-pillar organization that
|
||||
combines speculative innovation, profitable operations, community
|
||||
impact, and specialized talent acquisition. This structure creates
|
||||
multiple reinforcing competitive moats while managing risk and
|
||||
maintaining investor confidence.
|
||||
<p className="text-lg text-gray-300 max-w-3xl">
|
||||
Four-pillar ecosystem combining innovation, operations, community, and talent
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ const ARMS: Arm[] = [
|
|||
textColor: "text-purple-400",
|
||||
href: "/staff",
|
||||
icon: "https://cdn.builder.io/api/v1/image/assets%2Ffc53d607e21d497595ac97e0637001a1%2Fc0414efd7af54ef4b821a05d469150d0?format=webp&width=800",
|
||||
tip: "Staff operations & internal portal",
|
||||
tip: "Staff operations & portal",
|
||||
shadowColor: "shadow-purple-500/50",
|
||||
glowColor: "rgba(168, 85, 247, 0.3)",
|
||||
},
|
||||
|
|
@ -37,7 +37,7 @@ const ARMS: Arm[] = [
|
|||
textColor: "text-yellow-400",
|
||||
href: "/labs",
|
||||
icon: "https://cdn.builder.io/api/v1/image/assets%2Ffc53d607e21d497595ac97e0637001a1%2Fd93f7113d34347469e74421c3a3412e5?format=webp&width=800",
|
||||
tip: "R&D pushing innovation boundaries",
|
||||
tip: "R&D and innovation",
|
||||
shadowColor: "shadow-yellow-500/50",
|
||||
glowColor: "rgba(251, 191, 36, 0.3)",
|
||||
},
|
||||
|
|
@ -49,7 +49,7 @@ const ARMS: Arm[] = [
|
|||
textColor: "text-green-400",
|
||||
href: "/gameforge",
|
||||
icon: "https://cdn.builder.io/api/v1/image/assets%2Ffc53d607e21d497595ac97e0637001a1%2Fcd3534c1caa0497abfd44224040c6059?format=webp&width=800",
|
||||
tip: "Games shipped monthly at speed",
|
||||
tip: "Ship games monthly",
|
||||
shadowColor: "shadow-green-500/50",
|
||||
glowColor: "rgba(34, 197, 94, 0.3)",
|
||||
},
|
||||
|
|
@ -61,7 +61,7 @@ const ARMS: Arm[] = [
|
|||
textColor: "text-blue-400",
|
||||
href: "/corp",
|
||||
icon: "https://cdn.builder.io/api/v1/image/assets%2Ffc53d607e21d497595ac97e0637001a1%2F3772073d5b4b49e688ed02480f4cae43?format=webp&width=800",
|
||||
tip: "Enterprise solutions for scale",
|
||||
tip: "Enterprise solutions",
|
||||
shadowColor: "shadow-blue-500/50",
|
||||
glowColor: "rgba(59, 130, 246, 0.3)",
|
||||
},
|
||||
|
|
@ -73,7 +73,7 @@ const ARMS: Arm[] = [
|
|||
textColor: "text-red-400",
|
||||
href: "https://aethex.foundation",
|
||||
icon: "https://cdn.builder.io/api/v1/image/assets%2Ffc53d607e21d497595ac97e0637001a1%2Fc02cb1bf5056479bbb3ea4bd91f0d472?format=webp&width=800",
|
||||
tip: "Community & education initiatives",
|
||||
tip: "Community & education",
|
||||
shadowColor: "shadow-red-500/50",
|
||||
glowColor: "rgba(239, 68, 68, 0.3)",
|
||||
external: true,
|
||||
|
|
@ -86,7 +86,7 @@ const ARMS: Arm[] = [
|
|||
textColor: "text-purple-400",
|
||||
href: "/nexus",
|
||||
icon: "https://cdn.builder.io/api/v1/image/assets%2Ffc53d607e21d497595ac97e0637001a1%2F6df123b87a144b1fb99894d94198d97b?format=webp&width=800",
|
||||
tip: "Talent marketplace & collaboration",
|
||||
tip: "Talent marketplace",
|
||||
shadowColor: "shadow-purple-500/50",
|
||||
glowColor: "rgba(168, 85, 247, 0.3)",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -22,25 +22,25 @@ export default function Careers() {
|
|||
icon: <Microscope className="h-6 w-6" />,
|
||||
title: "Innovation First",
|
||||
description:
|
||||
"We push boundaries and explore cutting-edge technologies daily",
|
||||
"Push boundaries and explore cutting-edge technologies",
|
||||
},
|
||||
{
|
||||
icon: <Heart className="h-6 w-6" />,
|
||||
title: "People Matter",
|
||||
description:
|
||||
"We invest in our team's growth, health, and work-life balance",
|
||||
"Invest in team growth, health, and work-life balance",
|
||||
},
|
||||
{
|
||||
icon: <Zap className="h-6 w-6" />,
|
||||
title: "Ship It",
|
||||
description:
|
||||
"We believe in execution over perfection—iterate and learn fast",
|
||||
"Execute over perfection—iterate and learn fast",
|
||||
},
|
||||
{
|
||||
icon: <Users className="h-6 w-6" />,
|
||||
title: "Collaboration",
|
||||
description:
|
||||
"Great ideas come from diverse teams working together openly",
|
||||
"Great ideas come from diverse teams working openly",
|
||||
},
|
||||
];
|
||||
|
||||
|
|
@ -49,8 +49,8 @@ export default function Careers() {
|
|||
"Comprehensive health insurance (medical, dental, vision)",
|
||||
"Unlimited PTO",
|
||||
"Remote-first, work from anywhere",
|
||||
"Equipment budget for your home office",
|
||||
"Professional development fund ($5k/year)",
|
||||
"Equipment budget",
|
||||
"Professional development ($5k/year)",
|
||||
"Team offsites & retreats",
|
||||
"Stock options",
|
||||
"Parental leave",
|
||||
|
|
@ -67,7 +67,7 @@ export default function Careers() {
|
|||
level: "Senior",
|
||||
type: "Full-time",
|
||||
description:
|
||||
"Lead architecture and implementation of next-generation platform systems",
|
||||
"Lead platform architecture and implementation",
|
||||
},
|
||||
{
|
||||
title: "Game Developer",
|
||||
|
|
@ -75,7 +75,7 @@ export default function Careers() {
|
|||
location: "Remote",
|
||||
level: "Mid-level",
|
||||
type: "Full-time",
|
||||
description: "Ship games monthly with our world-class production team",
|
||||
description: "Ship games monthly with world-class team",
|
||||
},
|
||||
{
|
||||
title: "Research Scientist",
|
||||
|
|
@ -84,7 +84,7 @@ export default function Careers() {
|
|||
level: "Senior",
|
||||
type: "Full-time",
|
||||
description:
|
||||
"Explore AI/ML applications in game development and interactive experiences",
|
||||
"Explore AI/ML in game development and interactive experiences",
|
||||
},
|
||||
{
|
||||
title: "Product Manager",
|
||||
|
|
@ -93,7 +93,7 @@ export default function Careers() {
|
|||
level: "Mid-level",
|
||||
type: "Full-time",
|
||||
description:
|
||||
"Shape the future of our developer tools and platforms",
|
||||
"Shape the future of developer tools and platforms",
|
||||
},
|
||||
{
|
||||
title: "UX/UI Designer",
|
||||
|
|
@ -102,7 +102,7 @@ export default function Careers() {
|
|||
level: "Mid-level",
|
||||
type: "Full-time",
|
||||
description:
|
||||
"Design beautiful, intuitive interfaces for millions of developers",
|
||||
"Design beautiful interfaces for developers",
|
||||
},
|
||||
{
|
||||
title: "DevOps Engineer",
|
||||
|
|
@ -110,7 +110,7 @@ export default function Careers() {
|
|||
location: "Remote",
|
||||
level: "Senior",
|
||||
type: "Full-time",
|
||||
description: "Build the infrastructure that powers AeThex at scale",
|
||||
description: "Build infrastructure that powers AeThex at scale",
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -66,12 +66,11 @@ export default function Contact() {
|
|||
<div className="container mx-auto px-4 max-w-5xl space-y-10">
|
||||
<div className="grid md:grid-cols-2 gap-8 items-start">
|
||||
<div className="space-y-3">
|
||||
<h1 className="text-4xl font-bold text-gradient-purple">
|
||||
<h1 className="text-3xl font-bold text-gradient-purple">
|
||||
Contact Us
|
||||
</h1>
|
||||
<p className="text-muted-foreground">
|
||||
Have a project or question? We typically respond within 1–2
|
||||
business days.
|
||||
We respond within 1–2 business days
|
||||
</p>
|
||||
<Card className="bg-card/50 border-border/50">
|
||||
<CardContent className="p-6 space-y-3">
|
||||
|
|
|
|||
|
|
@ -78,8 +78,8 @@ export default function Corp() {
|
|||
|
||||
const services = [
|
||||
{
|
||||
title: "Custom Software Development",
|
||||
description: "Bespoke applications built for enterprise scale",
|
||||
title: "Custom Software",
|
||||
description: "Enterprise applications",
|
||||
icon: Code,
|
||||
examples: [
|
||||
"Web & mobile applications",
|
||||
|
|
@ -90,8 +90,8 @@ export default function Corp() {
|
|||
color: "from-blue-500 to-cyan-500",
|
||||
},
|
||||
{
|
||||
title: "Technology Consulting",
|
||||
description: "Strategic guidance for digital transformation",
|
||||
title: "Tech Consulting",
|
||||
description: "Digital transformation",
|
||||
icon: Briefcase,
|
||||
examples: [
|
||||
"Architecture design",
|
||||
|
|
@ -102,8 +102,8 @@ export default function Corp() {
|
|||
color: "from-purple-500 to-pink-500",
|
||||
},
|
||||
{
|
||||
title: "Game Development Services",
|
||||
description: "Specialized expertise for gaming companies",
|
||||
title: "Game Development",
|
||||
description: "Metaverse & gaming",
|
||||
icon: Rocket,
|
||||
examples: [
|
||||
"Full game production",
|
||||
|
|
|
|||
|
|
@ -304,14 +304,14 @@ export default function Dashboard() {
|
|||
</div>
|
||||
<Button
|
||||
onClick={() => navigate("/login")}
|
||||
className="w-full bg-gradient-to-r from-purple-600 to-blue-600 hover:from-purple-700 hover:to-blue-700 text-white text-lg py-6"
|
||||
className="w-full bg-gradient-to-r from-purple-600 to-blue-600 hover:from-purple-700 hover:to-blue-700 text-white py-6"
|
||||
>
|
||||
Sign In to Dashboard
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => navigate("/onboarding")}
|
||||
variant="outline"
|
||||
className="w-full text-lg py-6 border-purple-500/30 text-purple-300 hover:bg-purple-500/10"
|
||||
className="w-full py-6 border-purple-500/30 text-purple-300 hover:bg-purple-500/10"
|
||||
>
|
||||
Create New Account
|
||||
</Button>
|
||||
|
|
@ -326,15 +326,15 @@ export default function Dashboard() {
|
|||
return (
|
||||
<Layout>
|
||||
<div className="min-h-screen bg-gradient-to-b from-black via-purple-950/20 to-black">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 py-8 lg:py-12 max-w-6xl space-y-8">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 py-8 lg:py-12 max-w-6xl space-y-12">
|
||||
{/* Header Section */}
|
||||
<div className="space-y-4 animate-slide-down">
|
||||
<div className="flex flex-col md:flex-row md:items-center md:justify-between gap-4">
|
||||
<div className="space-y-2">
|
||||
<h1 className="text-5xl md:text-6xl font-bold bg-gradient-to-r from-purple-300 via-blue-300 to-purple-300 bg-clip-text text-transparent">
|
||||
<h1 className="text-4xl md:text-5xl font-bold bg-gradient-to-r from-purple-300 via-blue-300 to-purple-300 bg-clip-text text-transparent">
|
||||
Dashboard
|
||||
</h1>
|
||||
<p className="text-gray-400 text-lg">
|
||||
<p className="text-gray-400">
|
||||
Welcome back,{" "}
|
||||
<span className="text-purple-300 font-semibold">
|
||||
{profile?.full_name || user.email?.split("@")[0]}
|
||||
|
|
@ -413,15 +413,15 @@ export default function Dashboard() {
|
|||
<TabsContent value="realms" className="space-y-6 animate-fade-in">
|
||||
{/* Developer CTA Card */}
|
||||
{user && (
|
||||
<Card className="p-6 bg-gradient-to-br from-primary/10 to-primary/5 border-primary/20 hover:border-primary/40 transition-all">
|
||||
<div className="flex flex-col md:flex-row items-start gap-4">
|
||||
<div className="p-3 bg-primary/20 rounded-lg shrink-0">
|
||||
<Card className="p-8 bg-gradient-to-br from-primary/10 to-primary/5 border-primary/20 hover:border-primary/40 transition-all">
|
||||
<div className="flex flex-col md:flex-row items-start gap-6">
|
||||
<div className="p-4 bg-primary/20 rounded-lg shrink-0">
|
||||
<Code className="w-6 h-6 text-primary" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h3 className="text-lg font-semibold mb-2">Building with AeThex?</h3>
|
||||
<p className="text-sm text-muted-foreground mb-4">
|
||||
Get API keys, access comprehensive documentation, and explore developer tools to integrate AeThex into your applications.
|
||||
<h3 className="text-xl font-semibold mb-3">Building with AeThex?</h3>
|
||||
<p className="text-base text-muted-foreground mb-6">
|
||||
Get API keys and access developer tools
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-3">
|
||||
<Link to="/dev-platform/dashboard">
|
||||
|
|
@ -432,12 +432,7 @@ export default function Dashboard() {
|
|||
</Link>
|
||||
<Link to="/dev-platform/api-reference">
|
||||
<Button size="sm" variant="outline">
|
||||
View API Docs
|
||||
</Button>
|
||||
</Link>
|
||||
<Link to="/dev-platform/templates">
|
||||
<Button size="sm" variant="outline">
|
||||
Browse Templates
|
||||
View Docs
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
|
|
@ -446,7 +441,7 @@ export default function Dashboard() {
|
|||
</Card>
|
||||
)}
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{ARMS.map((arm) => {
|
||||
const IconComponent = arm.icon;
|
||||
return (
|
||||
|
|
@ -465,7 +460,7 @@ export default function Dashboard() {
|
|||
<Card
|
||||
className={`bg-gradient-to-br ${arm.bgGradient} border transition-all duration-300 h-full hover:shadow-lg hover:shadow-purple-500/20 ${arm.borderColor} cursor-pointer`}
|
||||
>
|
||||
<CardContent className="p-6 space-y-4">
|
||||
<CardContent className="p-8 space-y-6">
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="space-y-1">
|
||||
<div className="flex items-center gap-3">
|
||||
|
|
|
|||
|
|
@ -84,12 +84,11 @@ export default function Downloads() {
|
|||
<Badge variant="outline" className="mb-4 border-purple-500/50 text-purple-400">
|
||||
Version {CURRENT_VERSION}
|
||||
</Badge>
|
||||
<h1 className="text-4xl md:text-5xl font-bold mb-4 bg-gradient-to-r from-white via-purple-400 to-blue-400 bg-clip-text text-transparent">
|
||||
<h1 className="text-3xl md:text-4xl font-bold mb-4 bg-gradient-to-r from-white via-purple-400 to-blue-400 bg-clip-text text-transparent">
|
||||
Download AeThex Desktop
|
||||
</h1>
|
||||
<p className="text-lg text-muted-foreground max-w-2xl mx-auto">
|
||||
The AeThex Desktop Terminal brings the full power of the platform to your computer.
|
||||
Access realms, manage projects, and stay connected with your community.
|
||||
Desktop Terminal brings full platform access to your computer. Manage projects and stay connected.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import {
|
|||
TrendingUp,
|
||||
Heart,
|
||||
MessageSquare,
|
||||
Avatar,
|
||||
User,
|
||||
} from "lucide-react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import {
|
|||
Compass,
|
||||
ExternalLink,
|
||||
} from "lucide-react";
|
||||
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useEffect, useState, useRef } from "react";
|
||||
import LoadingScreen from "@/components/LoadingScreen";
|
||||
|
|
@ -95,7 +96,7 @@ export default function Foundation() {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div className="container mx-auto px-4 max-w-6xl space-y-20 py-16 lg:py-24">
|
||||
<div className="container mx-auto px-4 max-w-6xl space-y-24 py-16 lg:py-24">
|
||||
{/* Hero Section */}
|
||||
<div className="text-center space-y-8 animate-slide-down">
|
||||
<div className="flex justify-center mb-6">
|
||||
|
|
@ -112,12 +113,12 @@ export default function Foundation() {
|
|||
501(c)(3) Non-Profit Organization
|
||||
</Badge>
|
||||
|
||||
<h1 className="text-5xl md:text-6xl lg:text-7xl font-black bg-gradient-to-r from-red-300 via-pink-300 to-red-300 bg-clip-text text-transparent">
|
||||
<h1 className="text-5xl md:text-6xl lg:text-7xl font-bold bg-gradient-to-r from-red-300 via-pink-300 to-red-300 bg-clip-text text-transparent">
|
||||
AeThex Foundation
|
||||
</h1>
|
||||
|
||||
<p className="text-xl md:text-2xl text-gray-300 max-w-3xl mx-auto leading-relaxed">
|
||||
Building community, empowering developers, and advancing game development through open-source innovation and mentorship.
|
||||
<p className="text-lg md:text-xl text-gray-300 max-w-3xl mx-auto leading-relaxed">
|
||||
501(c)(3) non-profit advancing game development
|
||||
</p>
|
||||
|
||||
{/* TL;DR Section */}
|
||||
|
|
|
|||
|
|
@ -154,12 +154,12 @@ export default function GameForge() {
|
|||
Foundation's Game Production Studio
|
||||
</Badge>
|
||||
|
||||
<h1 className={`text-5xl md:text-6xl lg:text-7xl font-black text-green-300 leading-tight ${theme.fontClass}`}>
|
||||
<h1 className={`text-5xl md:text-6xl lg:text-7xl font-bold text-green-300 leading-tight ${theme.fontClass}`}>
|
||||
Ship Games Every Month
|
||||
</h1>
|
||||
|
||||
<p className="text-xl md:text-2xl text-green-100/80 max-w-3xl mx-auto leading-relaxed">
|
||||
AeThex GameForge is a master-apprentice mentorship program where teams of 5 developers ship real games in 30-day sprints.
|
||||
<p className="text-lg md:text-xl text-green-100/80 max-w-3xl mx-auto leading-relaxed">
|
||||
Ship real games in 30-day sprints
|
||||
</p>
|
||||
|
||||
{/* TL;DR Section */}
|
||||
|
|
|
|||
|
|
@ -132,20 +132,20 @@ export default function GetStarted() {
|
|||
|
||||
const platformFeatures = [
|
||||
{
|
||||
title: "XP & Leveling System",
|
||||
description: "Earn XP for daily logins, completing your profile, creating posts, and earning badges. Level up to unlock new features and recognition.",
|
||||
title: "XP & Leveling",
|
||||
description: "Earn XP and level up to unlock features",
|
||||
icon: Trophy,
|
||||
color: "from-yellow-500 to-amber-600",
|
||||
},
|
||||
{
|
||||
title: "AI Intelligent Agents",
|
||||
description: "Access 10 specialized AI personas for guidance on networking, game development, ethics, architecture, and more.",
|
||||
title: "AI Agents",
|
||||
description: "10 specialized AI personas for guidance",
|
||||
icon: Bot,
|
||||
color: "from-purple-500 to-violet-600",
|
||||
},
|
||||
{
|
||||
title: "Creator Passports",
|
||||
description: "Build a portable profile that aggregates your achievements, verified skills, project history, and mentorship contributions.",
|
||||
description: "Portable profile with achievements and skills",
|
||||
icon: IdCard,
|
||||
color: "from-cyan-500 to-blue-600",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useState, useEffect } from "react";
|
||||
import { useState } from "react";
|
||||
import SEO from "@/components/SEO";
|
||||
import Layout from "@/components/Layout";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
|
@ -27,7 +27,7 @@ const ecosystemPillars = [
|
|||
{
|
||||
icon: Boxes,
|
||||
title: "Six Realms",
|
||||
description: "Nexus, GameForge, Foundation, Labs, Corp, and Staff—each with unique APIs and capabilities",
|
||||
description: "Specialized APIs for every use case",
|
||||
href: "/realms",
|
||||
gradient: "from-purple-500 via-purple-600 to-indigo-600",
|
||||
accentColor: "hsl(var(--primary))",
|
||||
|
|
@ -35,7 +35,7 @@ const ecosystemPillars = [
|
|||
{
|
||||
icon: Database,
|
||||
title: "Developer APIs",
|
||||
description: "Comprehensive REST APIs for users, content, achievements, and more",
|
||||
description: "REST APIs for all platforms",
|
||||
href: "/dev-platform/api-reference",
|
||||
gradient: "from-blue-500 via-blue-600 to-cyan-600",
|
||||
accentColor: "hsl(var(--primary))",
|
||||
|
|
@ -43,7 +43,7 @@ const ecosystemPillars = [
|
|||
{
|
||||
icon: Terminal,
|
||||
title: "SDK & Tools",
|
||||
description: "TypeScript SDK, CLI tools, and pre-built templates to ship faster",
|
||||
description: "Ship faster with TypeScript SDK",
|
||||
href: "/dev-platform/quick-start",
|
||||
gradient: "from-cyan-500 via-teal-600 to-emerald-600",
|
||||
accentColor: "hsl(var(--primary))",
|
||||
|
|
@ -51,7 +51,7 @@ const ecosystemPillars = [
|
|||
{
|
||||
icon: Layers,
|
||||
title: "Marketplace",
|
||||
description: "Premium integrations, plugins, and components from the community",
|
||||
description: "Premium plugins & integrations",
|
||||
href: "/dev-platform/marketplace",
|
||||
gradient: "from-emerald-500 via-green-600 to-lime-600",
|
||||
accentColor: "hsl(var(--primary))",
|
||||
|
|
@ -59,7 +59,7 @@ const ecosystemPillars = [
|
|||
{
|
||||
icon: Users,
|
||||
title: "Community",
|
||||
description: "Join 12,000+ developers building on AeThex",
|
||||
description: "12K+ developers building together",
|
||||
href: "/community",
|
||||
gradient: "from-amber-500 via-orange-600 to-red-600",
|
||||
accentColor: "hsl(var(--primary))",
|
||||
|
|
@ -67,7 +67,7 @@ const ecosystemPillars = [
|
|||
{
|
||||
icon: Trophy,
|
||||
title: "Opportunities",
|
||||
description: "Get paid to build—contracts, bounties, and commissions",
|
||||
description: "Get paid to build",
|
||||
href: "/opportunities",
|
||||
gradient: "from-pink-500 via-rose-600 to-red-600",
|
||||
accentColor: "hsl(var(--primary))",
|
||||
|
|
@ -84,48 +84,39 @@ const stats = [
|
|||
const features = [
|
||||
{
|
||||
icon: Layers,
|
||||
title: "Cross-Platform Integration Layer",
|
||||
description: "One unified API to build across Roblox, VRChat, RecRoom, Spatial, Decentraland, The Sandbox, Minecraft, Meta Horizon, Fortnite, and Zepeto—no more managing separate platform SDKs or gated gardens",
|
||||
title: "Cross-Platform Integration",
|
||||
description: "One API for all metaverse platforms",
|
||||
},
|
||||
{
|
||||
icon: Code2,
|
||||
title: "Enterprise-Grade Developer Tools",
|
||||
description: "TypeScript SDK, REST APIs, unified authentication, cross-platform achievements, content delivery, and CLI tools—all integrated and production-ready",
|
||||
title: "Enterprise Developer Tools",
|
||||
description: "Production-ready SDK and APIs",
|
||||
},
|
||||
{
|
||||
icon: Gamepad2,
|
||||
title: "Six Specialized Realms",
|
||||
description: "Nexus (social hub), GameForge (games), Foundation (education), Labs (AI/innovation), Corp (business), Staff (governance)—each with unique APIs and tools",
|
||||
description: "Unique APIs for every use case",
|
||||
},
|
||||
{
|
||||
icon: Trophy,
|
||||
title: "Monetize Your Skills",
|
||||
description: "Get paid to build—access contracts, bounties, and commissions. 12K+ developers earning while creating cross-platform games, apps, and integrations",
|
||||
description: "12K+ developers earning on AeThex",
|
||||
},
|
||||
{
|
||||
icon: Users,
|
||||
title: "Thriving Creator Economy",
|
||||
description: "Join squads, collaborate on projects, share assets in the marketplace that work across all platforms, and grow your reputation across all six realms",
|
||||
title: "Creator Economy",
|
||||
description: "Collaborate and grow your reputation",
|
||||
},
|
||||
{
|
||||
icon: Rocket,
|
||||
title: "Ship Everywhere, Fast",
|
||||
description: "150+ cross-platform code examples, pre-built templates for VRChat, RecRoom, Spatial, Decentraland, The Sandbox, Roblox, and more—OAuth integration, Supabase backend, and one-command deployment to every metaverse",
|
||||
title: "Ship Fast",
|
||||
description: "150+ examples and one-click deployment",
|
||||
},
|
||||
];
|
||||
|
||||
export default function Index() {
|
||||
const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });
|
||||
const [hoveredCard, setHoveredCard] = useState<number | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleMouseMove = (e: MouseEvent) => {
|
||||
setMousePosition({ x: e.clientX, y: e.clientY });
|
||||
};
|
||||
window.addEventListener("mousemove", handleMouseMove);
|
||||
return () => window.removeEventListener("mousemove", handleMouseMove);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Layout hideFooter>
|
||||
<SEO
|
||||
|
|
@ -141,10 +132,10 @@ export default function Index() {
|
|||
{/* Animated Background */}
|
||||
<div className="fixed inset-0 pointer-events-none overflow-hidden">
|
||||
<motion.div
|
||||
className="absolute w-[800px] h-[800px] rounded-full blur-[128px] opacity-20 bg-primary/30"
|
||||
className="absolute w-[600px] h-[600px] rounded-full blur-[100px] opacity-15 bg-primary/30"
|
||||
style={{
|
||||
left: mousePosition.x - 400,
|
||||
top: mousePosition.y - 400,
|
||||
left: '10%',
|
||||
top: '20%',
|
||||
}}
|
||||
animate={{
|
||||
x: [0, 50, 0],
|
||||
|
|
@ -216,7 +207,7 @@ export default function Index() {
|
|||
<div className="absolute bottom-0 right-0 w-64 h-64 border-b-2 border-r-2 border-primary/30" />
|
||||
</div>
|
||||
|
||||
<div className="relative space-y-32 pb-32">
|
||||
<div className="relative space-y-40 pb-40">
|
||||
<section className="relative min-h-[90vh] flex items-center justify-center overflow-hidden pt-20">
|
||||
<div className="relative text-center max-w-6xl mx-auto space-y-10 px-4">
|
||||
<motion.div
|
||||
|
|
@ -237,7 +228,7 @@ export default function Index() {
|
|||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ duration: 0.8, delay: 0.2 }}
|
||||
>
|
||||
<h1 className="text-7xl md:text-8xl lg:text-9xl font-black tracking-tight leading-none">
|
||||
<h1 className="text-5xl md:text-6xl lg:text-7xl font-black tracking-tight leading-none">
|
||||
Build on
|
||||
<br />
|
||||
<span className="relative inline-block mt-4">
|
||||
|
|
@ -264,7 +255,7 @@ export default function Index() {
|
|||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.8, delay: 0.4 }}
|
||||
className="text-2xl md:text-3xl text-muted-foreground max-w-4xl mx-auto leading-relaxed font-light"
|
||||
className="text-xl md:text-2xl text-muted-foreground max-w-4xl mx-auto leading-relaxed font-light"
|
||||
>
|
||||
The <span className="text-primary font-bold">integration layer</span> connecting all metaverse platforms.
|
||||
<br className="hidden md:block" />
|
||||
|
|
@ -313,19 +304,19 @@ export default function Index() {
|
|||
<Link to="/dev-platform/quick-start">
|
||||
<Button
|
||||
size="lg"
|
||||
className="text-xl px-10 h-16 bg-primary hover:bg-primary/90 shadow-[0_0_40px_rgba(168,85,247,0.6)] hover:shadow-[0_0_60px_rgba(168,85,247,0.8)] hover:scale-105 transition-all duration-300 font-black uppercase tracking-wide border-2 border-primary/50"
|
||||
className="text-base px-8 h-12 bg-primary hover:bg-primary/90 shadow-[0_0_40px_rgba(168,85,247,0.6)] hover:shadow-[0_0_60px_rgba(168,85,247,0.8)] hover:scale-105 transition-all duration-300 font-bold uppercase tracking-wide border-2 border-primary/50"
|
||||
>
|
||||
Start Building
|
||||
<Rocket className="w-6 h-6 ml-3" />
|
||||
<Rocket className="w-5 h-5 ml-2" />
|
||||
</Button>
|
||||
</Link>
|
||||
<Link to="/dev-platform/api-reference">
|
||||
<Button
|
||||
size="lg"
|
||||
variant="outline"
|
||||
className="text-xl px-10 h-16 backdrop-blur-xl bg-background/50 border-2 border-primary/40 hover:bg-primary/10 hover:border-primary/60 shadow-[0_0_20px_rgba(168,85,247,0.3)] hover:shadow-[0_0_40px_rgba(168,85,247,0.5)] hover:scale-105 transition-all duration-300 font-black uppercase tracking-wide"
|
||||
className="text-base px-8 h-12 backdrop-blur-xl bg-background/50 border-2 border-primary/40 hover:bg-primary/10 hover:border-primary/60 shadow-[0_0_20px_rgba(168,85,247,0.3)] hover:shadow-[0_0_40px_rgba(168,85,247,0.5)] hover:scale-105 transition-all duration-300 font-bold uppercase tracking-wide"
|
||||
>
|
||||
<BookOpen className="w-6 h-6 mr-3" />
|
||||
<BookOpen className="w-5 h-5 mr-2" />
|
||||
Explore APIs
|
||||
</Button>
|
||||
</Link>
|
||||
|
|
@ -376,19 +367,19 @@ export default function Index() {
|
|||
</motion.div>
|
||||
</section>
|
||||
|
||||
<section className="space-y-12 px-4">
|
||||
<section className="space-y-20 px-4">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.8 }}
|
||||
className="text-center space-y-4"
|
||||
className="text-center space-y-6"
|
||||
>
|
||||
<h2 className="text-5xl md:text-6xl font-black text-primary">
|
||||
The AeThex Ecosystem
|
||||
</h2>
|
||||
<p className="text-xl text-muted-foreground max-w-3xl mx-auto">
|
||||
Six interconnected realms, each with unique capabilities and APIs to power your applications
|
||||
Six interconnected realms with unique APIs
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
|
|
@ -449,23 +440,23 @@ export default function Index() {
|
|||
</div>
|
||||
</section>
|
||||
|
||||
<section className="space-y-12 px-4">
|
||||
<section className="space-y-20 px-4">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.8 }}
|
||||
className="text-center space-y-4"
|
||||
className="text-center space-y-6"
|
||||
>
|
||||
<h2 className="text-5xl md:text-6xl font-black text-primary">
|
||||
Why Build on AeThex?
|
||||
</h2>
|
||||
<p className="text-xl text-muted-foreground max-w-3xl mx-auto">
|
||||
Join a growing ecosystem designed for creators, developers, and entrepreneurs
|
||||
Built for creators and developers
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
<div className="grid md:grid-cols-3 gap-8 max-w-6xl mx-auto">
|
||||
<div className="grid md:grid-cols-3 gap-10 max-w-6xl mx-auto">
|
||||
{features.map((feature, index) => (
|
||||
<motion.div
|
||||
key={feature.title}
|
||||
|
|
@ -474,13 +465,13 @@ export default function Index() {
|
|||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6, delay: index * 0.2 }}
|
||||
>
|
||||
<Card className="p-8 space-y-6 backdrop-blur-xl bg-background/50 border-primary/20 hover:border-primary/40 hover:scale-105 transition-all duration-300 h-full">
|
||||
<Card className="p-10 space-y-8 backdrop-blur-xl bg-background/50 border-primary/20 hover:border-primary/40 hover:scale-105 transition-all duration-300 h-full">
|
||||
<div className="w-16 h-16 rounded-2xl bg-primary flex items-center justify-center shadow-2xl shadow-primary/50">
|
||||
<feature.icon className="w-8 h-8 text-primary-foreground" />
|
||||
</div>
|
||||
<div className="space-y-3">
|
||||
<div className="space-y-4">
|
||||
<h3 className="text-2xl font-bold">{feature.title}</h3>
|
||||
<p className="text-muted-foreground leading-relaxed">
|
||||
<p className="text-lg text-muted-foreground">
|
||||
{feature.description}
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -572,20 +563,20 @@ export default function Index() {
|
|||
<Link to="/dev-platform/dashboard">
|
||||
<Button
|
||||
size="lg"
|
||||
className="text-xl px-10 h-16 bg-primary hover:bg-primary/90 shadow-[0_0_40px_rgba(168,85,247,0.6)] hover:shadow-[0_0_60px_rgba(168,85,247,0.8)] hover:scale-105 transition-all duration-300 font-black uppercase tracking-wide border-2 border-primary/50"
|
||||
className="text-base px-8 h-12 bg-primary hover:bg-primary/90 shadow-[0_0_40px_rgba(168,85,247,0.6)] hover:shadow-[0_0_60px_rgba(168,85,247,0.8)] hover:scale-105 transition-all duration-300 font-bold uppercase tracking-wide border-2 border-primary/50"
|
||||
>
|
||||
Get Your API Key
|
||||
<ArrowRight className="w-6 h-6 ml-3" />
|
||||
<ArrowRight className="w-5 h-5 ml-2" />
|
||||
</Button>
|
||||
</Link>
|
||||
<Link to="/realms">
|
||||
<Button
|
||||
size="lg"
|
||||
variant="outline"
|
||||
className="text-xl px-10 h-16 backdrop-blur-xl bg-background/50 border-2 border-primary/40 hover:bg-primary/10 hover:border-primary/60 shadow-[0_0_20px_rgba(168,85,247,0.3)] hover:shadow-[0_0_40px_rgba(168,85,247,0.5)] hover:scale-105 transition-all duration-300 font-black uppercase tracking-wide"
|
||||
className="text-base px-8 h-12 backdrop-blur-xl bg-background/50 border-2 border-primary/40 hover:bg-primary/10 hover:border-primary/60 shadow-[0_0_20px_rgba(168,85,247,0.3)] hover:shadow-[0_0_40px_rgba(168,85,247,0.5)] hover:scale-105 transition-all duration-300 font-bold uppercase tracking-wide"
|
||||
>
|
||||
Explore Realms
|
||||
<Boxes className="w-6 h-6 ml-3" />
|
||||
<Boxes className="w-5 h-5 ml-2" />
|
||||
</Button>
|
||||
</Link>
|
||||
</motion.div>
|
||||
|
|
|
|||
418
client/pages/Index.tsx.minimal
Normal file
|
|
@ -0,0 +1,418 @@
|
|||
import { useState } from "react";
|
||||
import SEO from "@/components/SEO";
|
||||
import Layout from "@/components/Layout";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card } from "@/components/ui/card";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Link } from "react-router-dom";
|
||||
import {
|
||||
ArrowRight,
|
||||
Terminal,
|
||||
Copy,
|
||||
Check,
|
||||
BookOpen,
|
||||
Zap,
|
||||
Shield,
|
||||
Globe,
|
||||
Code2,
|
||||
Database,
|
||||
Users,
|
||||
Boxes,
|
||||
Layers,
|
||||
Trophy,
|
||||
Gamepad2,
|
||||
} from "lucide-react";
|
||||
|
||||
const codeExample = `import { AeThex } from '@aethex/sdk';
|
||||
|
||||
const client = new AeThex({ apiKey: process.env.AETHEX_KEY });
|
||||
|
||||
// Authenticate user across platforms
|
||||
const user = await client.passport.authenticate({
|
||||
platform: 'roblox',
|
||||
userId: '123456789'
|
||||
});
|
||||
|
||||
// Sync achievements, inventory, progress
|
||||
await client.sync({
|
||||
achievements: user.achievements,
|
||||
inventory: user.inventory,
|
||||
progress: user.gameProgress
|
||||
});`;
|
||||
|
||||
const ecosystemPillars = [
|
||||
{
|
||||
icon: Boxes,
|
||||
title: "Six Realms",
|
||||
description: "Specialized APIs for every use case",
|
||||
href: "/realms",
|
||||
gradient: "from-purple-500 to-indigo-600",
|
||||
},
|
||||
{
|
||||
icon: Database,
|
||||
title: "Developer APIs",
|
||||
description: "REST APIs for all platforms",
|
||||
href: "/dev-platform/api-reference",
|
||||
gradient: "from-blue-500 to-cyan-600",
|
||||
},
|
||||
{
|
||||
icon: Terminal,
|
||||
title: "SDK & Tools",
|
||||
description: "Ship faster with TypeScript SDK",
|
||||
href: "/dev-platform/quick-start",
|
||||
gradient: "from-cyan-500 to-emerald-600",
|
||||
},
|
||||
{
|
||||
icon: Layers,
|
||||
title: "Marketplace",
|
||||
description: "Premium plugins & integrations",
|
||||
href: "/dev-platform/marketplace",
|
||||
gradient: "from-emerald-500 to-lime-600",
|
||||
},
|
||||
{
|
||||
icon: Users,
|
||||
title: "Community",
|
||||
description: "12K+ developers building together",
|
||||
href: "/community",
|
||||
gradient: "from-amber-500 to-red-600",
|
||||
},
|
||||
{
|
||||
icon: Trophy,
|
||||
title: "Opportunities",
|
||||
description: "Get paid to build",
|
||||
href: "/opportunities",
|
||||
gradient: "from-pink-500 to-red-600",
|
||||
},
|
||||
];
|
||||
|
||||
const stats = [
|
||||
{ value: "12K+", label: "Developers" },
|
||||
{ value: "2.5M+", label: "API Calls/Day" },
|
||||
{ value: "150+", label: "Examples" },
|
||||
{ value: "6", label: "Realms" },
|
||||
];
|
||||
|
||||
const features = [
|
||||
{
|
||||
icon: Globe,
|
||||
title: "Cross-Platform Identity",
|
||||
description: "One passport across Roblox, Minecraft, Fortnite, and more.",
|
||||
},
|
||||
{
|
||||
icon: Database,
|
||||
title: "Universal Data Sync",
|
||||
description: "Sync achievements, inventory, and progress with a single API.",
|
||||
},
|
||||
{
|
||||
icon: Shield,
|
||||
title: "Enterprise Auth",
|
||||
description: "OAuth 2.0, PKCE, JWT. Production-ready out of the box.",
|
||||
},
|
||||
{
|
||||
icon: Gamepad2,
|
||||
title: "Game Integration",
|
||||
description: "Drop-in SDKs for Roblox, Unity, Unreal, and more.",
|
||||
},
|
||||
];
|
||||
|
||||
const platforms = ["Roblox", "Minecraft", "Fortnite", "Meta Horizon", "Zepeto", "Unity", "Unreal"];
|
||||
|
||||
export default function Index() {
|
||||
const [copied, setCopied] = useState(false);
|
||||
|
||||
const copyCode = () => {
|
||||
navigator.clipboard.writeText(codeExample);
|
||||
setCopied(true);
|
||||
setTimeout(() => setCopied(false), 2000);
|
||||
};
|
||||
|
||||
return (
|
||||
<Layout hideFooter>
|
||||
<SEO
|
||||
pageTitle="AeThex | Developer Platform"
|
||||
description="Build cross-platform experiences with the AeThex SDK. One API for identity, data sync, and authentication across metaverse platforms."
|
||||
canonical={typeof window !== "undefined" ? window.location.href : undefined}
|
||||
/>
|
||||
|
||||
{/* Subtle background */}
|
||||
<div className="fixed inset-0 pointer-events-none overflow-hidden -z-10">
|
||||
<div className="absolute top-0 right-0 w-[600px] h-[600px] rounded-full bg-primary/5 blur-3xl" />
|
||||
<div className="absolute bottom-0 left-0 w-[500px] h-[500px] rounded-full bg-primary/5 blur-3xl" />
|
||||
<div
|
||||
className="absolute inset-0 opacity-[0.02]"
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(to right, hsl(var(--primary)) 1px, transparent 1px),
|
||||
linear-gradient(to bottom, hsl(var(--primary)) 1px, transparent 1px)`,
|
||||
backgroundSize: "60px 60px",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="relative min-h-screen">
|
||||
{/* Hero */}
|
||||
<section className="relative pt-20 pb-16 px-4">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<div className="grid lg:grid-cols-2 gap-12 items-center">
|
||||
{/* Left: Value Prop */}
|
||||
<div className="space-y-6">
|
||||
<Badge variant="outline" className="text-xs font-mono border-primary/30">
|
||||
v2.4.0 — TypeScript SDK
|
||||
</Badge>
|
||||
|
||||
<h1 className="text-4xl md:text-5xl lg:text-6xl font-bold tracking-tight">
|
||||
One API for
|
||||
<br />
|
||||
<span className="text-primary">cross-platform games</span>
|
||||
</h1>
|
||||
|
||||
<p className="text-lg text-muted-foreground max-w-lg">
|
||||
Connect players across Roblox, Minecraft, Fortnite, and more.
|
||||
Sync identity, achievements, and inventory with a single SDK.
|
||||
</p>
|
||||
|
||||
<div className="flex flex-wrap gap-3 pt-2">
|
||||
<Link to="/dev-platform/quick-start">
|
||||
<Button size="lg" className="font-medium shadow-lg shadow-primary/25">
|
||||
Get Started
|
||||
<ArrowRight className="w-4 h-4 ml-2" />
|
||||
</Button>
|
||||
</Link>
|
||||
<Link to="/dev-platform/api-reference">
|
||||
<Button size="lg" variant="outline" className="font-medium">
|
||||
<BookOpen className="w-4 h-4 mr-2" />
|
||||
Read Docs
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Install command */}
|
||||
<div className="flex items-center gap-2 pt-4">
|
||||
<code className="flex-1 bg-muted px-4 py-2.5 rounded-lg font-mono text-sm border">
|
||||
npm install @aethex/sdk
|
||||
</code>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
onClick={() => navigator.clipboard.writeText("npm install @aethex/sdk")}
|
||||
>
|
||||
<Copy className="w-4 h-4" />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Stats row */}
|
||||
<div className="grid grid-cols-4 gap-4 pt-6">
|
||||
{stats.map((stat) => (
|
||||
<div key={stat.label} className="text-center">
|
||||
<p className="text-2xl md:text-3xl font-bold text-primary">{stat.value}</p>
|
||||
<p className="text-xs text-muted-foreground">{stat.label}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right: Code Example */}
|
||||
<div className="relative">
|
||||
<Card className="bg-zinc-950 border-zinc-800 overflow-hidden shadow-2xl">
|
||||
<div className="flex items-center justify-between px-4 py-2 border-b border-zinc-800">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-3 h-3 rounded-full bg-red-500/80" />
|
||||
<div className="w-3 h-3 rounded-full bg-yellow-500/80" />
|
||||
<div className="w-3 h-3 rounded-full bg-green-500/80" />
|
||||
</div>
|
||||
<span className="text-xs text-zinc-500 font-mono">app.ts</span>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
className="h-6 text-zinc-400 hover:text-white"
|
||||
onClick={copyCode}
|
||||
>
|
||||
{copied ? <Check className="w-3 h-3" /> : <Copy className="w-3 h-3" />}
|
||||
</Button>
|
||||
</div>
|
||||
<pre className="p-4 text-sm overflow-x-auto">
|
||||
<code className="text-zinc-300 font-mono whitespace-pre-wrap">
|
||||
<span className="text-purple-400">import</span>
|
||||
<span className="text-zinc-300"> {"{"} </span>
|
||||
<span className="text-yellow-300">AeThex</span>
|
||||
<span className="text-zinc-300"> {"}"} </span>
|
||||
<span className="text-purple-400">from</span>
|
||||
<span className="text-green-400"> '@aethex/sdk'</span>
|
||||
<span className="text-zinc-300">;</span>
|
||||
{"\n\n"}
|
||||
<span className="text-purple-400">const</span>
|
||||
<span className="text-blue-300"> client</span>
|
||||
<span className="text-zinc-300"> = </span>
|
||||
<span className="text-purple-400">new</span>
|
||||
<span className="text-yellow-300"> AeThex</span>
|
||||
<span className="text-zinc-300">{"({ "}</span>
|
||||
<span className="text-blue-300">apiKey</span>
|
||||
<span className="text-zinc-300">: </span>
|
||||
<span className="text-blue-300">process.env.</span>
|
||||
<span className="text-zinc-300">AETHEX_KEY {"});"}</span>
|
||||
{"\n\n"}
|
||||
<span className="text-zinc-600">// Authenticate user across platforms</span>
|
||||
{"\n"}
|
||||
<span className="text-purple-400">const</span>
|
||||
<span className="text-blue-300"> user</span>
|
||||
<span className="text-zinc-300"> = </span>
|
||||
<span className="text-purple-400">await</span>
|
||||
<span className="text-blue-300"> client</span>
|
||||
<span className="text-zinc-300">.passport.</span>
|
||||
<span className="text-yellow-300">authenticate</span>
|
||||
<span className="text-zinc-300">{"({"}</span>
|
||||
{"\n"}
|
||||
<span className="text-zinc-300">{" "}</span>
|
||||
<span className="text-blue-300">platform</span>
|
||||
<span className="text-zinc-300">: </span>
|
||||
<span className="text-green-400">'roblox'</span>
|
||||
<span className="text-zinc-300">,</span>
|
||||
{"\n"}
|
||||
<span className="text-zinc-300">{" "}</span>
|
||||
<span className="text-blue-300">userId</span>
|
||||
<span className="text-zinc-300">: </span>
|
||||
<span className="text-green-400">'123456789'</span>
|
||||
{"\n"}
|
||||
<span className="text-zinc-300">{"});"}</span>
|
||||
{"\n\n"}
|
||||
<span className="text-zinc-600">// Sync achievements, inventory, progress</span>
|
||||
{"\n"}
|
||||
<span className="text-purple-400">await</span>
|
||||
<span className="text-blue-300"> client</span>
|
||||
<span className="text-zinc-300">.</span>
|
||||
<span className="text-yellow-300">sync</span>
|
||||
<span className="text-zinc-300">{"({"}</span>
|
||||
{"\n"}
|
||||
<span className="text-zinc-300">{" "}</span>
|
||||
<span className="text-blue-300">achievements</span>
|
||||
<span className="text-zinc-300">: </span>
|
||||
<span className="text-blue-300">user</span>
|
||||
<span className="text-zinc-300">.achievements,</span>
|
||||
{"\n"}
|
||||
<span className="text-zinc-300">{" "}</span>
|
||||
<span className="text-blue-300">inventory</span>
|
||||
<span className="text-zinc-300">: </span>
|
||||
<span className="text-blue-300">user</span>
|
||||
<span className="text-zinc-300">.inventory,</span>
|
||||
{"\n"}
|
||||
<span className="text-zinc-300">{" "}</span>
|
||||
<span className="text-blue-300">progress</span>
|
||||
<span className="text-zinc-300">: </span>
|
||||
<span className="text-blue-300">user</span>
|
||||
<span className="text-zinc-300">.gameProgress</span>
|
||||
{"\n"}
|
||||
<span className="text-zinc-300">{"});"}</span>
|
||||
</code>
|
||||
</pre>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Platforms */}
|
||||
<section className="py-6 px-4 border-y border-border/30">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<div className="flex flex-wrap items-center justify-center gap-6 md:gap-10 text-muted-foreground">
|
||||
<span className="text-sm font-medium">Works with:</span>
|
||||
{platforms.map((platform) => (
|
||||
<span key={platform} className="text-sm font-medium hover:text-foreground transition-colors cursor-default">
|
||||
{platform}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Ecosystem Pillars */}
|
||||
<section className="py-20 px-4">
|
||||
<div className="max-w-6xl mx-auto space-y-12">
|
||||
<div className="text-center space-y-4">
|
||||
<h2 className="text-3xl md:text-4xl font-bold">The AeThex Ecosystem</h2>
|
||||
<p className="text-muted-foreground max-w-2xl mx-auto">
|
||||
Six interconnected realms with specialized APIs for every use case
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-5">
|
||||
{ecosystemPillars.map((pillar) => (
|
||||
<Link key={pillar.title} to={pillar.href}>
|
||||
<Card className="group p-6 h-full hover:border-primary/40 transition-all duration-200 hover:shadow-lg hover:shadow-primary/5">
|
||||
<div className="space-y-4">
|
||||
<div className={`w-14 h-14 rounded-xl bg-gradient-to-br ${pillar.gradient} flex items-center justify-center shadow-lg group-hover:scale-105 transition-transform`}>
|
||||
<pillar.icon className="w-7 h-7 text-white" />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<h3 className="text-xl font-semibold group-hover:text-primary transition-colors">
|
||||
{pillar.title}
|
||||
</h3>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
{pillar.description}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center text-primary text-sm font-medium group-hover:translate-x-1 transition-transform">
|
||||
Explore <ArrowRight className="w-4 h-4 ml-1" />
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Features */}
|
||||
<section className="py-20 px-4 bg-muted/30">
|
||||
<div className="max-w-6xl mx-auto space-y-12">
|
||||
<div className="text-center space-y-4">
|
||||
<h2 className="text-3xl md:text-4xl font-bold">Built for game developers</h2>
|
||||
<p className="text-muted-foreground max-w-2xl mx-auto">
|
||||
Everything you need to connect players across platforms
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-5">
|
||||
{features.map((feature) => (
|
||||
<Card key={feature.title} className="p-5 space-y-3">
|
||||
<div className="w-11 h-11 rounded-lg bg-primary/10 flex items-center justify-center">
|
||||
<feature.icon className="w-5 h-5 text-primary" />
|
||||
</div>
|
||||
<h3 className="font-semibold">{feature.title}</h3>
|
||||
<p className="text-sm text-muted-foreground">{feature.description}</p>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA */}
|
||||
<section className="py-20 px-4">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<Card className="p-8 md:p-12 text-center space-y-6 bg-gradient-to-br from-primary/10 via-primary/5 to-background border-primary/20">
|
||||
<Zap className="w-12 h-12 text-primary mx-auto" />
|
||||
<h2 className="text-3xl md:text-4xl font-bold">Start building today</h2>
|
||||
<p className="text-muted-foreground max-w-lg mx-auto">
|
||||
Get your API key and integrate in minutes. Free tier includes 10K API calls/month.
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-4 justify-center pt-2">
|
||||
<Link to="/dev-platform/dashboard">
|
||||
<Button size="lg" className="shadow-lg shadow-primary/25">
|
||||
Get API Key
|
||||
<ArrowRight className="w-4 h-4 ml-2" />
|
||||
</Button>
|
||||
</Link>
|
||||
<Link to="/dev-platform/quick-start">
|
||||
<Button size="lg" variant="outline">
|
||||
View Quick Start
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Footer spacer */}
|
||||
<div className="pb-16" />
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
|
@ -95,17 +95,17 @@ export default function Investors() {
|
|||
{
|
||||
icon: <Layers className="h-5 w-5" />,
|
||||
title: "Three Engines",
|
||||
desc: "Studios (services), Platform (community), and Labs (R&D) compound value together.",
|
||||
desc: "Studios, Platform, and Labs compound value.",
|
||||
},
|
||||
{
|
||||
icon: <Shield className="h-5 w-5" />,
|
||||
title: "Trust & Quality",
|
||||
desc: "Security-first engineering and measurable delivery keep churn low and NPS high.",
|
||||
desc: "Security-first engineering with measurable delivery.",
|
||||
},
|
||||
{
|
||||
icon: <Target className="h-5 w-5" />,
|
||||
title: "Focused Markets",
|
||||
desc: "High-signal segments: games, real-time apps, and experience platforms.",
|
||||
desc: "Games, real-time apps, and experience platforms.",
|
||||
},
|
||||
];
|
||||
|
||||
|
|
@ -134,13 +134,11 @@ export default function Investors() {
|
|||
<span className="mr-2 inline-flex h-2 w-2 animate-pulse rounded-full bg-red-300" />
|
||||
Investor Relations
|
||||
</Badge>
|
||||
<h1 className="text-4xl font-black tracking-tight text-red-300 sm:text-5xl lg:text-6xl">
|
||||
<h1 className="text-3xl font-black tracking-tight text-red-300 sm:text-4xl lg:text-5xl">
|
||||
AeThex | Building With Conviction
|
||||
</h1>
|
||||
<p className="text-lg text-red-100/90 sm:text-xl">
|
||||
We craft reliable, loved software and the platform that powers
|
||||
creators. Explore our thesis, traction, and how to participate
|
||||
in compliant offerings.
|
||||
Reliable software and the platform powering creators. Explore our thesis and participation options.
|
||||
</p>
|
||||
<div className="flex flex-col gap-4 sm:flex-row">
|
||||
<Button
|
||||
|
|
|
|||
|
|
@ -154,9 +154,9 @@ export default function Labs() {
|
|||
{/* Cyberpunk Background Effects */}
|
||||
<div className="pointer-events-none absolute inset-0 opacity-[0.12] [background-image:radial-gradient(circle_at_top,#facc15_0,rgba(0,0,0,0.45)_55%,rgba(0,0,0,0.9)_100%)]" />
|
||||
<div className="pointer-events-none absolute inset-0 bg-[linear-gradient(transparent_0,transparent_calc(100%-1px),rgba(250,204,21,0.05)_calc(100%-1px))] bg-[length:100%_32px]" />
|
||||
<div className="pointer-events-none absolute inset-0 opacity-[0.08] [background-image:linear-gradient(90deg,rgba(251,191,36,0.1)_1px,transparent_1px),linear-gradient(0deg,rgba(251,191,36,0.1)_1px,transparent_1px)] [background-size:50px_50px] animate-pulse" />
|
||||
<div className="pointer-events-none absolute top-20 left-10 w-96 h-96 bg-yellow-500/20 rounded-full mix-blend-multiply filter blur-3xl animate-pulse" />
|
||||
<div className="pointer-events-none absolute bottom-20 right-10 w-96 h-96 bg-yellow-600/10 rounded-full mix-blend-multiply filter blur-3xl animate-pulse" />
|
||||
<div className="pointer-events-none absolute inset-0 opacity-[0.08] [background-image:linear-gradient(90deg,rgba(251,191,36,0.1)_1px,transparent_1px),linear-gradient(0deg,rgba(251,191,36,0.1)_1px,transparent_1px)] [background-size:50px_50px]" />
|
||||
<div className="pointer-events-none absolute top-20 left-10 w-96 h-96 bg-yellow-500/20 rounded-full mix-blend-multiply filter blur-3xl" />
|
||||
<div className="pointer-events-none absolute bottom-20 right-10 w-96 h-96 bg-yellow-600/10 rounded-full mix-blend-multiply filter blur-3xl" />
|
||||
|
||||
<main className="relative z-10">
|
||||
{/* Hero Section */}
|
||||
|
|
@ -177,12 +177,12 @@ export default function Labs() {
|
|||
Advanced Research & Development
|
||||
</Badge>
|
||||
|
||||
<h1 className={`text-5xl md:text-6xl lg:text-7xl font-black text-yellow-300 leading-tight ${theme.fontClass}`}>
|
||||
<h1 className={`text-5xl md:text-6xl lg:text-7xl font-bold text-yellow-300 leading-tight ${theme.fontClass}`}>
|
||||
The Innovation Engine
|
||||
</h1>
|
||||
|
||||
<p className="text-xl md:text-2xl text-yellow-100/80 max-w-3xl mx-auto leading-relaxed">
|
||||
Breakthrough R&D pushing the boundaries of what's possible in software, AI, games, and digital experiences.
|
||||
<p className="text-lg md:text-xl text-yellow-100/80 max-w-3xl mx-auto leading-relaxed">
|
||||
Breakthrough R&D in software, AI, and games
|
||||
</p>
|
||||
|
||||
{/* TL;DR Section */}
|
||||
|
|
|
|||
|
|
@ -123,14 +123,12 @@ export default function Nexus() {
|
|||
AeThex Nexus
|
||||
</Badge>
|
||||
|
||||
<h1 className="text-4xl font-black tracking-tight text-purple-300 sm:text-5xl lg:text-6xl">
|
||||
<h1 className="text-4xl font-bold tracking-tight text-purple-300 sm:text-5xl">
|
||||
The Talent Nexus
|
||||
</h1>
|
||||
|
||||
<p className="text-lg text-purple-100/90 sm:text-xl">
|
||||
Connect creators with opportunities across all AeThex arms.
|
||||
Find talent, post jobs, and build amazing teams in a unified
|
||||
marketplace powered by both AeThex and DevConnect.
|
||||
<p className="text-base text-purple-100/90">
|
||||
Connect creators with opportunities across all AeThex arms
|
||||
</p>
|
||||
|
||||
<div className="flex flex-col sm:flex-row gap-4">
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ export default function Projects() {
|
|||
Projects & Testimonials
|
||||
</h1>
|
||||
<p className="text-muted-foreground max-w-2xl mt-1">
|
||||
Studio initiatives across AeThex Platform, Labs, and Studio.
|
||||
AeThex showcase portfolio
|
||||
</p>
|
||||
</div>
|
||||
{isOwner && (
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ export default function Realms() {
|
|||
/>
|
||||
</div>
|
||||
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 py-8 lg:py-12 max-w-6xl relative">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 py-8 lg:py-12 max-w-6xl relative space-y-20">
|
||||
{/* Hero Section */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
|
|
@ -91,10 +91,8 @@ export default function Realms() {
|
|||
Choose Your{" "}
|
||||
<span className="text-primary drop-shadow-[0_0_25px_rgba(168,85,247,0.8)]">Realm</span>
|
||||
</h1>
|
||||
<p className="text-xl md:text-2xl text-muted-foreground max-w-3xl mx-auto font-light">
|
||||
Each realm has unique tools, communities, and opportunities.
|
||||
<br className="hidden md:block" />
|
||||
Your dashboard adapts to your choice.
|
||||
<p className="text-lg md:text-xl text-muted-foreground max-w-3xl mx-auto font-light">
|
||||
Unique tools and communities for every role
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ export default function Squads() {
|
|||
return (
|
||||
<Layout>
|
||||
<div className="min-h-screen bg-[radial-gradient(circle_at_top,_rgba(110,141,255,0.12),transparent_60%)]">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 py-8 lg:py-12 max-w-6xl space-y-8">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 py-8 lg:py-12 max-w-6xl space-y-12">
|
||||
{/* Header */}
|
||||
<section className="rounded-3xl border border-border/40 bg-background/80 p-6 shadow-2xl backdrop-blur">
|
||||
<div className="flex items-start justify-between">
|
||||
|
|
@ -96,8 +96,7 @@ export default function Squads() {
|
|||
Squads Hub
|
||||
</h1>
|
||||
<p className="mt-1 text-sm text-muted-foreground">
|
||||
Form squads and ship projects together. Match by skill,
|
||||
timezone, and goals.
|
||||
Form squads and ship projects together
|
||||
</p>
|
||||
</div>
|
||||
<div className="hidden sm:block p-3 rounded-2xl bg-gradient-to-br from-aethex-500/10 to-neon-blue/10">
|
||||
|
|
|
|||
|
|
@ -102,11 +102,11 @@ export default function Teams() {
|
|||
return (
|
||||
<Layout>
|
||||
<div className="min-h-screen bg-[radial-gradient(circle_at_top,_rgba(110,141,255,0.12),transparent_60%)]">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 py-8 lg:py-12 max-w-6xl space-y-8">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 py-8 lg:py-12 max-w-6xl space-y-12">
|
||||
<section className="rounded-3xl border border-border/40 bg-background/80 p-6 shadow-2xl backdrop-blur">
|
||||
<h1 className="text-3xl font-semibold text-foreground">Teams</h1>
|
||||
<p className="mt-1 text-sm text-muted-foreground">
|
||||
Create a team and collaborate with members across projects.
|
||||
Collaborate across projects
|
||||
</p>
|
||||
</section>
|
||||
|
||||
|
|
|
|||
|
|
@ -30,12 +30,11 @@ export default function Trust() {
|
|||
<Badge variant="outline" className="mx-auto">
|
||||
Transparency
|
||||
</Badge>
|
||||
<h1 className="text-4xl font-bold text-gradient-purple">
|
||||
<h1 className="text-3xl font-bold text-gradient-purple">
|
||||
Company & Governance
|
||||
</h1>
|
||||
<p className="text-muted-foreground max-w-3xl mx-auto">
|
||||
Clear, verifiable information about AeThex: leadership, legal
|
||||
entity, jurisdiction, policies, and status.
|
||||
Leadership, legal entity, jurisdiction, policies, and status.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
|
@ -91,17 +90,13 @@ export default function Trust() {
|
|||
<CardContent className="text-sm text-muted-foreground space-y-2">
|
||||
<ul className="list-disc pl-5 space-y-1">
|
||||
<li>
|
||||
Phased disclosures cadence: Phase 1 (executive roster +
|
||||
roles), Phase 2 (board/advisor bios and affiliations), Phase
|
||||
3 (jurisdictional filings & compliance references).
|
||||
Phase 1: executive roster & roles | Phase 2: board/advisor profiles | Phase 3: compliance filings.
|
||||
</li>
|
||||
<li>
|
||||
Operational policies and escalation paths are documented in
|
||||
the Transparency hub.
|
||||
Policies and escalation paths in Transparency hub.
|
||||
</li>
|
||||
<li>
|
||||
Verified channels: website, docs, and official social
|
||||
accounts noted below.
|
||||
Verified channels: website, docs, and social accounts.
|
||||
</li>
|
||||
</ul>
|
||||
<div className="text-xs text-muted-foreground/80">
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ export default function AdminEthosVerification() {
|
|||
setRequests(data);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
toast.error("Failed to load verification requests");
|
||||
toast.error({ title: "Failed to load verification requests" });
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
|
|
@ -124,11 +124,11 @@ export default function AdminEthosVerification() {
|
|||
|
||||
if (!response.ok) throw new Error(`Failed to ${confirmAction} artist`);
|
||||
|
||||
toast.success(
|
||||
confirmAction === "approve"
|
||||
toast.success({
|
||||
title: confirmAction === "approve"
|
||||
? "Artist verified successfully! Email sent."
|
||||
: "Artist application rejected. Email sent.",
|
||||
);
|
||||
});
|
||||
|
||||
setIsConfirming(false);
|
||||
setSelectedRequest(null);
|
||||
|
|
@ -136,7 +136,7 @@ export default function AdminEthosVerification() {
|
|||
fetchRequests();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
toast.error(`Failed to ${confirmAction} artist`);
|
||||
toast.error({ title: `Failed to ${confirmAction} artist` });
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
436
client/pages/dev-platform/AethexLang.tsx
Normal file
|
|
@ -0,0 +1,436 @@
|
|||
import Layout from "@/components/Layout";
|
||||
import SEO from "@/components/SEO";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { Link } from "react-router-dom";
|
||||
import {
|
||||
Package,
|
||||
Shield,
|
||||
Users,
|
||||
Zap,
|
||||
Copy,
|
||||
CheckCircle2,
|
||||
ArrowRight,
|
||||
ExternalLink,
|
||||
Github,
|
||||
Terminal,
|
||||
Code,
|
||||
Lock,
|
||||
Globe,
|
||||
FileText,
|
||||
} from "lucide-react";
|
||||
import { useState } from "react";
|
||||
|
||||
const PACKAGE_VERSION = "1.0.0";
|
||||
|
||||
const features = [
|
||||
{
|
||||
icon: Users,
|
||||
title: "Passport",
|
||||
description: "Universal identity across platforms - authenticate users seamlessly on Roblox, web, and more",
|
||||
color: "text-blue-500",
|
||||
bgColor: "bg-blue-500/10",
|
||||
},
|
||||
{
|
||||
icon: Zap,
|
||||
title: "DataSync",
|
||||
description: "Cross-platform data synchronization for real-time state management",
|
||||
color: "text-yellow-500",
|
||||
bgColor: "bg-yellow-500/10",
|
||||
},
|
||||
{
|
||||
icon: Shield,
|
||||
title: "SafeInput",
|
||||
description: "PII detection and scrubbing - critical for CODEX and child safety compliance",
|
||||
color: "text-green-500",
|
||||
bgColor: "bg-green-500/10",
|
||||
},
|
||||
{
|
||||
icon: Lock,
|
||||
title: "Compliance",
|
||||
description: "Built-in COPPA/FERPA compliance checks with audit trail logging",
|
||||
color: "text-purple-500",
|
||||
bgColor: "bg-purple-500/10",
|
||||
},
|
||||
];
|
||||
|
||||
const platforms = [
|
||||
{ name: "Roblox", supported: true },
|
||||
{ name: "UEFN", supported: true },
|
||||
{ name: "Unity", supported: true },
|
||||
{ name: "Web", supported: true },
|
||||
{ name: "Node.js", supported: true },
|
||||
];
|
||||
|
||||
const codeExamples = {
|
||||
passport: `const { Passport } = require('@aethex.os/core');
|
||||
|
||||
const passport = new Passport('user123', 'PlayerOne');
|
||||
await passport.verify();
|
||||
await passport.syncAcross(['roblox', 'web']);`,
|
||||
safeinput: `const { SafeInput } = require('@aethex.os/core');
|
||||
|
||||
// Detect PII
|
||||
const detected = SafeInput.detectPII('Call me at 555-1234');
|
||||
// Returns: ['phone']
|
||||
|
||||
// Scrub PII
|
||||
const clean = SafeInput.scrub('My email is user@example.com');
|
||||
// Returns: 'My email is [EMAIL_REDACTED]'
|
||||
|
||||
// Validate input
|
||||
const result = SafeInput.validate('PlayerName123');
|
||||
if (result.valid) {
|
||||
console.log('Safe to use');
|
||||
}`,
|
||||
compliance: `const { Compliance } = require('@aethex.os/core');
|
||||
|
||||
// Age gate
|
||||
if (Compliance.isCOPPACompliant(userAge)) {
|
||||
// User is 13+
|
||||
}
|
||||
|
||||
// Check data collection permission
|
||||
if (Compliance.canCollectData(user)) {
|
||||
// Safe to collect
|
||||
}
|
||||
|
||||
// Log compliance check for audit
|
||||
Compliance.logCheck(userId, 'leaderboard_submission', true);`,
|
||||
datasync: `const { DataSync } = require('@aethex.os/core');
|
||||
|
||||
// Sync data across platforms
|
||||
await DataSync.sync({
|
||||
inventory: playerInventory,
|
||||
progress: gameProgress
|
||||
}, ['roblox', 'web']);
|
||||
|
||||
// Pull data from specific platform
|
||||
const data = await DataSync.pull(userId, 'roblox');`,
|
||||
};
|
||||
|
||||
function CopyButton({ text }: { text: string }) {
|
||||
const [copied, setCopied] = useState(false);
|
||||
|
||||
const handleCopy = async () => {
|
||||
await navigator.clipboard.writeText(text);
|
||||
setCopied(true);
|
||||
setTimeout(() => setCopied(false), 2000);
|
||||
};
|
||||
|
||||
return (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={handleCopy}
|
||||
className="absolute top-2 right-2 h-8 w-8 p-0"
|
||||
>
|
||||
{copied ? (
|
||||
<CheckCircle2 className="h-4 w-4 text-green-500" />
|
||||
) : (
|
||||
<Copy className="h-4 w-4" />
|
||||
)}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
function CodeBlock({ code, language = "javascript" }: { code: string; language?: string }) {
|
||||
return (
|
||||
<div className="relative">
|
||||
<CopyButton text={code} />
|
||||
<pre className="bg-slate-900 border border-slate-700 rounded-lg p-4 overflow-x-auto">
|
||||
<code className="text-sm text-slate-300 font-mono">{code}</code>
|
||||
</pre>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function AethexLang() {
|
||||
return (
|
||||
<Layout>
|
||||
<SEO
|
||||
pageTitle="@aethex.os/core | AeThex Language Standard Library"
|
||||
description="Cross-platform utilities for authentication, data sync, and compliance. Build safer metaverse experiences with built-in COPPA support."
|
||||
/>
|
||||
<div className="space-y-16">
|
||||
{/* Hero Section */}
|
||||
<section className="text-center max-w-4xl mx-auto space-y-6">
|
||||
<div className="flex items-center justify-center gap-3 mb-4">
|
||||
<Badge className="text-sm px-4 py-1 bg-purple-500/20 text-purple-400 border-purple-500/30">
|
||||
v{PACKAGE_VERSION}
|
||||
</Badge>
|
||||
<Badge variant="outline" className="text-sm px-4 py-1">
|
||||
MIT License
|
||||
</Badge>
|
||||
</div>
|
||||
<h1 className="text-5xl font-bold tracking-tight">
|
||||
<span className="text-primary">@aethex.os/core</span>
|
||||
</h1>
|
||||
<p className="text-xl text-muted-foreground max-w-2xl mx-auto">
|
||||
AeThex Language Standard Library — Cross-platform utilities for authentication,
|
||||
data sync, and compliance across the metaverse.
|
||||
</p>
|
||||
|
||||
{/* Install Command */}
|
||||
<div className="relative max-w-md mx-auto">
|
||||
<div className="flex items-center gap-3 bg-slate-900 border border-slate-700 rounded-lg px-4 py-3">
|
||||
<Terminal className="h-5 w-5 text-slate-500" />
|
||||
<code className="text-sm font-mono text-slate-300 flex-1 text-left">
|
||||
npm install @aethex.os/core
|
||||
</code>
|
||||
<CopyButton text="npm install @aethex.os/core" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-4 justify-center pt-4">
|
||||
<a
|
||||
href="https://www.npmjs.com/package/@aethex.os/core"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Button size="lg">
|
||||
<Package className="w-4 h-4 mr-2" />
|
||||
View on npm
|
||||
<ExternalLink className="w-4 h-4 ml-2" />
|
||||
</Button>
|
||||
</a>
|
||||
<a
|
||||
href="https://github.com/AeThex-Corporation/AeThexOS"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Button size="lg" variant="outline">
|
||||
<Github className="w-4 h-4 mr-2" />
|
||||
GitHub
|
||||
</Button>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Platform Support */}
|
||||
<section className="text-center">
|
||||
<p className="text-sm text-muted-foreground mb-4">Works everywhere you build</p>
|
||||
<div className="flex flex-wrap justify-center gap-3">
|
||||
{platforms.map((platform) => (
|
||||
<Badge
|
||||
key={platform.name}
|
||||
variant="outline"
|
||||
className="px-4 py-2 text-sm"
|
||||
>
|
||||
<Globe className="w-3 h-3 mr-2" />
|
||||
{platform.name}
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Features Grid */}
|
||||
<section>
|
||||
<h2 className="text-3xl font-bold text-center mb-4">Core Modules</h2>
|
||||
<p className="text-center text-muted-foreground mb-12 max-w-2xl mx-auto">
|
||||
Everything you need to build safe, compliant, cross-platform experiences
|
||||
</p>
|
||||
<div className="grid md:grid-cols-2 gap-6">
|
||||
{features.map((feature) => (
|
||||
<Card key={feature.title} className="p-6 hover:border-primary/50 transition-all">
|
||||
<div className={`w-12 h-12 rounded-lg ${feature.bgColor} flex items-center justify-center mb-4`}>
|
||||
<feature.icon className={`w-6 h-6 ${feature.color}`} />
|
||||
</div>
|
||||
<h3 className="text-xl font-semibold mb-2">{feature.title}</h3>
|
||||
<p className="text-muted-foreground">{feature.description}</p>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Code Examples */}
|
||||
<section>
|
||||
<h2 className="text-3xl font-bold text-center mb-4">Quick Examples</h2>
|
||||
<p className="text-center text-muted-foreground mb-8 max-w-2xl mx-auto">
|
||||
Get started in minutes with these production-ready code snippets
|
||||
</p>
|
||||
|
||||
<Tabs defaultValue="passport" className="max-w-4xl mx-auto">
|
||||
<TabsList className="grid w-full grid-cols-4">
|
||||
<TabsTrigger value="passport">Passport</TabsTrigger>
|
||||
<TabsTrigger value="safeinput">SafeInput</TabsTrigger>
|
||||
<TabsTrigger value="compliance">Compliance</TabsTrigger>
|
||||
<TabsTrigger value="datasync">DataSync</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent value="passport" className="mt-6">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Users className="w-5 h-5 text-blue-500" />
|
||||
Passport - Universal Identity
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
Authenticate users once, verify them everywhere
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CodeBlock code={codeExamples.passport} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
<TabsContent value="safeinput" className="mt-6">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Shield className="w-5 h-5 text-green-500" />
|
||||
SafeInput - PII Detection
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
Detect and scrub personally identifiable information automatically
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CodeBlock code={codeExamples.safeinput} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
<TabsContent value="compliance" className="mt-6">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Lock className="w-5 h-5 text-purple-500" />
|
||||
Compliance - COPPA/FERPA
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
Built-in compliance checks with audit trail logging
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CodeBlock code={codeExamples.compliance} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
<TabsContent value="datasync" className="mt-6">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Zap className="w-5 h-5 text-yellow-500" />
|
||||
DataSync - Cross-Platform State
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
Synchronize data across all supported platforms
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CodeBlock code={codeExamples.datasync} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</section>
|
||||
|
||||
{/* API Reference */}
|
||||
<section>
|
||||
<Card className="bg-gradient-to-br from-slate-800/50 to-purple-900/20 border-purple-500/20">
|
||||
<CardContent className="p-8">
|
||||
<div className="grid md:grid-cols-2 gap-8">
|
||||
<div>
|
||||
<h3 className="text-2xl font-bold mb-4">API Reference</h3>
|
||||
<div className="space-y-4 text-sm">
|
||||
<div>
|
||||
<h4 className="font-semibold text-purple-400 mb-2">Passport</h4>
|
||||
<ul className="space-y-1 text-muted-foreground">
|
||||
<li><code className="text-xs bg-slate-800 px-1 rounded">new Passport(userId, username)</code> - Create passport</li>
|
||||
<li><code className="text-xs bg-slate-800 px-1 rounded">verify()</code> - Verify identity</li>
|
||||
<li><code className="text-xs bg-slate-800 px-1 rounded">syncAcross(platforms)</code> - Sync across platforms</li>
|
||||
<li><code className="text-xs bg-slate-800 px-1 rounded">toJSON()</code> - Export as JSON</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-semibold text-green-400 mb-2">SafeInput</h4>
|
||||
<ul className="space-y-1 text-muted-foreground">
|
||||
<li><code className="text-xs bg-slate-800 px-1 rounded">SafeInput.detectPII(input)</code> - Detect PII types</li>
|
||||
<li><code className="text-xs bg-slate-800 px-1 rounded">SafeInput.scrub(input)</code> - Scrub PII from string</li>
|
||||
<li><code className="text-xs bg-slate-800 px-1 rounded">SafeInput.validate(input)</code> - Validate input safety</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="space-y-4 text-sm">
|
||||
<div>
|
||||
<h4 className="font-semibold text-yellow-400 mb-2">DataSync</h4>
|
||||
<ul className="space-y-1 text-muted-foreground">
|
||||
<li><code className="text-xs bg-slate-800 px-1 rounded">DataSync.sync(data, platforms)</code> - Sync data</li>
|
||||
<li><code className="text-xs bg-slate-800 px-1 rounded">DataSync.pull(userId, platform)</code> - Pull data</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-semibold text-purple-400 mb-2">Compliance</h4>
|
||||
<ul className="space-y-1 text-muted-foreground">
|
||||
<li><code className="text-xs bg-slate-800 px-1 rounded">Compliance.isCOPPACompliant(age)</code> - Check if 13+</li>
|
||||
<li><code className="text-xs bg-slate-800 px-1 rounded">Compliance.requiresParentConsent(age)</code> - Check if <13</li>
|
||||
<li><code className="text-xs bg-slate-800 px-1 rounded">Compliance.canCollectData(user)</code> - Check permission</li>
|
||||
<li><code className="text-xs bg-slate-800 px-1 rounded">Compliance.logCheck(userId, type, result)</code> - Audit log</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</section>
|
||||
|
||||
{/* Keywords/Use Cases */}
|
||||
<section className="text-center">
|
||||
<p className="text-sm text-muted-foreground mb-4">Built for</p>
|
||||
<div className="flex flex-wrap justify-center gap-2">
|
||||
{["metaverse", "cross-platform", "roblox", "uefn", "unity", "coppa", "compliance", "pii-detection"].map((keyword) => (
|
||||
<Badge key={keyword} variant="secondary" className="px-3 py-1">
|
||||
{keyword}
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA */}
|
||||
<section className="text-center space-y-6 py-8">
|
||||
<h2 className="text-3xl font-bold">Ready to Build?</h2>
|
||||
<p className="text-muted-foreground max-w-xl mx-auto">
|
||||
Start building safer, compliant cross-platform experiences today.
|
||||
</p>
|
||||
<div className="flex gap-4 justify-center">
|
||||
<Link to="/docs/lang/quickstart">
|
||||
<Button size="lg">
|
||||
Quick Start Guide
|
||||
<ArrowRight className="w-4 h-4 ml-2" />
|
||||
</Button>
|
||||
</Link>
|
||||
<Link to="/docs/lang">
|
||||
<Button size="lg" variant="outline">
|
||||
<FileText className="w-4 h-4 mr-2" />
|
||||
Full Documentation
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Footer Info */}
|
||||
<section className="text-center text-sm text-muted-foreground border-t border-border/50 pt-8">
|
||||
<p>
|
||||
Maintained by{" "}
|
||||
<a href="https://aethex.dev" className="text-primary hover:underline">
|
||||
AeThex Foundation
|
||||
</a>
|
||||
{" · "}
|
||||
<a
|
||||
href="https://github.com/AeThex-Corporation/AeThexOS/issues"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-primary hover:underline"
|
||||
>
|
||||
Report Issues
|
||||
</a>
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
|
@ -67,9 +67,7 @@ await game.deploy(['roblox', 'fortnite', 'web']);`;
|
|||
<span className="text-primary">Deploy Everywhere.</span>
|
||||
</h1>
|
||||
<p className="mt-6 text-lg text-muted-foreground sm:text-xl">
|
||||
The complete developer platform for building cross-platform games
|
||||
with AeThex. Ship to Roblox, Fortnite, Web, and Mobile from a
|
||||
single codebase.
|
||||
Ship to Roblox, Fortnite, Web, and Mobile from one codebase
|
||||
</p>
|
||||
<div className="mt-10 flex flex-col gap-4 sm:flex-row sm:justify-center">
|
||||
<Link to="/docs/getting-started">
|
||||
|
|
@ -118,9 +116,7 @@ await game.deploy(['roblox', 'fortnite', 'web']);`;
|
|||
Simple. Powerful. Universal.
|
||||
</h2>
|
||||
<p className="text-lg text-muted-foreground">
|
||||
Write your game logic once using the AeThex SDK, then deploy
|
||||
to all major platforms with a single command. No
|
||||
platform-specific code required.
|
||||
Write once, deploy everywhere. No platform-specific code.
|
||||
</p>
|
||||
<ul className="space-y-3">
|
||||
{[
|
||||
|
|
@ -160,7 +156,7 @@ await game.deploy(['roblox', 'fortnite', 'web']);`;
|
|||
<div className="text-center mb-12">
|
||||
<h2 className="text-3xl font-bold">Everything You Need</h2>
|
||||
<p className="text-lg text-muted-foreground mt-4">
|
||||
Build production-ready games with enterprise-grade infrastructure
|
||||
Enterprise-grade infrastructure
|
||||
</p>
|
||||
</div>
|
||||
<div className="grid gap-8 md:grid-cols-2">
|
||||
|
|
@ -185,7 +181,7 @@ await game.deploy(['roblox', 'fortnite', 'web']);`;
|
|||
<div className="text-center mb-12">
|
||||
<h2 className="text-3xl font-bold">Developer Tools</h2>
|
||||
<p className="text-lg text-muted-foreground mt-4">
|
||||
Everything you need to build, test, and deploy your games
|
||||
Build, test, and deploy
|
||||
</p>
|
||||
</div>
|
||||
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-4">
|
||||
|
|
|
|||
|
|
@ -110,13 +110,11 @@ export default function DocsApiReference() {
|
|||
<ServerCog className="mr-2 h-3 w-3" />
|
||||
API Reference
|
||||
</Badge>
|
||||
<h2 className="text-3xl font-semibold text-white">
|
||||
Integrate programmatically with the AeThex API
|
||||
<h2 className="text-2xl font-semibold text-white">
|
||||
REST API reference and integration guide
|
||||
</h2>
|
||||
<p className="text-gray-300 max-w-3xl">
|
||||
The REST API exposes every core capability of the AeThex platform.
|
||||
Authenticate with OAuth 2.1 or personal access tokens, call idempotent
|
||||
endpoints, and subscribe to webhooks to react to changes in real time.
|
||||
Authenticate with OAuth or access tokens, call idempotent endpoints, and subscribe to webhooks for real-time updates.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
|
|
|
|||
|
|
@ -88,14 +88,11 @@ export default function DocsCli() {
|
|||
<Terminal className="mr-2 h-3 w-3" />
|
||||
CLI Tools
|
||||
</Badge>
|
||||
<h2 className="text-3xl font-semibold text-white">
|
||||
Operate AeThex from the command line
|
||||
<h2 className="text-2xl font-semibold text-white">
|
||||
Command-line tools for development and deployment
|
||||
</h2>
|
||||
<p className="text-gray-300 max-w-3xl">
|
||||
The AeThex CLI automates local development, environment management,
|
||||
and production deployments. It is built with stability in mind,
|
||||
featuring transactional deploys, shell-friendly output, and native
|
||||
support for Linux, macOS, and Windows.
|
||||
Automate local development, environment management, and production deployments with cross-platform support.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ const curriculumModules: CurriculumModule[] = [
|
|||
id: "foundations",
|
||||
title: "AeThex Foundations",
|
||||
description:
|
||||
"Establish core mastery of the AeThex platform, from environment setup to shipping your first interactive experience.",
|
||||
"Master platform basics from setup to deployment.",
|
||||
duration: "2.5 hrs",
|
||||
level: "foundation",
|
||||
focus: [
|
||||
|
|
@ -129,7 +129,7 @@ const curriculumModules: CurriculumModule[] = [
|
|||
id: "builder",
|
||||
title: "Product Builder Track",
|
||||
description:
|
||||
"Design and scale collaborative communities with AeThex real-time tooling, automations, and membership flows.",
|
||||
"Build collaborative communities with real-time tools and automations.",
|
||||
duration: "3 hrs",
|
||||
level: "builder",
|
||||
focus: ["Community feed", "Workflow automations", "Admin control center"],
|
||||
|
|
@ -184,7 +184,7 @@ const curriculumModules: CurriculumModule[] = [
|
|||
id: "advanced",
|
||||
title: "Advanced Ops & Ecosystems",
|
||||
description:
|
||||
"Engineer large-scale AeThex deployments that blend AI-guided creation, marketplace integrations, and monetization.",
|
||||
"Scale deployments with AI, marketplace, and monetization features.",
|
||||
duration: "3.5 hrs",
|
||||
level: "advanced",
|
||||
focus: ["AI pipelines", "Marketplace", "Monetization"],
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ const exampleSnippets = [
|
|||
{
|
||||
title: "Server-side matchmaking",
|
||||
description:
|
||||
"Quickly assemble a matchmaking service that uses AeThex queues, weighting rules, and player telemetry streams.",
|
||||
"Build matchmaking with queues, weighting rules, and telemetry.",
|
||||
language: "TypeScript",
|
||||
href: "https://github.com/aethex/examples/tree/main/matchmaking-service",
|
||||
code: `import { createQueue, matchPlayers } from "@aethex/matchmaking";
|
||||
|
|
@ -54,7 +54,7 @@ export async function enqueuePlayer(player) {
|
|||
{
|
||||
title: "Realtime activity overlays",
|
||||
description:
|
||||
"Broadcast live deployment and incident updates to your in-game HUD or operations dashboard using AeThex events.",
|
||||
"Broadcast deployment updates to in-game HUD or dashboards.",
|
||||
language: "React",
|
||||
href: "https://github.com/aethex/examples/tree/main/realtime-overlay",
|
||||
code: `import { useEffect, useState } from "react";
|
||||
|
|
@ -142,13 +142,11 @@ export default function DocsExamples() {
|
|||
<Blocks className="mr-2 h-3 w-3" />
|
||||
Examples & Templates
|
||||
</Badge>
|
||||
<h2 className="text-3xl font-semibold text-white">
|
||||
Production-ready patterns you can copy
|
||||
<h2 className="text-2xl font-semibold text-white">
|
||||
Code examples and starter templates
|
||||
</h2>
|
||||
<p className="text-gray-300 max-w-3xl">
|
||||
Explore curated examples covering backend services, realtime overlays,
|
||||
automation scripts, and workflow integrations. Each project includes
|
||||
detailed READMEs, infrastructure diagrams, and deployment runbooks.
|
||||
Production-ready examples for backend services, real-time overlays, automation, and integrations.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
|
|
|
|||
|
|
@ -58,14 +58,14 @@ const prerequisites = [
|
|||
{
|
||||
title: "AeThex Account",
|
||||
description:
|
||||
"You will need an active AeThex account to access the dashboard, API console, and deployment tools.",
|
||||
"Active account required for dashboard and API access.",
|
||||
actionLabel: "Create account",
|
||||
actionHref: "/onboarding",
|
||||
},
|
||||
{
|
||||
title: "Node.js 18+ & npm",
|
||||
description:
|
||||
"The AeThex CLI relies on modern Node runtimes. Verify your local toolchain before continuing.",
|
||||
"Modern Node runtime required for CLI.",
|
||||
actionLabel: "Verify environment",
|
||||
actionHref: "https://nodejs.org/en/download",
|
||||
},
|
||||
|
|
@ -82,13 +82,13 @@ const setupSteps = [
|
|||
{
|
||||
title: "Install the CLI",
|
||||
description:
|
||||
"The CLI bootstraps local projects, provisions cloud environments, and manages deployments.",
|
||||
"Bootstrap projects and manage deployments.",
|
||||
command: "npm install -g aethex",
|
||||
},
|
||||
{
|
||||
title: "Authenticate",
|
||||
description:
|
||||
"Log in with your AeThex credentials or paste a personal access token from the dashboard.",
|
||||
"Log in with credentials or access token.",
|
||||
command: "aethex login",
|
||||
},
|
||||
{
|
||||
|
|
@ -196,8 +196,8 @@ export default function DocsGettingStarted() {
|
|||
<Rocket className="mr-2 h-3 w-3" />
|
||||
Getting Started
|
||||
</Badge>
|
||||
<h2 className="text-3xl font-semibold text-white">
|
||||
Launch your first AeThex project in under 30 minutes
|
||||
<h2 className="text-2xl font-semibold text-white">
|
||||
Launch your first project in 30 minutes
|
||||
</h2>
|
||||
<p className="text-gray-300 max-w-3xl">
|
||||
This guide walks through the minimum setup required to ship a
|
||||
|
|
|
|||
|
|
@ -101,15 +101,11 @@ export default function DocsIntegrations() {
|
|||
<Puzzle className="mr-2 h-3 w-3" />
|
||||
Integrations
|
||||
</Badge>
|
||||
<h2 className="text-3xl font-semibold text-white">
|
||||
Connecting partner services to AeThex
|
||||
<h2 className="text-2xl font-semibold text-white">
|
||||
Third-party integrations and connectors
|
||||
</h2>
|
||||
<p className="text-gray-300 max-w-3xl">
|
||||
AeThex Integrations wrap third-party analytics, identity, payments,
|
||||
and live-ops tooling behind a consistent runtime, security model, and
|
||||
visual system. Use this guide to register new connectors, surface
|
||||
partner UI in product flows, and automate data exchange without
|
||||
hand-rolled plumbing.
|
||||
Connect analytics, identity, payments, and live-ops tools with unified security and data exchange.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
|
|
@ -135,7 +131,7 @@ export default function DocsIntegrations() {
|
|||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<CardDescription className="text-gray-300">
|
||||
Open-source MIT-licensed engine with GDScript and C# support
|
||||
MIT-licensed engine with GDScript and C# support
|
||||
</CardDescription>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<Badge variant="secondary" className="bg-blue-500/20 text-blue-200">GDScript</Badge>
|
||||
|
|
@ -160,7 +156,7 @@ export default function DocsIntegrations() {
|
|||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<CardDescription className="text-gray-300">
|
||||
Powerful 2D engine with GML scripting for rapid game development
|
||||
2D engine with GML scripting for rapid development
|
||||
</CardDescription>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<Badge variant="secondary" className="bg-green-500/20 text-green-200">GML</Badge>
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ const platformPillars = [
|
|||
{
|
||||
title: "Unified dashboard",
|
||||
description:
|
||||
"Monitor deployments, live metrics, and release health from a single control surface. Jump into incidents, approvals, and audit trails without leaving the workspace.",
|
||||
"Monitor deployments, metrics, and incidents from a unified dashboard.",
|
||||
icon: LayoutDashboard,
|
||||
href: "/dashboard",
|
||||
cta: "Visit dashboard",
|
||||
|
|
@ -36,7 +36,7 @@ const platformPillars = [
|
|||
{
|
||||
title: "AeThex Passport",
|
||||
description:
|
||||
"Give builders portable identity with verified skills, achievements, and cross-product progress synced to their Passport profile.",
|
||||
"Portable identity with verified skills and achievements.",
|
||||
icon: IdCard,
|
||||
href: "/passport/me",
|
||||
cta: "Open passport",
|
||||
|
|
@ -169,14 +169,11 @@ export default function DocsPlatform() {
|
|||
<Sparkles className="mr-2 h-3 w-3" />
|
||||
Platform Experience
|
||||
</Badge>
|
||||
<h2 className="text-3xl font-semibold text-white">
|
||||
Deliver cohesive player and builder journeys on AeThex
|
||||
<h2 className="text-2xl font-semibold text-white">
|
||||
Platform overview and core features
|
||||
</h2>
|
||||
<p className="text-gray-300 max-w-3xl">
|
||||
Beyond deployment pipelines and CLI tooling, AeThex bundles
|
||||
collaboration, identity, and live-ops systems so teams can craft
|
||||
unforgettable experiences. Use this guide to orient new stakeholders
|
||||
and plan end-to-end platform rollouts.
|
||||
AeThex combines deployment pipelines, collaboration tools, identity systems, and live-ops features for building complete experiences.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
|
|
|
|||
379
client/pages/docs/lang/DocsLangCli.tsx
Normal file
|
|
@ -0,0 +1,379 @@
|
|||
import { Link } from "react-router-dom";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import {
|
||||
Terminal,
|
||||
CheckCircle2,
|
||||
Copy,
|
||||
ExternalLink,
|
||||
Package,
|
||||
} from "lucide-react";
|
||||
import { useState } from "react";
|
||||
|
||||
function CopyButton({ text }: { text: string }) {
|
||||
const [copied, setCopied] = useState(false);
|
||||
const handleCopy = async () => {
|
||||
await navigator.clipboard.writeText(text);
|
||||
setCopied(true);
|
||||
setTimeout(() => setCopied(false), 2000);
|
||||
};
|
||||
return (
|
||||
<button
|
||||
onClick={handleCopy}
|
||||
className="absolute top-3 right-3 p-1.5 rounded bg-slate-700 hover:bg-slate-600 transition-colors"
|
||||
>
|
||||
{copied ? <CheckCircle2 className="h-4 w-4 text-green-400" /> : <Copy className="h-4 w-4 text-slate-400" />}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
function CodeBlock({ code, language = "bash" }: { code: string; language?: string }) {
|
||||
return (
|
||||
<div className="relative">
|
||||
<CopyButton text={code} />
|
||||
<pre className="bg-slate-900 border border-slate-700 rounded-lg p-4 overflow-x-auto">
|
||||
<code className="text-sm text-slate-300 font-mono whitespace-pre">{code}</code>
|
||||
</pre>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const installCode = `npm install -g @aethex.os/cli`;
|
||||
|
||||
const compileBasicCode = `aethex compile myfile.aethex`;
|
||||
|
||||
const compileTargetCode = `# JavaScript (default)
|
||||
aethex compile myfile.aethex --target javascript
|
||||
|
||||
# Roblox/Lua
|
||||
aethex compile myfile.aethex --target roblox
|
||||
|
||||
# UEFN/Verse (coming soon)
|
||||
aethex compile myfile.aethex --target uefn
|
||||
|
||||
# Unity/C# (coming soon)
|
||||
aethex compile myfile.aethex --target unity`;
|
||||
|
||||
const outputCode = `aethex compile myfile.aethex -o output.js
|
||||
aethex compile myfile.aethex -t roblox -o game.lua`;
|
||||
|
||||
const watchCode = `aethex compile myfile.aethex --watch`;
|
||||
|
||||
const newProjectCode = `# Basic project
|
||||
aethex new my-project
|
||||
|
||||
# With template
|
||||
aethex new my-game --template passport`;
|
||||
|
||||
const initCode = `aethex init`;
|
||||
|
||||
const helloAethexCode = `reality HelloWorld {
|
||||
platforms: all
|
||||
}
|
||||
|
||||
journey Greet(name) {
|
||||
platform: all
|
||||
notify "Hello, " + name + "!"
|
||||
}`;
|
||||
|
||||
const commands = [
|
||||
{
|
||||
name: "compile",
|
||||
syntax: "aethex compile <file>",
|
||||
description: "Compile an AeThex file to the target platform",
|
||||
options: [
|
||||
{ flag: "-t, --target <platform>", description: "Target platform (javascript, roblox, uefn, unity)" },
|
||||
{ flag: "-o, --output <file>", description: "Output file path" },
|
||||
{ flag: "-w, --watch", description: "Watch for changes and recompile" },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "new",
|
||||
syntax: "aethex new <name>",
|
||||
description: "Create a new AeThex project",
|
||||
options: [
|
||||
{ flag: "--template <type>", description: "Project template (basic, passport, game)" },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "init",
|
||||
syntax: "aethex init",
|
||||
description: "Initialize AeThex in the current directory",
|
||||
options: [],
|
||||
},
|
||||
{
|
||||
name: "--help",
|
||||
syntax: "aethex --help",
|
||||
description: "Show help information",
|
||||
options: [],
|
||||
},
|
||||
{
|
||||
name: "--version",
|
||||
syntax: "aethex --version",
|
||||
description: "Show CLI version",
|
||||
options: [],
|
||||
},
|
||||
];
|
||||
|
||||
const targets = [
|
||||
{ name: "javascript", language: "JavaScript", platform: "Web, Node.js", status: "ready" },
|
||||
{ name: "roblox", language: "Lua", platform: "Roblox", status: "ready" },
|
||||
{ name: "uefn", language: "Verse", platform: "Fortnite", status: "coming" },
|
||||
{ name: "unity", language: "C#", platform: "Unity, VRChat", status: "coming" },
|
||||
];
|
||||
|
||||
export default function DocsLangCli() {
|
||||
return (
|
||||
<div className="space-y-12">
|
||||
{/* Header */}
|
||||
<section>
|
||||
<Badge className="mb-4 bg-green-500/20 text-green-400 border-green-500/30">
|
||||
@aethex.os/cli
|
||||
</Badge>
|
||||
<h1 className="text-4xl font-bold mb-4">CLI Reference</h1>
|
||||
<p className="text-xl text-muted-foreground">
|
||||
AeThex Language Command Line Interface - Compile <code className="bg-slate-800 px-2 py-0.5 rounded">.aethex</code> files
|
||||
to JavaScript, Lua, Verse, and C#.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
{/* Installation */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-4">Installation</h2>
|
||||
<CodeBlock code={installCode} />
|
||||
<p className="mt-4 text-sm text-muted-foreground">
|
||||
<a
|
||||
href="https://www.npmjs.com/package/@aethex.os/cli"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-primary hover:underline inline-flex items-center gap-1"
|
||||
>
|
||||
View on npm <ExternalLink className="w-3 h-3" />
|
||||
</a>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
{/* Usage */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-6">Usage</h2>
|
||||
|
||||
<div className="space-y-6">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Terminal className="w-5 h-5" />
|
||||
Compile a file
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CodeBlock code={compileBasicCode} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Compile to specific target</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CodeBlock code={compileTargetCode} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Save to file</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CodeBlock code={outputCode} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Watch mode</CardTitle>
|
||||
<CardDescription>Auto-recompile on file changes</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CodeBlock code={watchCode} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Create new project</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CodeBlock code={newProjectCode} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Initialize in existing directory</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CodeBlock code={initCode} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Example */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-4">Example</h2>
|
||||
<p className="text-muted-foreground mb-4">
|
||||
Create <code className="bg-slate-800 px-2 py-0.5 rounded">hello.aethex</code>:
|
||||
</p>
|
||||
<CodeBlock code={helloAethexCode} language="aethex" />
|
||||
<p className="text-muted-foreground mt-6 mb-4">Compile and run:</p>
|
||||
<CodeBlock code={`aethex compile hello.aethex -o hello.js
|
||||
node hello.js`} />
|
||||
</section>
|
||||
|
||||
{/* Commands Reference */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-6">Commands</h2>
|
||||
<div className="space-y-4">
|
||||
{commands.map((cmd) => (
|
||||
<Card key={cmd.name}>
|
||||
<CardHeader className="pb-2">
|
||||
<CardTitle className="font-mono text-lg">{cmd.syntax}</CardTitle>
|
||||
<CardDescription>{cmd.description}</CardDescription>
|
||||
</CardHeader>
|
||||
{cmd.options.length > 0 && (
|
||||
<CardContent>
|
||||
<div className="space-y-2">
|
||||
{cmd.options.map((opt) => (
|
||||
<div key={opt.flag} className="flex gap-4 text-sm">
|
||||
<code className="bg-slate-800 px-2 py-0.5 rounded whitespace-nowrap">{opt.flag}</code>
|
||||
<span className="text-muted-foreground">{opt.description}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</CardContent>
|
||||
)}
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Options */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-6">Global Options</h2>
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full border-collapse">
|
||||
<thead>
|
||||
<tr className="border-b border-slate-700">
|
||||
<th className="text-left py-3 px-4 font-medium">Option</th>
|
||||
<th className="text-left py-3 px-4 font-medium">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr className="border-b border-slate-800">
|
||||
<td className="py-3 px-4"><code className="bg-slate-800 px-2 py-0.5 rounded">-t, --target <platform></code></td>
|
||||
<td className="py-3 px-4 text-muted-foreground">Target platform (javascript, roblox, uefn, unity)</td>
|
||||
</tr>
|
||||
<tr className="border-b border-slate-800">
|
||||
<td className="py-3 px-4"><code className="bg-slate-800 px-2 py-0.5 rounded">-o, --output <file></code></td>
|
||||
<td className="py-3 px-4 text-muted-foreground">Output file path</td>
|
||||
</tr>
|
||||
<tr className="border-b border-slate-800">
|
||||
<td className="py-3 px-4"><code className="bg-slate-800 px-2 py-0.5 rounded">-w, --watch</code></td>
|
||||
<td className="py-3 px-4 text-muted-foreground">Watch for changes</td>
|
||||
</tr>
|
||||
<tr className="border-b border-slate-800">
|
||||
<td className="py-3 px-4"><code className="bg-slate-800 px-2 py-0.5 rounded">--template <type></code></td>
|
||||
<td className="py-3 px-4 text-muted-foreground">Project template (basic, passport, game)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Targets */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-6">Targets</h2>
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full border-collapse">
|
||||
<thead>
|
||||
<tr className="border-b border-slate-700">
|
||||
<th className="text-left py-3 px-4 font-medium">Target</th>
|
||||
<th className="text-left py-3 px-4 font-medium">Language</th>
|
||||
<th className="text-left py-3 px-4 font-medium">Platform</th>
|
||||
<th className="text-left py-3 px-4 font-medium">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{targets.map((target) => (
|
||||
<tr key={target.name} className="border-b border-slate-800">
|
||||
<td className="py-3 px-4">
|
||||
<code className="bg-slate-800 px-2 py-0.5 rounded">{target.name}</code>
|
||||
</td>
|
||||
<td className="py-3 px-4">{target.language}</td>
|
||||
<td className="py-3 px-4 text-muted-foreground">{target.platform}</td>
|
||||
<td className="py-3 px-4">
|
||||
{target.status === "ready" ? (
|
||||
<Badge className="bg-green-500/20 text-green-400 border-green-500/30">
|
||||
<CheckCircle2 className="w-3 h-3 mr-1" /> Ready
|
||||
</Badge>
|
||||
) : (
|
||||
<Badge variant="outline" className="text-slate-400">Coming Soon</Badge>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Learn More */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-6">Learn More</h2>
|
||||
<div className="grid md:grid-cols-3 gap-4">
|
||||
<Link to="/docs/lang">
|
||||
<Card className="h-full hover:border-primary/50 transition-all cursor-pointer">
|
||||
<CardContent className="pt-6">
|
||||
<Package className="w-6 h-6 mb-2 text-primary" />
|
||||
<h3 className="font-semibold">Language Guide</h3>
|
||||
<p className="text-sm text-muted-foreground">Full documentation</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Link>
|
||||
<Link to="/docs/lang/examples">
|
||||
<Card className="h-full hover:border-primary/50 transition-all cursor-pointer">
|
||||
<CardContent className="pt-6">
|
||||
<Terminal className="w-6 h-6 mb-2 text-green-500" />
|
||||
<h3 className="font-semibold">Examples</h3>
|
||||
<p className="text-sm text-muted-foreground">Code samples</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Link>
|
||||
<a
|
||||
href="https://www.npmjs.com/package/@aethex.os/core"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Card className="h-full hover:border-primary/50 transition-all cursor-pointer">
|
||||
<CardContent className="pt-6">
|
||||
<Package className="w-6 h-6 mb-2 text-purple-500" />
|
||||
<h3 className="font-semibold">@aethex.os/core</h3>
|
||||
<p className="text-sm text-muted-foreground">Standard Library</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Navigation */}
|
||||
<section className="flex justify-between pt-8 border-t border-border/50">
|
||||
<Link to="/docs/lang/syntax" className="text-sm text-muted-foreground hover:text-foreground">
|
||||
← Language Syntax
|
||||
</Link>
|
||||
<Link to="/docs/lang/examples" className="text-sm text-muted-foreground hover:text-foreground">
|
||||
Examples →
|
||||
</Link>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
414
client/pages/docs/lang/DocsLangExamples.tsx
Normal file
|
|
@ -0,0 +1,414 @@
|
|||
import { Link } from "react-router-dom";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import {
|
||||
CheckCircle2,
|
||||
Copy,
|
||||
Shield,
|
||||
Users,
|
||||
Award,
|
||||
Zap,
|
||||
Lock,
|
||||
} from "lucide-react";
|
||||
import { useState } from "react";
|
||||
|
||||
function CopyButton({ text }: { text: string }) {
|
||||
const [copied, setCopied] = useState(false);
|
||||
const handleCopy = async () => {
|
||||
await navigator.clipboard.writeText(text);
|
||||
setCopied(true);
|
||||
setTimeout(() => setCopied(false), 2000);
|
||||
};
|
||||
return (
|
||||
<button
|
||||
onClick={handleCopy}
|
||||
className="absolute top-3 right-3 p-1.5 rounded bg-slate-700 hover:bg-slate-600 transition-colors"
|
||||
>
|
||||
{copied ? <CheckCircle2 className="h-4 w-4 text-green-400" /> : <Copy className="h-4 w-4 text-slate-400" />}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
function CodeBlock({ code }: { code: string }) {
|
||||
return (
|
||||
<div className="relative">
|
||||
<CopyButton text={code} />
|
||||
<pre className="bg-slate-900 border border-slate-700 rounded-lg p-4 overflow-x-auto">
|
||||
<code className="text-sm text-slate-300 font-mono whitespace-pre">{code}</code>
|
||||
</pre>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const helloWorldCode = `# AeThex Hello World Example
|
||||
|
||||
reality HelloWorld {
|
||||
platforms: all
|
||||
}
|
||||
|
||||
journey Greet(name) {
|
||||
platform: all
|
||||
notify "Hello, " + name + " from AeThex!"
|
||||
}`;
|
||||
|
||||
const crossPlatformAuthCode = `import { Passport, DataSync } from "@aethex.os/core"
|
||||
|
||||
reality UniversalAuth {
|
||||
platforms: [roblox, uefn, web]
|
||||
}
|
||||
|
||||
journey Login(username, password) {
|
||||
platform: all
|
||||
|
||||
let passport = new Passport(username)
|
||||
|
||||
when passport.verify() {
|
||||
sync passport across [roblox, uefn, web]
|
||||
|
||||
# Pull existing data from any platform
|
||||
let playerData = DataSync.pull(passport.userId, "roblox")
|
||||
|
||||
notify "Logged in across all platforms!"
|
||||
reveal passport
|
||||
}
|
||||
}`;
|
||||
|
||||
const secureLeaderboardCode = `# The Foundry Certification Exam
|
||||
# Task: Build a COPPA-compliant, PII-safe leaderboard
|
||||
#
|
||||
# Requirements:
|
||||
# 1. Must accept player scores
|
||||
# 2. Must detect and block PII (phone numbers, emails, etc.)
|
||||
# 3. Must work on Roblox (Lua)
|
||||
# 4. Must display safely without exposing sensitive data
|
||||
|
||||
import { SafeInput, Compliance } from "@aethex.os/core"
|
||||
|
||||
reality SecureLeaderboard {
|
||||
platforms: [roblox]
|
||||
type: "compliance-exam"
|
||||
}
|
||||
|
||||
# CRITICAL: This is the exam
|
||||
# If PII gets through to the leaderboard, you FAIL
|
||||
|
||||
journey SubmitScore(player, playerName, score) {
|
||||
platform: roblox
|
||||
|
||||
# STEP 1: Validate player age (COPPA compliance)
|
||||
when !Compliance.isCOPPACompliant(player.age) {
|
||||
notify "Players under 13 cannot submit scores publicly"
|
||||
return
|
||||
}
|
||||
|
||||
# STEP 2: Validate player name for PII
|
||||
let nameValidation = SafeInput.validate(playerName)
|
||||
|
||||
when !nameValidation.valid {
|
||||
notify "Invalid name: " + nameValidation.message
|
||||
notify "Blocked PII types: " + nameValidation.blocked
|
||||
|
||||
# Log security incident
|
||||
Compliance.logCheck(player.userId, "leaderboard_name_check", false)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
# STEP 3: Validate score value for PII
|
||||
let scoreValidation = SafeInput.validate(score.toString())
|
||||
|
||||
when !scoreValidation.valid {
|
||||
notify "Invalid score: contains sensitive data"
|
||||
|
||||
# Log security incident
|
||||
Compliance.logCheck(player.userId, "leaderboard_score_check", false)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
# STEP 4: All validations passed - safe to submit
|
||||
Compliance.logCheck(player.userId, "leaderboard_submission", true)
|
||||
notify "Score submitted successfully!"
|
||||
|
||||
reveal {
|
||||
player: nameValidation.clean,
|
||||
score: scoreValidation.clean
|
||||
}
|
||||
}
|
||||
|
||||
# Test function: Attempts to inject PII
|
||||
journey TestPIIDetection() {
|
||||
platform: roblox
|
||||
|
||||
notify "=== FOUNDRY EXAM TEST SUITE ==="
|
||||
|
||||
# Test 1: Phone number in name
|
||||
let test1 = SafeInput.validate("John 555-1234")
|
||||
when test1.valid {
|
||||
notify "❌ FAIL: Phone number not detected"
|
||||
} otherwise {
|
||||
notify "✅ PASS: Phone number blocked"
|
||||
}
|
||||
|
||||
# Test 2: Email in name
|
||||
let test2 = SafeInput.validate("player@email.com")
|
||||
when test2.valid {
|
||||
notify "❌ FAIL: Email not detected"
|
||||
} otherwise {
|
||||
notify "✅ PASS: Email blocked"
|
||||
}
|
||||
|
||||
# Test 3: Clean name
|
||||
let test3 = SafeInput.validate("PlayerOne")
|
||||
when test3.valid {
|
||||
notify "✅ PASS: Clean name accepted"
|
||||
} otherwise {
|
||||
notify "❌ FAIL: Clean name rejected"
|
||||
}
|
||||
|
||||
# Test 4: SSN in score
|
||||
let test4 = SafeInput.validate("123-45-6789")
|
||||
when test4.valid {
|
||||
notify "❌ FAIL: SSN not detected"
|
||||
} otherwise {
|
||||
notify "✅ PASS: SSN blocked"
|
||||
}
|
||||
}`;
|
||||
|
||||
const coppaRegistrationCode = `import { Compliance, Passport } from "@aethex.os/core"
|
||||
|
||||
journey RegisterUser(username, age) {
|
||||
platform: all
|
||||
|
||||
when Compliance.isCOPPACompliant(age) {
|
||||
# User is 13+, can proceed
|
||||
let passport = new Passport(username)
|
||||
passport.verify()
|
||||
notify "Account created!"
|
||||
} otherwise {
|
||||
# Under 13, require parent consent
|
||||
notify "Parent permission required"
|
||||
# Send email to parent (implementation omitted)
|
||||
}
|
||||
}`;
|
||||
|
||||
const dataSyncCode = `import { Passport, DataSync } from "@aethex.os/core"
|
||||
|
||||
reality CrossPlatformProgress {
|
||||
platforms: [roblox, uefn, web]
|
||||
}
|
||||
|
||||
journey SaveProgress(player, progress) {
|
||||
platform: all
|
||||
|
||||
# Sync progress data across all platforms
|
||||
DataSync.sync({
|
||||
level: progress.level,
|
||||
experience: progress.xp,
|
||||
inventory: progress.items
|
||||
}, [roblox, uefn, web])
|
||||
|
||||
notify "Progress saved!"
|
||||
}
|
||||
|
||||
journey LoadProgress(player) {
|
||||
platform: all
|
||||
|
||||
# Pull latest progress from any platform
|
||||
let data = DataSync.pull(player.userId, "web")
|
||||
|
||||
reveal data
|
||||
}`;
|
||||
|
||||
const examples = [
|
||||
{
|
||||
id: "hello-world",
|
||||
title: "Hello World",
|
||||
description: "Your first AeThex program",
|
||||
icon: Zap,
|
||||
color: "text-yellow-500",
|
||||
code: helloWorldCode,
|
||||
difficulty: "Beginner",
|
||||
},
|
||||
{
|
||||
id: "cross-platform-auth",
|
||||
title: "Cross-Platform Authentication",
|
||||
description: "Login once, authenticated everywhere",
|
||||
icon: Users,
|
||||
color: "text-blue-500",
|
||||
code: crossPlatformAuthCode,
|
||||
difficulty: "Intermediate",
|
||||
},
|
||||
{
|
||||
id: "secure-leaderboard",
|
||||
title: "Secure Leaderboard (Foundry Exam)",
|
||||
description: "COPPA-compliant, PII-safe leaderboard - the certification exam",
|
||||
icon: Award,
|
||||
color: "text-purple-500",
|
||||
code: secureLeaderboardCode,
|
||||
difficulty: "Advanced",
|
||||
},
|
||||
{
|
||||
id: "coppa-registration",
|
||||
title: "COPPA-Compliant Registration",
|
||||
description: "User registration with age verification",
|
||||
icon: Lock,
|
||||
color: "text-green-500",
|
||||
code: coppaRegistrationCode,
|
||||
difficulty: "Intermediate",
|
||||
},
|
||||
{
|
||||
id: "data-sync",
|
||||
title: "Cross-Platform Data Sync",
|
||||
description: "Sync player progress across all platforms",
|
||||
icon: Shield,
|
||||
color: "text-cyan-500",
|
||||
code: dataSyncCode,
|
||||
difficulty: "Intermediate",
|
||||
},
|
||||
];
|
||||
|
||||
const difficultyColors: Record<string, string> = {
|
||||
Beginner: "bg-green-500/20 text-green-400 border-green-500/30",
|
||||
Intermediate: "bg-yellow-500/20 text-yellow-400 border-yellow-500/30",
|
||||
Advanced: "bg-red-500/20 text-red-400 border-red-500/30",
|
||||
};
|
||||
|
||||
export default function DocsLangExamples() {
|
||||
const [activeExample, setActiveExample] = useState("hello-world");
|
||||
const currentExample = examples.find((e) => e.id === activeExample) || examples[0];
|
||||
|
||||
return (
|
||||
<div className="space-y-12">
|
||||
{/* Header */}
|
||||
<section>
|
||||
<Badge className="mb-4 bg-purple-500/20 text-purple-400 border-purple-500/30">
|
||||
Code Examples
|
||||
</Badge>
|
||||
<h1 className="text-4xl font-bold mb-4">Examples</h1>
|
||||
<p className="text-xl text-muted-foreground">
|
||||
Real-world code examples and patterns for AeThex development.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
{/* Examples Grid for Quick Navigation */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-6">Browse Examples</h2>
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{examples.map((example) => (
|
||||
<button
|
||||
key={example.id}
|
||||
onClick={() => setActiveExample(example.id)}
|
||||
className={`text-left w-full ${
|
||||
activeExample === example.id ? "ring-2 ring-primary" : ""
|
||||
}`}
|
||||
>
|
||||
<Card className="h-full hover:border-primary/50 transition-all cursor-pointer">
|
||||
<CardHeader>
|
||||
<div className="flex items-start justify-between">
|
||||
<example.icon className={`w-6 h-6 ${example.color}`} />
|
||||
<Badge className={difficultyColors[example.difficulty]}>
|
||||
{example.difficulty}
|
||||
</Badge>
|
||||
</div>
|
||||
<CardTitle className="text-lg mt-2">{example.title}</CardTitle>
|
||||
<CardDescription>{example.description}</CardDescription>
|
||||
</CardHeader>
|
||||
</Card>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Active Example Display */}
|
||||
<section>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-3">
|
||||
<currentExample.icon className={`w-6 h-6 ${currentExample.color}`} />
|
||||
<CardTitle>{currentExample.title}</CardTitle>
|
||||
</div>
|
||||
<Badge className={difficultyColors[currentExample.difficulty]}>
|
||||
{currentExample.difficulty}
|
||||
</Badge>
|
||||
</div>
|
||||
<CardDescription>{currentExample.description}</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CodeBlock code={currentExample.code} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</section>
|
||||
|
||||
{/* All Examples (Tabbed) */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-6">All Examples</h2>
|
||||
<Tabs defaultValue="hello-world" className="w-full">
|
||||
<TabsList className="flex flex-wrap h-auto gap-2">
|
||||
{examples.map((example) => (
|
||||
<TabsTrigger key={example.id} value={example.id} className="text-xs">
|
||||
{example.title.split(" ")[0]}
|
||||
</TabsTrigger>
|
||||
))}
|
||||
</TabsList>
|
||||
{examples.map((example) => (
|
||||
<TabsContent key={example.id} value={example.id} className="mt-6">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<div className="flex items-center gap-3">
|
||||
<example.icon className={`w-5 h-5 ${example.color}`} />
|
||||
<CardTitle className="text-lg">{example.title}</CardTitle>
|
||||
<Badge className={difficultyColors[example.difficulty]}>
|
||||
{example.difficulty}
|
||||
</Badge>
|
||||
</div>
|
||||
<CardDescription>{example.description}</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CodeBlock code={example.code} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
))}
|
||||
</Tabs>
|
||||
</section>
|
||||
|
||||
{/* The Foundry Note */}
|
||||
<section>
|
||||
<Card className="bg-gradient-to-br from-slate-800/50 to-purple-900/20 border-purple-500/20">
|
||||
<CardContent className="p-8">
|
||||
<div className="flex items-start gap-4">
|
||||
<Award className="w-8 h-8 text-purple-400 shrink-0" />
|
||||
<div>
|
||||
<h3 className="text-xl font-bold mb-2">The Foundry Certification</h3>
|
||||
<p className="text-muted-foreground mb-4">
|
||||
The <strong>Secure Leaderboard</strong> example above is the actual Foundry certification exam.
|
||||
If you can implement a COPPA-compliant, PII-safe leaderboard that passes all validation tests,
|
||||
you're ready for professional metaverse development.
|
||||
</p>
|
||||
<Link
|
||||
to="/foundation"
|
||||
className="text-primary hover:underline text-sm"
|
||||
>
|
||||
Learn more about The Foundry →
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</section>
|
||||
|
||||
{/* Navigation */}
|
||||
<section className="flex justify-between pt-8 border-t border-border/50">
|
||||
<Link to="/docs/lang/cli" className="text-sm text-muted-foreground hover:text-foreground">
|
||||
← CLI Reference
|
||||
</Link>
|
||||
<Link to="/docs/lang" className="text-sm text-muted-foreground hover:text-foreground">
|
||||
Back to Overview →
|
||||
</Link>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
380
client/pages/docs/lang/DocsLangOverview.tsx
Normal file
|
|
@ -0,0 +1,380 @@
|
|||
import { Link } from "react-router-dom";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import {
|
||||
Package,
|
||||
Terminal,
|
||||
BookOpen,
|
||||
Code,
|
||||
Zap,
|
||||
Shield,
|
||||
Users,
|
||||
ExternalLink,
|
||||
ArrowRight,
|
||||
CheckCircle2,
|
||||
FileText,
|
||||
Github,
|
||||
Globe,
|
||||
Lock,
|
||||
Copy,
|
||||
} from "lucide-react";
|
||||
import { useState } from "react";
|
||||
|
||||
function CopyButton({ text }: { text: string }) {
|
||||
const [copied, setCopied] = useState(false);
|
||||
const handleCopy = async () => {
|
||||
await navigator.clipboard.writeText(text);
|
||||
setCopied(true);
|
||||
setTimeout(() => setCopied(false), 2000);
|
||||
};
|
||||
return (
|
||||
<button
|
||||
onClick={handleCopy}
|
||||
className="absolute top-3 right-3 p-1.5 rounded bg-slate-700 hover:bg-slate-600 transition-colors"
|
||||
>
|
||||
{copied ? <CheckCircle2 className="h-4 w-4 text-green-400" /> : <Copy className="h-4 w-4 text-slate-400" />}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
function CodeBlock({ code, language = "aethex" }: { code: string; language?: string }) {
|
||||
return (
|
||||
<div className="relative">
|
||||
<CopyButton text={code} />
|
||||
<pre className="bg-slate-900 border border-slate-700 rounded-lg p-4 overflow-x-auto">
|
||||
<code className="text-sm text-slate-300 font-mono whitespace-pre">{code}</code>
|
||||
</pre>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const docSections = [
|
||||
{
|
||||
title: "Quick Start",
|
||||
description: "Get up and running in 5 minutes",
|
||||
icon: Zap,
|
||||
href: "/docs/lang/quickstart",
|
||||
color: "text-yellow-500",
|
||||
bgColor: "bg-yellow-500/10",
|
||||
},
|
||||
{
|
||||
title: "Language Syntax",
|
||||
description: "Learn realities, journeys, and cross-platform sync",
|
||||
icon: Code,
|
||||
href: "/docs/lang/syntax",
|
||||
color: "text-blue-500",
|
||||
bgColor: "bg-blue-500/10",
|
||||
},
|
||||
{
|
||||
title: "CLI Reference",
|
||||
description: "Command line compiler and tools",
|
||||
icon: Terminal,
|
||||
href: "/docs/lang/cli",
|
||||
color: "text-green-500",
|
||||
bgColor: "bg-green-500/10",
|
||||
},
|
||||
{
|
||||
title: "Examples",
|
||||
description: "Real-world code examples and patterns",
|
||||
icon: FileText,
|
||||
href: "/docs/lang/examples",
|
||||
color: "text-purple-500",
|
||||
bgColor: "bg-purple-500/10",
|
||||
},
|
||||
];
|
||||
|
||||
const features = [
|
||||
{
|
||||
icon: Globe,
|
||||
title: "Cross-Platform Native",
|
||||
description: "Deploy to Roblox, UEFN, Unity, VRChat, Spatial, and Web",
|
||||
},
|
||||
{
|
||||
icon: Users,
|
||||
title: "Universal Passport",
|
||||
description: "Single identity system across all metaverse platforms",
|
||||
},
|
||||
{
|
||||
icon: Shield,
|
||||
title: "Compliance-First",
|
||||
description: "Built-in COPPA/FERPA/PII protection",
|
||||
},
|
||||
{
|
||||
icon: Package,
|
||||
title: "Standard Library",
|
||||
description: "Battle-tested utilities for auth, data sync, and safety",
|
||||
},
|
||||
];
|
||||
|
||||
const platforms = [
|
||||
{ name: "JavaScript", status: "ready" },
|
||||
{ name: "Roblox (Lua)", status: "ready" },
|
||||
{ name: "UEFN (Verse)", status: "coming" },
|
||||
{ name: "Unity (C#)", status: "coming" },
|
||||
];
|
||||
|
||||
const helloWorldCode = `reality HelloWorld {
|
||||
platforms: all
|
||||
}
|
||||
|
||||
journey Greet(name) {
|
||||
platform: all
|
||||
notify "Hello, " + name + "!"
|
||||
}`;
|
||||
|
||||
const crossPlatformCode = `import { Passport } from "@aethex.os/core"
|
||||
|
||||
reality MyGame {
|
||||
platforms: [roblox, uefn, web]
|
||||
}
|
||||
|
||||
journey AuthenticatePlayer(username) {
|
||||
platform: all
|
||||
|
||||
let passport = new Passport(username)
|
||||
|
||||
when passport.verify() {
|
||||
sync passport across [roblox, uefn, web]
|
||||
notify "Welcome, " + username + "!"
|
||||
}
|
||||
}`;
|
||||
|
||||
export default function DocsLangOverview() {
|
||||
return (
|
||||
<div className="space-y-12">
|
||||
{/* Hero Section */}
|
||||
<section className="text-center space-y-6">
|
||||
<div className="flex items-center justify-center gap-3 mb-4">
|
||||
<Badge className="text-sm px-4 py-1 bg-purple-500/20 text-purple-400 border-purple-500/30">
|
||||
v1.0.0
|
||||
</Badge>
|
||||
<Badge variant="outline" className="text-sm px-4 py-1">
|
||||
MIT License
|
||||
</Badge>
|
||||
</div>
|
||||
<h1 className="text-4xl font-bold">AeThex Language</h1>
|
||||
<p className="text-xl text-muted-foreground max-w-2xl mx-auto">
|
||||
<strong>Write once. Build everywhere. Comply by default.</strong>
|
||||
</p>
|
||||
<p className="text-muted-foreground max-w-3xl mx-auto">
|
||||
AeThex is a programming language for cross-platform metaverse development.
|
||||
Write your game logic, authentication, and compliance rules once, then compile
|
||||
to JavaScript, Lua (Roblox), Verse (UEFN), and C# (Unity).
|
||||
</p>
|
||||
|
||||
{/* Install Command */}
|
||||
<div className="relative max-w-md mx-auto">
|
||||
<div className="flex items-center gap-3 bg-slate-900 border border-slate-700 rounded-lg px-4 py-3">
|
||||
<Terminal className="h-5 w-5 text-slate-500" />
|
||||
<code className="text-sm font-mono text-slate-300 flex-1 text-left">
|
||||
npm install -g @aethex.os/cli
|
||||
</code>
|
||||
<CopyButton text="npm install -g @aethex.os/cli" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-4 justify-center pt-4">
|
||||
<Link to="/docs/lang/quickstart">
|
||||
<Button size="lg">
|
||||
Get Started
|
||||
<ArrowRight className="w-4 h-4 ml-2" />
|
||||
</Button>
|
||||
</Link>
|
||||
<a
|
||||
href="https://github.com/AeThex-Corporation/AeThexOS"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Button size="lg" variant="outline">
|
||||
<Github className="w-4 h-4 mr-2" />
|
||||
GitHub
|
||||
</Button>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Platform Support */}
|
||||
<section className="text-center">
|
||||
<p className="text-sm text-muted-foreground mb-4">Compilation Targets</p>
|
||||
<div className="flex flex-wrap justify-center gap-3">
|
||||
{platforms.map((platform) => (
|
||||
<Badge
|
||||
key={platform.name}
|
||||
variant={platform.status === "ready" ? "default" : "outline"}
|
||||
className={`px-4 py-2 text-sm ${
|
||||
platform.status === "ready"
|
||||
? "bg-green-500/20 text-green-400 border-green-500/30"
|
||||
: "text-slate-400"
|
||||
}`}
|
||||
>
|
||||
{platform.status === "ready" && <CheckCircle2 className="w-3 h-3 mr-2" />}
|
||||
{platform.name}
|
||||
{platform.status === "coming" && " (Coming Soon)"}
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Documentation Sections */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-6">Documentation</h2>
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
{docSections.map((section) => (
|
||||
<Link key={section.title} to={section.href}>
|
||||
<Card className="h-full hover:border-primary/50 transition-all cursor-pointer">
|
||||
<CardHeader className="flex flex-row items-start gap-4">
|
||||
<div className={`p-2 rounded-lg ${section.bgColor}`}>
|
||||
<section.icon className={`w-5 h-5 ${section.color}`} />
|
||||
</div>
|
||||
<div>
|
||||
<CardTitle className="text-lg">{section.title}</CardTitle>
|
||||
<CardDescription>{section.description}</CardDescription>
|
||||
</div>
|
||||
</CardHeader>
|
||||
</Card>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Hello World Example */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-4">Hello World</h2>
|
||||
<p className="text-muted-foreground mb-6">
|
||||
Create <code className="bg-slate-800 px-2 py-0.5 rounded text-sm">hello.aethex</code>:
|
||||
</p>
|
||||
<CodeBlock code={helloWorldCode} />
|
||||
<div className="mt-4 flex gap-2">
|
||||
<code className="bg-slate-800 px-3 py-2 rounded text-sm font-mono">
|
||||
aethex compile hello.aethex
|
||||
</code>
|
||||
<code className="bg-slate-800 px-3 py-2 rounded text-sm font-mono">
|
||||
node hello.js
|
||||
</code>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Cross-Platform Example */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-4">Cross-Platform Authentication</h2>
|
||||
<p className="text-muted-foreground mb-6">
|
||||
One codebase, deployed everywhere:
|
||||
</p>
|
||||
<CodeBlock code={crossPlatformCode} />
|
||||
</section>
|
||||
|
||||
{/* Features */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-6">Why AeThex?</h2>
|
||||
<div className="grid md:grid-cols-2 gap-6">
|
||||
{features.map((feature) => (
|
||||
<div key={feature.title} className="flex gap-4">
|
||||
<div className="p-2 h-fit rounded-lg bg-primary/10">
|
||||
<feature.icon className="w-5 h-5 text-primary" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-semibold mb-1">{feature.title}</h3>
|
||||
<p className="text-sm text-muted-foreground">{feature.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* npm Packages */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-6">npm Packages</h2>
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2 text-lg">
|
||||
<Terminal className="w-5 h-5 text-green-500" />
|
||||
@aethex.os/cli
|
||||
</CardTitle>
|
||||
<CardDescription>Command line compiler</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<a
|
||||
href="https://www.npmjs.com/package/@aethex.os/cli"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-sm text-primary hover:underline flex items-center gap-1"
|
||||
>
|
||||
View on npm <ExternalLink className="w-3 h-3" />
|
||||
</a>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2 text-lg">
|
||||
<Package className="w-5 h-5 text-purple-500" />
|
||||
@aethex.os/core
|
||||
</CardTitle>
|
||||
<CardDescription>Standard library</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<a
|
||||
href="https://www.npmjs.com/package/@aethex.os/core"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-sm text-primary hover:underline flex items-center gap-1"
|
||||
>
|
||||
View on npm <ExternalLink className="w-3 h-3" />
|
||||
</a>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* The Foundry */}
|
||||
<section>
|
||||
<Card className="bg-gradient-to-br from-slate-800/50 to-purple-900/20 border-purple-500/20">
|
||||
<CardContent className="p-8 text-center">
|
||||
<BookOpen className="w-12 h-12 mx-auto mb-4 text-purple-400" />
|
||||
<h2 className="text-2xl font-bold mb-2">The Foundry Certification</h2>
|
||||
<p className="text-muted-foreground mb-6 max-w-2xl mx-auto">
|
||||
AeThex is the official language taught at The AeThex Foundry certification program.
|
||||
Learn to build compliant, cross-platform metaverse experiences.
|
||||
</p>
|
||||
<div className="flex gap-4 justify-center">
|
||||
<Link to="/foundation">
|
||||
<Button>
|
||||
Learn More
|
||||
<ArrowRight className="w-4 h-4 ml-2" />
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</section>
|
||||
|
||||
{/* Quick Links */}
|
||||
<section className="text-center text-sm text-muted-foreground border-t border-border/50 pt-8">
|
||||
<p className="flex items-center justify-center gap-4 flex-wrap">
|
||||
<a
|
||||
href="https://github.com/AeThex-Corporation/AeThexOS"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="hover:text-foreground flex items-center gap-1"
|
||||
>
|
||||
<Github className="w-4 h-4" /> GitHub
|
||||
</a>
|
||||
<span>•</span>
|
||||
<a
|
||||
href="https://github.com/AeThex-Corporation/AeThexOS/issues"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="hover:text-foreground"
|
||||
>
|
||||
Report Issues
|
||||
</a>
|
||||
<span>•</span>
|
||||
<Link to="/community" className="hover:text-foreground">
|
||||
Community
|
||||
</Link>
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
354
client/pages/docs/lang/DocsLangQuickstart.tsx
Normal file
|
|
@ -0,0 +1,354 @@
|
|||
import { Link } from "react-router-dom";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import {
|
||||
Terminal,
|
||||
CheckCircle2,
|
||||
Copy,
|
||||
ArrowRight,
|
||||
FileText,
|
||||
Folder,
|
||||
ExternalLink,
|
||||
} from "lucide-react";
|
||||
import { useState } from "react";
|
||||
|
||||
function CopyButton({ text }: { text: string }) {
|
||||
const [copied, setCopied] = useState(false);
|
||||
const handleCopy = async () => {
|
||||
await navigator.clipboard.writeText(text);
|
||||
setCopied(true);
|
||||
setTimeout(() => setCopied(false), 2000);
|
||||
};
|
||||
return (
|
||||
<button
|
||||
onClick={handleCopy}
|
||||
className="absolute top-3 right-3 p-1.5 rounded bg-slate-700 hover:bg-slate-600 transition-colors"
|
||||
>
|
||||
{copied ? <CheckCircle2 className="h-4 w-4 text-green-400" /> : <Copy className="h-4 w-4 text-slate-400" />}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
function CodeBlock({ code, language = "bash" }: { code: string; language?: string }) {
|
||||
return (
|
||||
<div className="relative">
|
||||
<CopyButton text={code} />
|
||||
<pre className="bg-slate-900 border border-slate-700 rounded-lg p-4 overflow-x-auto">
|
||||
<code className="text-sm text-slate-300 font-mono whitespace-pre">{code}</code>
|
||||
</pre>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function StepCard({ number, title, children }: { number: number; title: string; children: React.ReactNode }) {
|
||||
return (
|
||||
<Card className="relative overflow-hidden">
|
||||
<div className="absolute top-4 left-4 w-8 h-8 rounded-full bg-primary/20 flex items-center justify-center">
|
||||
<span className="text-sm font-bold text-primary">{number}</span>
|
||||
</div>
|
||||
<CardHeader className="pl-16">
|
||||
<CardTitle className="text-lg">{title}</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="pl-16">
|
||||
{children}
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
const installCode = `# Install the CLI globally
|
||||
npm install -g @aethex.os/cli
|
||||
|
||||
# Verify installation
|
||||
aethex --version`;
|
||||
|
||||
const newProjectCode = `aethex new my-first-game
|
||||
cd my-first-game
|
||||
npm install`;
|
||||
|
||||
const mainAethexCode = `reality MyFirstGame {
|
||||
platforms: [roblox, web]
|
||||
}
|
||||
|
||||
journey WelcomePlayer(username) {
|
||||
platform: all
|
||||
notify "Welcome, " + username + "!"
|
||||
}`;
|
||||
|
||||
const compileCode = `# Compile to JavaScript
|
||||
npm run build
|
||||
|
||||
# Run it
|
||||
node build/main.js
|
||||
|
||||
# Or compile to Roblox
|
||||
npm run build:roblox`;
|
||||
|
||||
const authExampleCode = `import { Passport } from "@aethex.os/core"
|
||||
|
||||
journey Login(username) {
|
||||
let passport = new Passport(username)
|
||||
|
||||
when passport.verify() {
|
||||
sync passport across [roblox, web]
|
||||
notify "Logged in everywhere!"
|
||||
}
|
||||
}`;
|
||||
|
||||
const piiExampleCode = `import { SafeInput } from "@aethex.os/core"
|
||||
|
||||
journey SubmitScore(player, score) {
|
||||
let validation = SafeInput.validate(score)
|
||||
|
||||
when validation.valid {
|
||||
# Safe to submit
|
||||
notify "Score: " + score
|
||||
} otherwise {
|
||||
# PII detected!
|
||||
notify "Error: " + validation.message
|
||||
}
|
||||
}`;
|
||||
|
||||
const projectStructure = `my-project/
|
||||
├── aethex.config.json # Config file
|
||||
├── package.json # npm dependencies
|
||||
├── src/
|
||||
│ ├── main.aethex # Your code
|
||||
│ ├── auth.aethex
|
||||
│ └── game.aethex
|
||||
└── build/
|
||||
├── main.js # Compiled JavaScript
|
||||
└── main.lua # Compiled Lua`;
|
||||
|
||||
const stdlibCode = `# Import from @aethex.os/core
|
||||
import { Passport, DataSync, SafeInput, Compliance } from "@aethex.os/core"
|
||||
|
||||
# Import from @aethex.os/roblox (platform-specific)
|
||||
import { RemoteEvent, Leaderboard } from "@aethex.os/roblox"`;
|
||||
|
||||
const commonPatterns = {
|
||||
auth: `journey Login(user) {
|
||||
when user.verify() {
|
||||
sync user.passport across [roblox, web]
|
||||
}
|
||||
}`,
|
||||
datasync: `journey SaveProgress(player) {
|
||||
sync player.stats across [roblox, uefn, web]
|
||||
}`,
|
||||
pii: `let result = SafeInput.validate(userInput)
|
||||
when result.valid {
|
||||
# Safe to use
|
||||
}`,
|
||||
coppa: `when Compliance.isCOPPACompliant(user.age) {
|
||||
# User is 13+
|
||||
}`,
|
||||
};
|
||||
|
||||
export default function DocsLangQuickstart() {
|
||||
return (
|
||||
<div className="space-y-12">
|
||||
{/* Header */}
|
||||
<section>
|
||||
<Badge className="mb-4 bg-yellow-500/20 text-yellow-400 border-yellow-500/30">
|
||||
5 Minute Guide
|
||||
</Badge>
|
||||
<h1 className="text-4xl font-bold mb-4">Quick Start</h1>
|
||||
<p className="text-xl text-muted-foreground">
|
||||
Get up and running with AeThex in 5 minutes.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
{/* Installation */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-6">Installation</h2>
|
||||
<CodeBlock code={installCode} />
|
||||
</section>
|
||||
|
||||
{/* Steps */}
|
||||
<section className="space-y-6">
|
||||
<h2 className="text-2xl font-bold">Your First AeThex Program</h2>
|
||||
|
||||
<StepCard number={1} title="Create a new project">
|
||||
<CodeBlock code={newProjectCode} />
|
||||
</StepCard>
|
||||
|
||||
<StepCard number={2} title="Edit src/main.aethex">
|
||||
<CodeBlock code={mainAethexCode} language="aethex" />
|
||||
</StepCard>
|
||||
|
||||
<StepCard number={3} title="Compile and run">
|
||||
<CodeBlock code={compileCode} />
|
||||
</StepCard>
|
||||
</section>
|
||||
|
||||
{/* Example Projects */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-6">Example Projects</h2>
|
||||
|
||||
<div className="space-y-6">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Cross-Platform Authentication</CardTitle>
|
||||
<CardDescription>Authenticate users across multiple platforms with one codebase</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CodeBlock code={authExampleCode} language="aethex" />
|
||||
<div className="mt-4 text-sm text-muted-foreground">
|
||||
Compile and run:
|
||||
<code className="ml-2 bg-slate-800 px-2 py-1 rounded">aethex compile auth.aethex && node auth.js</code>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<div className="flex items-center gap-2">
|
||||
<CardTitle>PII-Safe Leaderboard</CardTitle>
|
||||
<Badge variant="outline" className="text-xs">Foundry Exam</Badge>
|
||||
</div>
|
||||
<CardDescription>
|
||||
This is the Foundry certification exam - if you can build this correctly,
|
||||
you're ready to work in metaverse development.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CodeBlock code={piiExampleCode} language="aethex" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Compilation Targets */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-6">Compilation Targets</h2>
|
||||
<CodeBlock code={`# JavaScript (default)
|
||||
aethex compile game.aethex
|
||||
|
||||
# Roblox (Lua)
|
||||
aethex compile game.aethex --target roblox --output game.lua
|
||||
|
||||
# UEFN (Verse) - Coming soon
|
||||
aethex compile game.aethex --target uefn --output game.verse
|
||||
|
||||
# Unity (C#) - Coming soon
|
||||
aethex compile game.aethex --target unity --output game.cs`} />
|
||||
</section>
|
||||
|
||||
{/* Watch Mode */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-4">Watch Mode</h2>
|
||||
<p className="text-muted-foreground mb-4">Auto-recompile on file save:</p>
|
||||
<CodeBlock code="aethex compile game.aethex --watch" />
|
||||
</section>
|
||||
|
||||
{/* Project Structure */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-4">Project Structure</h2>
|
||||
<CodeBlock code={projectStructure} />
|
||||
</section>
|
||||
|
||||
{/* Standard Library */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-4">Standard Library</h2>
|
||||
<CodeBlock code={stdlibCode} language="aethex" />
|
||||
</section>
|
||||
|
||||
{/* Common Patterns */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-6">Common Patterns</h2>
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<Card>
|
||||
<CardHeader className="pb-2">
|
||||
<CardTitle className="text-sm font-medium">Authentication</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CodeBlock code={commonPatterns.auth} language="aethex" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader className="pb-2">
|
||||
<CardTitle className="text-sm font-medium">Data Sync</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CodeBlock code={commonPatterns.datasync} language="aethex" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader className="pb-2">
|
||||
<CardTitle className="text-sm font-medium">PII Protection</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CodeBlock code={commonPatterns.pii} language="aethex" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader className="pb-2">
|
||||
<CardTitle className="text-sm font-medium">COPPA Compliance</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CodeBlock code={commonPatterns.coppa} language="aethex" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Next Steps */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-6">Next Steps</h2>
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<Link to="/docs/lang/syntax">
|
||||
<Card className="h-full hover:border-primary/50 transition-all cursor-pointer">
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<FileText className="w-5 h-5 text-blue-500" />
|
||||
Language Syntax
|
||||
</CardTitle>
|
||||
<CardDescription>Learn realities, journeys, and more</CardDescription>
|
||||
</CardHeader>
|
||||
</Card>
|
||||
</Link>
|
||||
<Link to="/docs/lang/examples">
|
||||
<Card className="h-full hover:border-primary/50 transition-all cursor-pointer">
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Folder className="w-5 h-5 text-purple-500" />
|
||||
Examples
|
||||
</CardTitle>
|
||||
<CardDescription>View more code examples</CardDescription>
|
||||
</CardHeader>
|
||||
</Card>
|
||||
</Link>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Getting Help */}
|
||||
<section className="text-center text-sm text-muted-foreground border-t border-border/50 pt-8">
|
||||
<h3 className="font-semibold text-foreground mb-4">Getting Help</h3>
|
||||
<p className="flex items-center justify-center gap-4 flex-wrap">
|
||||
<a
|
||||
href="https://github.com/AeThex-Corporation/AeThexOS/issues"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="hover:text-foreground flex items-center gap-1"
|
||||
>
|
||||
GitHub Issues <ExternalLink className="w-3 h-3" />
|
||||
</a>
|
||||
<span>•</span>
|
||||
<a
|
||||
href="https://discord.gg/aethex"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="hover:text-foreground"
|
||||
>
|
||||
Discord
|
||||
</a>
|
||||
<span>•</span>
|
||||
<Link to="/support" className="hover:text-foreground">
|
||||
Support
|
||||
</Link>
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
365
client/pages/docs/lang/DocsLangSyntax.tsx
Normal file
|
|
@ -0,0 +1,365 @@
|
|||
import { Link } from "react-router-dom";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import {
|
||||
CheckCircle2,
|
||||
Copy,
|
||||
Code,
|
||||
Layers,
|
||||
Zap,
|
||||
Globe,
|
||||
GitBranch,
|
||||
} from "lucide-react";
|
||||
import { useState } from "react";
|
||||
|
||||
function CopyButton({ text }: { text: string }) {
|
||||
const [copied, setCopied] = useState(false);
|
||||
const handleCopy = async () => {
|
||||
await navigator.clipboard.writeText(text);
|
||||
setCopied(true);
|
||||
setTimeout(() => setCopied(false), 2000);
|
||||
};
|
||||
return (
|
||||
<button
|
||||
onClick={handleCopy}
|
||||
className="absolute top-3 right-3 p-1.5 rounded bg-slate-700 hover:bg-slate-600 transition-colors"
|
||||
>
|
||||
{copied ? <CheckCircle2 className="h-4 w-4 text-green-400" /> : <Copy className="h-4 w-4 text-slate-400" />}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
function CodeBlock({ code, language = "aethex" }: { code: string; language?: string }) {
|
||||
return (
|
||||
<div className="relative">
|
||||
<CopyButton text={code} />
|
||||
<pre className="bg-slate-900 border border-slate-700 rounded-lg p-4 overflow-x-auto">
|
||||
<code className="text-sm text-slate-300 font-mono whitespace-pre">{code}</code>
|
||||
</pre>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const realitiesCode = `reality GameName {
|
||||
platforms: [roblox, uefn, web]
|
||||
type: "multiplayer"
|
||||
}`;
|
||||
|
||||
const journeysCode = `journey ProcessScore(player, score) {
|
||||
platform: all
|
||||
|
||||
# Automatically scrubs PII before processing
|
||||
when score > 1000 {
|
||||
notify "High score achieved!"
|
||||
}
|
||||
}`;
|
||||
|
||||
const syncCode = `import { Passport } from "@aethex.os/core"
|
||||
|
||||
journey SaveProgress(player) {
|
||||
platform: all
|
||||
|
||||
let passport = player.passport
|
||||
sync passport across [roblox, uefn, web]
|
||||
}`;
|
||||
|
||||
const conditionalCode = `when player.age < 13 {
|
||||
# COPPA compliance automatic
|
||||
notify "Parent permission required"
|
||||
} otherwise {
|
||||
# Full features unlocked
|
||||
reveal player.stats
|
||||
}`;
|
||||
|
||||
const platformSpecificCode = `journey DisplayLeaderboard() {
|
||||
platform: roblox {
|
||||
# Roblox-specific code
|
||||
reveal leaderboardGUI
|
||||
}
|
||||
|
||||
platform: web {
|
||||
# Web-specific code
|
||||
reveal leaderboardHTML
|
||||
}
|
||||
}`;
|
||||
|
||||
const coreLibraryCode = `import { Passport, DataSync, SafeInput, Compliance } from "@aethex.os/core"
|
||||
|
||||
# Passport - Universal identity
|
||||
let passport = new Passport(userId, username)
|
||||
passport.verify()
|
||||
passport.syncAcross([roblox, web])
|
||||
|
||||
# DataSync - Cross-platform data
|
||||
DataSync.sync(playerData, [roblox, uefn])
|
||||
|
||||
# SafeInput - PII protection
|
||||
let result = SafeInput.validate(userInput)
|
||||
when result.valid {
|
||||
# Input is safe
|
||||
}
|
||||
|
||||
# Compliance - COPPA/FERPA checks
|
||||
when Compliance.isCOPPACompliant(user.age) {
|
||||
# Can collect data
|
||||
}`;
|
||||
|
||||
const robloxLibraryCode = `import { RemoteEvent, Leaderboard } from "@aethex.os/roblox"
|
||||
|
||||
# Roblox-specific features
|
||||
let event = RemoteEvent.new("PlayerJoined")
|
||||
event.FireAllClients(player)
|
||||
|
||||
let stats = Leaderboard.new("Points", 0)
|
||||
Leaderboard.updateScore(player, "Points", 100)`;
|
||||
|
||||
const configCode = `{
|
||||
"targets": ["javascript", "roblox", "uefn"],
|
||||
"srcDir": "src",
|
||||
"outDir": "build",
|
||||
"stdlib": true,
|
||||
"compliance": {
|
||||
"coppa": true,
|
||||
"ferpa": true,
|
||||
"piiDetection": true
|
||||
}
|
||||
}`;
|
||||
|
||||
const projectStructureCode = `my-game/
|
||||
├── aethex.config.json # Compilation settings
|
||||
├── package.json # npm dependencies
|
||||
├── src/
|
||||
│ ├── main.aethex # Entry point
|
||||
│ ├── auth.aethex # Authentication logic
|
||||
│ └── game.aethex # Game logic
|
||||
└── build/
|
||||
├── main.js # JavaScript output
|
||||
└── main.lua # Roblox output`;
|
||||
|
||||
const syntaxSections = [
|
||||
{
|
||||
id: "realities",
|
||||
title: "Realities (Namespaces)",
|
||||
icon: Layers,
|
||||
description: "Define your game or application namespace",
|
||||
code: realitiesCode,
|
||||
},
|
||||
{
|
||||
id: "journeys",
|
||||
title: "Journeys (Functions)",
|
||||
icon: Zap,
|
||||
description: "Create functions that run across platforms",
|
||||
code: journeysCode,
|
||||
},
|
||||
{
|
||||
id: "sync",
|
||||
title: "Cross-Platform Sync",
|
||||
icon: Globe,
|
||||
description: "Synchronize data across all platforms with one line",
|
||||
code: syncCode,
|
||||
},
|
||||
{
|
||||
id: "conditionals",
|
||||
title: "Conditional Logic",
|
||||
icon: GitBranch,
|
||||
description: "Use when/otherwise for conditions with built-in compliance",
|
||||
code: conditionalCode,
|
||||
},
|
||||
{
|
||||
id: "platform",
|
||||
title: "Platform-Specific Code",
|
||||
icon: Code,
|
||||
description: "Write code that only runs on specific platforms",
|
||||
code: platformSpecificCode,
|
||||
},
|
||||
];
|
||||
|
||||
export default function DocsLangSyntax() {
|
||||
return (
|
||||
<div className="space-y-12">
|
||||
{/* Header */}
|
||||
<section>
|
||||
<Badge className="mb-4 bg-blue-500/20 text-blue-400 border-blue-500/30">
|
||||
Language Reference
|
||||
</Badge>
|
||||
<h1 className="text-4xl font-bold mb-4">Language Syntax</h1>
|
||||
<p className="text-xl text-muted-foreground">
|
||||
Learn the AeThex syntax, from realities and journeys to cross-platform sync.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
{/* Syntax Sections */}
|
||||
<section className="space-y-8">
|
||||
{syntaxSections.map((section) => (
|
||||
<Card key={section.id} id={section.id}>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<section.icon className="w-5 h-5 text-primary" />
|
||||
{section.title}
|
||||
</CardTitle>
|
||||
<CardDescription>{section.description}</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CodeBlock code={section.code} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</section>
|
||||
|
||||
{/* Standard Library */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-6">Standard Library</h2>
|
||||
|
||||
<Tabs defaultValue="core" className="w-full">
|
||||
<TabsList className="grid w-full grid-cols-2">
|
||||
<TabsTrigger value="core">@aethex.os/core</TabsTrigger>
|
||||
<TabsTrigger value="roblox">@aethex.os/roblox</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent value="core" className="mt-6">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Core Library</CardTitle>
|
||||
<CardDescription>
|
||||
Universal utilities for authentication, data sync, and compliance
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CodeBlock code={coreLibraryCode} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
<TabsContent value="roblox" className="mt-6">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Roblox Library</CardTitle>
|
||||
<CardDescription>
|
||||
Roblox-specific features and integrations
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CodeBlock code={robloxLibraryCode} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</section>
|
||||
|
||||
{/* Configuration */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-4">Configuration</h2>
|
||||
<p className="text-muted-foreground mb-6">
|
||||
Configure your project with <code className="bg-slate-800 px-2 py-0.5 rounded text-sm">aethex.config.json</code>:
|
||||
</p>
|
||||
<CodeBlock code={configCode} language="json" />
|
||||
</section>
|
||||
|
||||
{/* Project Structure */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-4">Project Structure</h2>
|
||||
<CodeBlock code={projectStructureCode} />
|
||||
</section>
|
||||
|
||||
{/* Compilation Targets Table */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-6">Compilation Targets</h2>
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full border-collapse">
|
||||
<thead>
|
||||
<tr className="border-b border-slate-700">
|
||||
<th className="text-left py-3 px-4 font-medium">Target</th>
|
||||
<th className="text-left py-3 px-4 font-medium">Extension</th>
|
||||
<th className="text-left py-3 px-4 font-medium">Use Case</th>
|
||||
<th className="text-left py-3 px-4 font-medium">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr className="border-b border-slate-800">
|
||||
<td className="py-3 px-4">JavaScript</td>
|
||||
<td className="py-3 px-4"><code className="bg-slate-800 px-2 py-0.5 rounded text-sm">.js</code></td>
|
||||
<td className="py-3 px-4 text-muted-foreground">Web applications, Node.js backends</td>
|
||||
<td className="py-3 px-4"><Badge className="bg-green-500/20 text-green-400 border-green-500/30">Ready</Badge></td>
|
||||
</tr>
|
||||
<tr className="border-b border-slate-800">
|
||||
<td className="py-3 px-4">Roblox (Lua)</td>
|
||||
<td className="py-3 px-4"><code className="bg-slate-800 px-2 py-0.5 rounded text-sm">.lua</code></td>
|
||||
<td className="py-3 px-4 text-muted-foreground">Roblox games</td>
|
||||
<td className="py-3 px-4"><Badge className="bg-green-500/20 text-green-400 border-green-500/30">Ready</Badge></td>
|
||||
</tr>
|
||||
<tr className="border-b border-slate-800">
|
||||
<td className="py-3 px-4">UEFN (Verse)</td>
|
||||
<td className="py-3 px-4"><code className="bg-slate-800 px-2 py-0.5 rounded text-sm">.verse</code></td>
|
||||
<td className="py-3 px-4 text-muted-foreground">Fortnite Creative</td>
|
||||
<td className="py-3 px-4"><Badge variant="outline" className="text-slate-400">Coming Soon</Badge></td>
|
||||
</tr>
|
||||
<tr className="border-b border-slate-800">
|
||||
<td className="py-3 px-4">Unity (C#)</td>
|
||||
<td className="py-3 px-4"><code className="bg-slate-800 px-2 py-0.5 rounded text-sm">.cs</code></td>
|
||||
<td className="py-3 px-4 text-muted-foreground">Unity games, VRChat</td>
|
||||
<td className="py-3 px-4"><Badge variant="outline" className="text-slate-400">Coming Soon</Badge></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Keywords Reference */}
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold mb-6">Keywords Reference</h2>
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<Card>
|
||||
<CardHeader className="pb-2">
|
||||
<CardTitle className="text-sm font-medium">Declarations</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2 text-sm">
|
||||
<div><code className="bg-slate-800 px-2 py-0.5 rounded">reality</code> - Define a namespace</div>
|
||||
<div><code className="bg-slate-800 px-2 py-0.5 rounded">journey</code> - Define a function</div>
|
||||
<div><code className="bg-slate-800 px-2 py-0.5 rounded">let</code> - Declare a variable</div>
|
||||
<div><code className="bg-slate-800 px-2 py-0.5 rounded">import</code> - Import from libraries</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader className="pb-2">
|
||||
<CardTitle className="text-sm font-medium">Control Flow</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2 text-sm">
|
||||
<div><code className="bg-slate-800 px-2 py-0.5 rounded">when</code> - Conditional (if)</div>
|
||||
<div><code className="bg-slate-800 px-2 py-0.5 rounded">otherwise</code> - Else clause</div>
|
||||
<div><code className="bg-slate-800 px-2 py-0.5 rounded">return</code> - Return from journey</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader className="pb-2">
|
||||
<CardTitle className="text-sm font-medium">Cross-Platform</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2 text-sm">
|
||||
<div><code className="bg-slate-800 px-2 py-0.5 rounded">sync ... across</code> - Sync data</div>
|
||||
<div><code className="bg-slate-800 px-2 py-0.5 rounded">platform:</code> - Target platforms</div>
|
||||
<div><code className="bg-slate-800 px-2 py-0.5 rounded">platforms:</code> - Reality platforms</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader className="pb-2">
|
||||
<CardTitle className="text-sm font-medium">Actions</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2 text-sm">
|
||||
<div><code className="bg-slate-800 px-2 py-0.5 rounded">notify</code> - Output message</div>
|
||||
<div><code className="bg-slate-800 px-2 py-0.5 rounded">reveal</code> - Return/expose data</div>
|
||||
<div><code className="bg-slate-800 px-2 py-0.5 rounded">new</code> - Create instance</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Navigation */}
|
||||
<section className="flex justify-between pt-8 border-t border-border/50">
|
||||
<Link to="/docs/lang/quickstart" className="text-sm text-muted-foreground hover:text-foreground">
|
||||
← Quick Start
|
||||
</Link>
|
||||
<Link to="/docs/lang/cli" className="text-sm text-muted-foreground hover:text-foreground">
|
||||
CLI Reference →
|
||||
</Link>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -115,13 +115,12 @@ export default function OpportunitiesHub() {
|
|||
<div className="text-center mb-8">
|
||||
<div className="inline-flex items-center justify-center gap-2 mb-4">
|
||||
<Briefcase className="h-8 w-8 text-cyan-400" />
|
||||
<h1 className="text-4xl lg:text-5xl font-black text-white">
|
||||
<h1 className="text-4xl font-bold text-white">
|
||||
Opportunities
|
||||
</h1>
|
||||
</div>
|
||||
<p className="text-lg text-gray-300 max-w-2xl mx-auto mb-6">
|
||||
Find jobs, collaborations, and research opportunities across
|
||||
all AeThex arms.
|
||||
<p className="text-base text-gray-300 max-w-2xl mx-auto mb-6">
|
||||
Find jobs and collaborations across AeThex
|
||||
</p>
|
||||
<div className="flex justify-center gap-3">
|
||||
<Button
|
||||
|
|
|
|||
205
server/index.ts
|
|
@ -1038,6 +1038,211 @@ export function createServer() {
|
|||
}
|
||||
});
|
||||
|
||||
// =====================================================
|
||||
// Foundation OAuth Callback Routes
|
||||
// =====================================================
|
||||
const FOUNDATION_URL = process.env.VITE_FOUNDATION_URL || "https://aethex.foundation";
|
||||
const FOUNDATION_CLIENT_ID = process.env.FOUNDATION_OAUTH_CLIENT_ID || "aethex_corp";
|
||||
const FOUNDATION_CLIENT_SECRET = process.env.FOUNDATION_OAUTH_CLIENT_SECRET;
|
||||
const API_BASE = process.env.VITE_API_BASE || "https://aethex.dev";
|
||||
|
||||
// GET /auth/callback - Receives authorization code from Foundation
|
||||
app.get("/auth/callback", async (req, res) => {
|
||||
const { code, state, error, error_description } = req.query;
|
||||
|
||||
// Handle Foundation errors
|
||||
if (error) {
|
||||
const message = error_description
|
||||
? decodeURIComponent(String(error_description))
|
||||
: String(error);
|
||||
return res.redirect(`/login?error=${error}&message=${encodeURIComponent(message)}`);
|
||||
}
|
||||
|
||||
if (!code) {
|
||||
return res.redirect(`/login?error=no_code&message=${encodeURIComponent("No authorization code received")}`);
|
||||
}
|
||||
|
||||
try {
|
||||
console.log("[Foundation OAuth] Received authorization code, initiating token exchange");
|
||||
|
||||
// Exchange code for token
|
||||
if (!FOUNDATION_CLIENT_SECRET) {
|
||||
throw new Error("FOUNDATION_OAUTH_CLIENT_SECRET not configured");
|
||||
}
|
||||
|
||||
const tokenEndpoint = `${FOUNDATION_URL}/api/oauth/token`;
|
||||
const params = new URLSearchParams();
|
||||
params.append("grant_type", "authorization_code");
|
||||
params.append("code", String(code));
|
||||
params.append("client_id", FOUNDATION_CLIENT_ID);
|
||||
params.append("client_secret", FOUNDATION_CLIENT_SECRET);
|
||||
params.append("redirect_uri", `${API_BASE}/auth/callback`);
|
||||
|
||||
const tokenResponse = await fetch(tokenEndpoint, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||
body: params.toString(),
|
||||
});
|
||||
|
||||
if (!tokenResponse.ok) {
|
||||
const errorData = await tokenResponse.json().catch(() => ({}));
|
||||
console.error("[Foundation OAuth] Token exchange failed:", errorData);
|
||||
throw new Error(`Token exchange failed: ${tokenResponse.status}`);
|
||||
}
|
||||
|
||||
const tokenData = await tokenResponse.json();
|
||||
if (!tokenData.access_token) {
|
||||
throw new Error("No access token in Foundation response");
|
||||
}
|
||||
|
||||
// Fetch user info from Foundation
|
||||
const userInfoResponse = await fetch(`${FOUNDATION_URL}/api/oauth/userinfo`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
Authorization: `Bearer ${tokenData.access_token}`,
|
||||
Accept: "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
if (!userInfoResponse.ok) {
|
||||
throw new Error(`Failed to fetch user info: ${userInfoResponse.status}`);
|
||||
}
|
||||
|
||||
const userInfo = await userInfoResponse.json();
|
||||
if (!userInfo.id || !userInfo.email) {
|
||||
throw new Error("Invalid user info from Foundation");
|
||||
}
|
||||
|
||||
console.log("[Foundation OAuth] User authenticated:", userInfo.id);
|
||||
|
||||
// Sync user to local database
|
||||
const now = new Date().toISOString();
|
||||
const cacheValidUntil = new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString();
|
||||
|
||||
await adminSupabase.from("user_profiles").upsert({
|
||||
id: userInfo.id,
|
||||
email: userInfo.email,
|
||||
username: userInfo.username || null,
|
||||
full_name: userInfo.full_name || null,
|
||||
avatar_url: userInfo.avatar_url || null,
|
||||
profile_completed: userInfo.profile_complete || false,
|
||||
foundation_synced_at: now,
|
||||
cache_valid_until: cacheValidUntil,
|
||||
updated_at: now,
|
||||
});
|
||||
|
||||
// Set session cookies
|
||||
res.cookie("foundation_access_token", tokenData.access_token, {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === "production",
|
||||
sameSite: "strict",
|
||||
maxAge: (tokenData.expires_in || 3600) * 1000,
|
||||
});
|
||||
res.cookie("auth_user_id", userInfo.id, {
|
||||
secure: process.env.NODE_ENV === "production",
|
||||
sameSite: "strict",
|
||||
maxAge: 30 * 24 * 60 * 60 * 1000, // 30 days
|
||||
});
|
||||
|
||||
// Redirect to dashboard or stored destination
|
||||
const redirectTo = (req.query.redirect_to as string) || "/dashboard";
|
||||
return res.redirect(redirectTo);
|
||||
} catch (err: any) {
|
||||
console.error("[Foundation OAuth] Callback error:", err);
|
||||
const message = err?.message || "Authentication failed";
|
||||
return res.redirect(`/login?error=auth_failed&message=${encodeURIComponent(message)}`);
|
||||
}
|
||||
});
|
||||
|
||||
// POST /auth/callback/exchange - Exchange code for token (called from frontend)
|
||||
app.post("/auth/callback/exchange", async (req, res) => {
|
||||
const { code } = req.body || {};
|
||||
|
||||
if (!code) {
|
||||
return res.status(400).json({ error: "Authorization code is required" });
|
||||
}
|
||||
|
||||
try {
|
||||
if (!FOUNDATION_CLIENT_SECRET) {
|
||||
throw new Error("FOUNDATION_OAUTH_CLIENT_SECRET not configured");
|
||||
}
|
||||
|
||||
const tokenEndpoint = `${FOUNDATION_URL}/api/oauth/token`;
|
||||
const params = new URLSearchParams();
|
||||
params.append("grant_type", "authorization_code");
|
||||
params.append("code", code);
|
||||
params.append("client_id", FOUNDATION_CLIENT_ID);
|
||||
params.append("client_secret", FOUNDATION_CLIENT_SECRET);
|
||||
params.append("redirect_uri", `${API_BASE}/auth/callback`);
|
||||
|
||||
const tokenResponse = await fetch(tokenEndpoint, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||
body: params.toString(),
|
||||
});
|
||||
|
||||
if (!tokenResponse.ok) {
|
||||
const errorData = await tokenResponse.json().catch(() => ({}));
|
||||
throw new Error(`Token exchange failed: ${tokenResponse.status}`);
|
||||
}
|
||||
|
||||
const tokenData = await tokenResponse.json();
|
||||
if (!tokenData.access_token) {
|
||||
throw new Error("No access token in Foundation response");
|
||||
}
|
||||
|
||||
// Fetch user info from Foundation
|
||||
const userInfoResponse = await fetch(`${FOUNDATION_URL}/api/oauth/userinfo`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
Authorization: `Bearer ${tokenData.access_token}`,
|
||||
Accept: "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
if (!userInfoResponse.ok) {
|
||||
throw new Error(`Failed to fetch user info: ${userInfoResponse.status}`);
|
||||
}
|
||||
|
||||
const userInfo = await userInfoResponse.json();
|
||||
|
||||
// Sync user to local database
|
||||
const now = new Date().toISOString();
|
||||
const cacheValidUntil = new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString();
|
||||
|
||||
await adminSupabase.from("user_profiles").upsert({
|
||||
id: userInfo.id,
|
||||
email: userInfo.email,
|
||||
username: userInfo.username || null,
|
||||
full_name: userInfo.full_name || null,
|
||||
avatar_url: userInfo.avatar_url || null,
|
||||
profile_completed: userInfo.profile_complete || false,
|
||||
foundation_synced_at: now,
|
||||
cache_valid_until: cacheValidUntil,
|
||||
updated_at: now,
|
||||
});
|
||||
|
||||
// Set session cookies
|
||||
res.cookie("foundation_access_token", tokenData.access_token, {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === "production",
|
||||
sameSite: "strict",
|
||||
maxAge: (tokenData.expires_in || 3600) * 1000,
|
||||
});
|
||||
res.cookie("auth_user_id", userInfo.id, {
|
||||
secure: process.env.NODE_ENV === "production",
|
||||
sameSite: "strict",
|
||||
maxAge: 30 * 24 * 60 * 60 * 1000,
|
||||
});
|
||||
|
||||
console.log("[Foundation OAuth] Token exchange successful for:", userInfo.id);
|
||||
return res.json({ accessToken: tokenData.access_token, user: userInfo });
|
||||
} catch (err: any) {
|
||||
console.error("[Foundation OAuth] Token exchange error:", err);
|
||||
return res.status(400).json({ error: err?.message || "Token exchange failed" });
|
||||
}
|
||||
});
|
||||
|
||||
// Admin-backed API (service role)
|
||||
try {
|
||||
const ownerEmail = (
|
||||
|
|
|
|||
|
|
@ -109,14 +109,14 @@ CREATE TABLE notifications (
|
|||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Insert default achievements
|
||||
INSERT INTO achievements (name, description, icon, xp_reward, badge_color) VALUES
|
||||
('Welcome to AeThex', 'Complete your profile setup', '🎉', 100, '#10B981'),
|
||||
('First Project', 'Create your first project', '🚀', 150, '#3B82F6'),
|
||||
('Community Contributor', 'Make your first community post', '💬', 75, '#8B5CF6'),
|
||||
('Level Up', 'Reach level 5', '⭐', 200, '#F59E0B'),
|
||||
('Experienced Developer', 'Complete 5 projects', '👨💻', 300, '#EF4444'),
|
||||
('Community Leader', 'Get 100 likes on your posts', '👑', 500, '#F97316');
|
||||
|
||||
-- Insert core achievements with deterministic UUIDs to match activate.ts
|
||||
INSERT INTO achievements (id, name, description, icon, xp_reward, badge_color) VALUES
|
||||
('b6e2e1e2-2e2e-5e2e-8e2e-e2e2e2e2e2e2', 'Welcome to AeThex', 'Completed onboarding and joined the AeThex network.', '🎉', 250, '#7C3AED'),
|
||||
('c1e2e1e2-2e2e-5e2e-8e2e-e2e2e2e2e2e2', 'AeThex Explorer', 'Engaged with community initiatives and posted first update.', '🧭', 400, '#0EA5E9'),
|
||||
('d1e2e1e2-2e2e-5e2e-8e2e-e2e2e2e2e2e2', 'Community Champion', 'Contributed feedback, resolved bugs, and mentored squads.', '🏆', 750, '#22C55E'),
|
||||
('e1e2e1e2-2e2e-5e2e-8e2e-e2e2e2e2e2e2', 'Workshop Architect', 'Published a high-impact mod or toolkit adopted by teams.', '🛠️', 1200, '#F97316'),
|
||||
('f1e2e1e2-2e2e-5e2e-8e2e-e2e2e2e2e2e2', 'GOD Mode', 'Legendary status awarded by AeThex studio leadership.', '⚡', 5000, '#FACC15');
|
||||
|
||||
-- Enable Row Level Security (RLS)
|
||||
ALTER TABLE user_profiles ENABLE ROW LEVEL SECURITY;
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
v2.67.1
|
||||
v2.75.0
|
||||
|
|
@ -47,19 +47,14 @@ CREATE INDEX IF NOT EXISTS idx_user_profiles_stripe_customer ON user_profiles(st
|
|||
ALTER TABLE badges ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE user_badges ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- 7. RLS Policies for badges (read-only for authenticated users)
|
||||
CREATE POLICY IF NOT EXISTS "Badges are viewable by everyone"
|
||||
ON badges FOR SELECT
|
||||
USING (true);
|
||||
DROP POLICY IF EXISTS "Badges are viewable by everyone" ON badges;
|
||||
CREATE POLICY "Badges are viewable by everyone" ON badges FOR SELECT USING (true);
|
||||
|
||||
-- 8. RLS Policies for user_badges
|
||||
CREATE POLICY IF NOT EXISTS "Users can view their own badges"
|
||||
ON user_badges FOR SELECT
|
||||
USING (auth.uid() = user_id);
|
||||
DROP POLICY IF EXISTS "Users can view their own badges" ON user_badges;
|
||||
CREATE POLICY "Users can view their own badges" ON user_badges FOR SELECT USING (auth.uid() = user_id);
|
||||
|
||||
CREATE POLICY IF NOT EXISTS "Users can view others badges"
|
||||
ON user_badges FOR SELECT
|
||||
USING (true);
|
||||
DROP POLICY IF EXISTS "Users can view others badges" ON user_badges;
|
||||
CREATE POLICY "Users can view others badges" ON user_badges FOR SELECT USING (true);
|
||||
|
||||
-- 9. Seed initial badges that unlock AI personas
|
||||
INSERT INTO badges (name, slug, description, icon, unlock_criteria, unlocks_persona) VALUES
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ CREATE INDEX IF NOT EXISTS idx_discord_linking_sessions_token ON discord_linking
|
|||
CREATE INDEX IF NOT EXISTS idx_discord_linking_sessions_expires ON discord_linking_sessions(expires_at);
|
||||
|
||||
ALTER TABLE discord_linking_sessions ENABLE ROW LEVEL SECURITY;
|
||||
DROP POLICY IF EXISTS "discord_linking_sessions_service_role" ON discord_linking_sessions;
|
||||
CREATE POLICY "discord_linking_sessions_service_role" ON discord_linking_sessions
|
||||
FOR ALL TO service_role USING (true);
|
||||
|
||||
|
|
@ -73,35 +74,42 @@ CREATE INDEX IF NOT EXISTS idx_discord_user_roles_server ON discord_user_roles(s
|
|||
-- RLS Policies
|
||||
|
||||
ALTER TABLE discord_links ENABLE ROW LEVEL SECURITY;
|
||||
DROP POLICY IF EXISTS "discord_links_users_select" ON discord_links;
|
||||
CREATE POLICY "discord_links_users_select" ON discord_links
|
||||
FOR SELECT TO authenticated
|
||||
USING (user_id = auth.uid());
|
||||
|
||||
DROP POLICY IF EXISTS "discord_links_service_role" ON discord_links;
|
||||
CREATE POLICY "discord_links_service_role" ON discord_links
|
||||
FOR ALL TO service_role
|
||||
USING (true);
|
||||
|
||||
ALTER TABLE discord_verifications ENABLE ROW LEVEL SECURITY;
|
||||
DROP POLICY IF EXISTS "discord_verifications_service_role" ON discord_verifications;
|
||||
CREATE POLICY "discord_verifications_service_role" ON discord_verifications
|
||||
FOR ALL TO service_role
|
||||
USING (true);
|
||||
|
||||
ALTER TABLE discord_role_mappings ENABLE ROW LEVEL SECURITY;
|
||||
DROP POLICY IF EXISTS "discord_role_mappings_public_read" ON discord_role_mappings;
|
||||
CREATE POLICY "discord_role_mappings_public_read" ON discord_role_mappings
|
||||
FOR SELECT
|
||||
USING (true);
|
||||
|
||||
DROP POLICY IF EXISTS "discord_role_mappings_admin_write" ON discord_role_mappings;
|
||||
CREATE POLICY "discord_role_mappings_admin_write" ON discord_role_mappings
|
||||
FOR INSERT
|
||||
TO service_role
|
||||
WITH CHECK (true);
|
||||
|
||||
DROP POLICY IF EXISTS "discord_role_mappings_admin_update" ON discord_role_mappings;
|
||||
CREATE POLICY "discord_role_mappings_admin_update" ON discord_role_mappings
|
||||
FOR UPDATE
|
||||
TO service_role
|
||||
USING (true);
|
||||
|
||||
ALTER TABLE discord_user_roles ENABLE ROW LEVEL SECURITY;
|
||||
DROP POLICY IF EXISTS "discord_user_roles_service_role" ON discord_user_roles;
|
||||
CREATE POLICY "discord_user_roles_service_role" ON discord_user_roles
|
||||
FOR ALL TO service_role
|
||||
USING (true);
|
||||
|
|
|
|||
|
|
@ -94,28 +94,32 @@ ALTER TABLE game_sessions ENABLE ROW LEVEL SECURITY;
|
|||
ALTER TABLE roblox_links ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE web3_wallets ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- Public tables for game auth (service role only for inserts)
|
||||
DROP POLICY IF EXISTS "game_auth_tokens_service_insert" ON game_auth_tokens;
|
||||
CREATE POLICY "game_auth_tokens_service_insert" ON game_auth_tokens
|
||||
FOR INSERT TO anon, authenticated
|
||||
WITH CHECK (false);
|
||||
|
||||
DROP POLICY IF EXISTS "game_sessions_service_insert" ON game_sessions;
|
||||
CREATE POLICY "game_sessions_service_insert" ON game_sessions
|
||||
FOR INSERT TO anon, authenticated
|
||||
WITH CHECK (false);
|
||||
|
||||
-- Allow authenticated users to view their own game data
|
||||
DROP POLICY IF EXISTS "game_auth_tokens_user_select" ON game_auth_tokens;
|
||||
CREATE POLICY "game_auth_tokens_user_select" ON game_auth_tokens
|
||||
FOR SELECT TO authenticated
|
||||
USING (user_id = auth.uid());
|
||||
|
||||
DROP POLICY IF EXISTS "game_sessions_user_select" ON game_sessions;
|
||||
CREATE POLICY "game_sessions_user_select" ON game_sessions
|
||||
FOR SELECT TO authenticated
|
||||
USING (user_id = auth.uid());
|
||||
|
||||
DROP POLICY IF EXISTS "roblox_links_user_select" ON roblox_links;
|
||||
CREATE POLICY "roblox_links_user_select" ON roblox_links
|
||||
FOR SELECT TO authenticated
|
||||
USING (user_id = auth.uid());
|
||||
|
||||
DROP POLICY IF EXISTS "web3_wallets_user_select" ON web3_wallets;
|
||||
CREATE POLICY "web3_wallets_user_select" ON web3_wallets
|
||||
FOR SELECT TO authenticated
|
||||
USING (user_id = auth.uid());
|
||||
|
|
|
|||
|
|
@ -48,22 +48,25 @@ ALTER TABLE fourthwall_products ENABLE ROW LEVEL SECURITY;
|
|||
ALTER TABLE fourthwall_orders ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE fourthwall_webhook_logs ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- Create RLS policies - allow authenticated users to read, admins to manage
|
||||
DROP POLICY IF EXISTS "Allow authenticated users to read fourthwall products" ON fourthwall_products;
|
||||
CREATE POLICY "Allow authenticated users to read fourthwall products"
|
||||
ON fourthwall_products
|
||||
FOR SELECT
|
||||
USING (true);
|
||||
|
||||
DROP POLICY IF EXISTS "Allow service role to manage fourthwall products" ON fourthwall_products;
|
||||
CREATE POLICY "Allow service role to manage fourthwall products"
|
||||
ON fourthwall_products
|
||||
FOR ALL
|
||||
USING (auth.role() = 'service_role');
|
||||
|
||||
DROP POLICY IF EXISTS "Allow service role to manage fourthwall orders" ON fourthwall_orders;
|
||||
CREATE POLICY "Allow service role to manage fourthwall orders"
|
||||
ON fourthwall_orders
|
||||
FOR ALL
|
||||
USING (auth.role() = 'service_role');
|
||||
|
||||
DROP POLICY IF EXISTS "Allow service role to manage webhook logs" ON fourthwall_webhook_logs;
|
||||
CREATE POLICY "Allow service role to manage webhook logs"
|
||||
ON fourthwall_webhook_logs
|
||||
FOR ALL
|
||||
|
|
|
|||
|
|
@ -44,27 +44,27 @@ GRANT SELECT, INSERT, UPDATE, DELETE ON public.provider_identities TO service_ro
|
|||
-- Enable RLS
|
||||
ALTER TABLE public.provider_identities ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- Users can only see their own provider identities
|
||||
DROP POLICY IF EXISTS "Users can view own provider identities" ON public.provider_identities;
|
||||
CREATE POLICY "Users can view own provider identities"
|
||||
ON public.provider_identities FOR SELECT
|
||||
USING (auth.uid() = user_id);
|
||||
|
||||
-- Users can only insert their own provider identities
|
||||
DROP POLICY IF EXISTS "Users can insert own provider identities" ON public.provider_identities;
|
||||
CREATE POLICY "Users can insert own provider identities"
|
||||
ON public.provider_identities FOR INSERT
|
||||
WITH CHECK (auth.uid() = user_id);
|
||||
|
||||
-- Users can only update their own provider identities
|
||||
DROP POLICY IF EXISTS "Users can update own provider identities" ON public.provider_identities;
|
||||
CREATE POLICY "Users can update own provider identities"
|
||||
ON public.provider_identities FOR UPDATE
|
||||
USING (auth.uid() = user_id);
|
||||
|
||||
-- Users can only delete their own provider identities
|
||||
DROP POLICY IF EXISTS "Users can delete own provider identities" ON public.provider_identities;
|
||||
CREATE POLICY "Users can delete own provider identities"
|
||||
ON public.provider_identities FOR DELETE
|
||||
USING (auth.uid() = user_id);
|
||||
|
||||
-- Service role can do anything for OAuth flows
|
||||
DROP POLICY IF EXISTS "Service role can manage all provider identities" ON public.provider_identities;
|
||||
CREATE POLICY "Service role can manage all provider identities"
|
||||
ON public.provider_identities
|
||||
FOR ALL
|
||||
|
|
|
|||
|
|
@ -47,17 +47,19 @@ ALTER TABLE public.collaboration_posts_authors ENABLE ROW LEVEL SECURITY;
|
|||
ALTER TABLE public.collaboration_post_likes ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE public.collaboration_comments ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- Policies for collaboration_posts
|
||||
DROP POLICY IF EXISTS "collaboration_posts_read" ON public.collaboration_posts;
|
||||
CREATE POLICY "collaboration_posts_read" ON public.collaboration_posts
|
||||
FOR SELECT TO authenticated USING (is_published = true);
|
||||
|
||||
DROP POLICY IF EXISTS "collaboration_posts_manage_own" ON public.collaboration_posts;
|
||||
CREATE POLICY "collaboration_posts_manage_own" ON public.collaboration_posts
|
||||
FOR ALL TO authenticated USING (created_by = auth.uid()) WITH CHECK (created_by = auth.uid());
|
||||
|
||||
-- Policies for collaboration_posts_authors
|
||||
DROP POLICY IF EXISTS "collaboration_posts_authors_read" ON public.collaboration_posts_authors;
|
||||
CREATE POLICY "collaboration_posts_authors_read" ON public.collaboration_posts_authors
|
||||
FOR SELECT TO authenticated USING (true);
|
||||
|
||||
DROP POLICY IF EXISTS "collaboration_posts_authors_manage" ON public.collaboration_posts_authors;
|
||||
CREATE POLICY "collaboration_posts_authors_manage" ON public.collaboration_posts_authors
|
||||
FOR ALL TO authenticated
|
||||
USING (
|
||||
|
|
@ -73,17 +75,19 @@ CREATE POLICY "collaboration_posts_authors_manage" ON public.collaboration_posts
|
|||
)
|
||||
);
|
||||
|
||||
-- Policies for collaboration_post_likes
|
||||
DROP POLICY IF EXISTS "collaboration_post_likes_read" ON public.collaboration_post_likes;
|
||||
CREATE POLICY "collaboration_post_likes_read" ON public.collaboration_post_likes
|
||||
FOR SELECT TO authenticated USING (true);
|
||||
|
||||
DROP POLICY IF EXISTS "collaboration_post_likes_manage_self" ON public.collaboration_post_likes;
|
||||
CREATE POLICY "collaboration_post_likes_manage_self" ON public.collaboration_post_likes
|
||||
FOR ALL TO authenticated USING (user_id = auth.uid()) WITH CHECK (user_id = auth.uid());
|
||||
|
||||
-- Policies for collaboration_comments
|
||||
DROP POLICY IF EXISTS "collaboration_comments_read" ON public.collaboration_comments;
|
||||
CREATE POLICY "collaboration_comments_read" ON public.collaboration_comments
|
||||
FOR SELECT TO authenticated USING (true);
|
||||
|
||||
DROP POLICY IF EXISTS "collaboration_comments_manage_self" ON public.collaboration_comments;
|
||||
CREATE POLICY "collaboration_comments_manage_self" ON public.collaboration_comments
|
||||
FOR ALL TO authenticated USING (user_id = auth.uid()) WITH CHECK (user_id = auth.uid());
|
||||
|
||||
|
|
|
|||
|
|
@ -23,11 +23,11 @@ CREATE INDEX IF NOT EXISTS idx_user_followed_arms_arm_id ON public.user_followed
|
|||
-- Enable RLS on user_followed_arms
|
||||
ALTER TABLE public.user_followed_arms ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- Policy: Users can read all followed arms data
|
||||
DROP POLICY IF EXISTS "user_followed_arms_read" ON public.user_followed_arms;
|
||||
CREATE POLICY "user_followed_arms_read" ON public.user_followed_arms
|
||||
FOR SELECT TO authenticated USING (true);
|
||||
|
||||
-- Policy: Users can manage their own followed arms
|
||||
DROP POLICY IF EXISTS "user_followed_arms_manage_self" ON public.user_followed_arms;
|
||||
CREATE POLICY "user_followed_arms_manage_self" ON public.user_followed_arms
|
||||
FOR ALL TO authenticated USING (user_id = auth.uid()) WITH CHECK (user_id = auth.uid());
|
||||
|
||||
|
|
|
|||
|
|
@ -54,18 +54,18 @@ ALTER TABLE staff_contractors ENABLE ROW LEVEL SECURITY;
|
|||
|
||||
-- Staff members policies
|
||||
|
||||
-- Allow authenticated users to read all staff members (directory)
|
||||
DROP POLICY IF EXISTS "staff_members_select_authenticated" ON staff_members;
|
||||
CREATE POLICY "staff_members_select_authenticated" ON staff_members
|
||||
FOR SELECT
|
||||
USING (auth.role() = 'authenticated');
|
||||
|
||||
-- Allow staff members to update their own record
|
||||
DROP POLICY IF EXISTS "staff_members_update_own" ON staff_members;
|
||||
CREATE POLICY "staff_members_update_own" ON staff_members
|
||||
FOR UPDATE
|
||||
USING (auth.uid() = user_id OR auth.role() = 'service_role')
|
||||
WITH CHECK (auth.uid() = user_id OR auth.role() = 'service_role');
|
||||
|
||||
-- Allow admins to do anything
|
||||
DROP POLICY IF EXISTS "staff_members_admin_all" ON staff_members;
|
||||
CREATE POLICY "staff_members_admin_all" ON staff_members
|
||||
FOR ALL
|
||||
USING (
|
||||
|
|
@ -79,18 +79,18 @@ CREATE POLICY "staff_members_admin_all" ON staff_members
|
|||
|
||||
-- Staff contractors policies
|
||||
|
||||
-- Allow authenticated users to read all contractors (directory)
|
||||
DROP POLICY IF EXISTS "staff_contractors_select_authenticated" ON staff_contractors;
|
||||
CREATE POLICY "staff_contractors_select_authenticated" ON staff_contractors
|
||||
FOR SELECT
|
||||
USING (auth.role() = 'authenticated');
|
||||
|
||||
-- Allow contractors to update their own record
|
||||
DROP POLICY IF EXISTS "staff_contractors_update_own" ON staff_contractors;
|
||||
CREATE POLICY "staff_contractors_update_own" ON staff_contractors
|
||||
FOR UPDATE
|
||||
USING (auth.uid() = user_id OR auth.role() = 'service_role')
|
||||
WITH CHECK (auth.uid() = user_id OR auth.role() = 'service_role');
|
||||
|
||||
-- Allow admins to do anything
|
||||
DROP POLICY IF EXISTS "staff_contractors_admin_all" ON staff_contractors;
|
||||
CREATE POLICY "staff_contractors_admin_all" ON staff_contractors
|
||||
FOR ALL
|
||||
USING (
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ CREATE INDEX idx_user_email_links_primary ON user_email_links(user_id, is_primar
|
|||
-- Enable RLS
|
||||
ALTER TABLE user_email_links ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- RLS: Users can view their own linked emails
|
||||
DROP POLICY IF EXISTS "Users can view own email links" ON user_email_links;
|
||||
CREATE POLICY "Users can view own email links"
|
||||
ON user_email_links
|
||||
FOR SELECT
|
||||
|
|
@ -29,7 +29,7 @@ CREATE POLICY "Users can view own email links"
|
|||
)
|
||||
);
|
||||
|
||||
-- RLS: Service role can do anything (for backend operations)
|
||||
DROP POLICY IF EXISTS "Service role full access" ON user_email_links;
|
||||
CREATE POLICY "Service role full access"
|
||||
ON user_email_links
|
||||
FOR ALL
|
||||
|
|
|
|||
|
|
@ -86,33 +86,45 @@ alter table public.ethos_artist_profiles enable row level security;
|
|||
alter table public.ethos_guild_members enable row level security;
|
||||
alter table public.ethos_licensing_agreements enable row level security;
|
||||
|
||||
-- RLS Policies: ethos_tracks
|
||||
drop policy if exists "Ethos tracks are readable by all authenticated users" on public.ethos_tracks;
|
||||
create policy "Ethos tracks are readable by all authenticated users" on public.ethos_tracks
|
||||
for select using (auth.role() = 'authenticated');
|
||||
|
||||
create policy "Users can insert their own tracks" on public.ethos_tracks
|
||||
drop policy if exists "Users can insert their own tracks" on public.ethos_tracks;
|
||||
create policy "Users can insert their own tracks" on public.ethos_tracks
|
||||
for insert with check (auth.uid() = user_id);
|
||||
|
||||
create policy "Users can update their own tracks" on public.ethos_tracks
|
||||
drop policy if exists "Users can update their own tracks" on public.ethos_tracks;
|
||||
create policy "Users can update their own tracks" on public.ethos_tracks
|
||||
for update using (auth.uid() = user_id);
|
||||
|
||||
create policy "Users can delete their own tracks" on public.ethos_tracks
|
||||
drop policy if exists "Users can delete their own tracks" on public.ethos_tracks;
|
||||
create policy "Users can delete their own tracks" on public.ethos_tracks
|
||||
for delete using (auth.uid() = user_id);
|
||||
|
||||
-- RLS Policies: ethos_artist_profiles
|
||||
drop policy if exists "Ethos artist profiles are readable by all authenticated users" on public.ethos_artist_profiles;
|
||||
create policy "Ethos artist profiles are readable by all authenticated users" on public.ethos_artist_profiles
|
||||
for select using (auth.role() = 'authenticated');
|
||||
|
||||
create policy "Users can insert their own artist profile" on public.ethos_artist_profiles
|
||||
drop policy if exists "Users can insert their own artist profile" on public.ethos_artist_profiles;
|
||||
create policy "Users can insert their own artist profile" on public.ethos_artist_profiles
|
||||
for insert with check (auth.uid() = user_id);
|
||||
|
||||
create policy "Users can update their own artist profile" on public.ethos_artist_profiles
|
||||
drop policy if exists "Users can update their own artist profile" on public.ethos_artist_profiles;
|
||||
create policy "Users can update their own artist profile" on public.ethos_artist_profiles
|
||||
for update using (auth.uid() = user_id);
|
||||
|
||||
-- RLS Policies: ethos_guild_members
|
||||
drop policy if exists "Guild membership is readable by all authenticated users" on public.ethos_guild_members;
|
||||
create policy "Guild membership is readable by all authenticated users" on public.ethos_guild_members
|
||||
for select using (auth.role() = 'authenticated');
|
||||
|
||||
create policy "Admins can manage guild members" on public.ethos_guild_members
|
||||
drop policy if exists "Admins can manage guild members" on public.ethos_guild_members;
|
||||
create policy "Admins can manage guild members" on public.ethos_guild_members
|
||||
for all using (
|
||||
exists(
|
||||
|
|
@ -121,10 +133,12 @@ create policy "Admins can manage guild members" on public.ethos_guild_members
|
|||
)
|
||||
);
|
||||
|
||||
create policy "Users can see their own membership" on public.ethos_guild_members
|
||||
drop policy if exists "Users can see their own membership" on public.ethos_guild_members;
|
||||
create policy "Users can see their own membership" on public.ethos_guild_members
|
||||
for select using (auth.uid() = user_id or auth.role() = 'authenticated');
|
||||
|
||||
-- RLS Policies: ethos_licensing_agreements
|
||||
drop policy if exists "Licensing agreements readable by involved parties" on public.ethos_licensing_agreements;
|
||||
create policy "Licensing agreements readable by involved parties" on public.ethos_licensing_agreements
|
||||
for select using (
|
||||
auth.uid() in (
|
||||
|
|
|
|||
|
|
@ -43,9 +43,13 @@ alter table public.ethos_verification_requests enable row level security;
|
|||
alter table public.ethos_verification_audit_log enable row level security;
|
||||
|
||||
-- RLS Policies: ethos_verification_requests
|
||||
create policy "Artists can view their own verification request" on public.ethos_verification_requests
|
||||
drop policy if exists "Artists can view their own verification request" on public.ethos_verification_requests;
|
||||
create policy "Artists can view their own verification request" on public.ethos_verification_requests
|
||||
for select using (auth.uid() = user_id);
|
||||
|
||||
create policy "Admins can view all verification requests" on public.ethos_verification_requests
|
||||
drop policy if exists "Admins can view all verification requests" on public.ethos_verification_requests;
|
||||
create policy "Admins can view all verification requests" on public.ethos_verification_requests
|
||||
for select using (
|
||||
exists(
|
||||
|
|
@ -54,9 +58,13 @@ create policy "Admins can view all verification requests" on public.ethos_verifi
|
|||
)
|
||||
);
|
||||
|
||||
create policy "Artists can submit verification request" on public.ethos_verification_requests
|
||||
drop policy if exists "Artists can submit verification request" on public.ethos_verification_requests;
|
||||
create policy "Artists can submit verification request" on public.ethos_verification_requests
|
||||
for insert with check (auth.uid() = user_id);
|
||||
|
||||
create policy "Admins can update verification status" on public.ethos_verification_requests
|
||||
drop policy if exists "Admins can update verification status" on public.ethos_verification_requests;
|
||||
create policy "Admins can update verification status" on public.ethos_verification_requests
|
||||
for update using (
|
||||
exists(
|
||||
|
|
@ -66,6 +74,8 @@ create policy "Admins can update verification status" on public.ethos_verificati
|
|||
);
|
||||
|
||||
-- RLS Policies: ethos_verification_audit_log
|
||||
create policy "Admins can view audit log" on public.ethos_verification_audit_log
|
||||
drop policy if exists "Admins can view audit log" on public.ethos_verification_audit_log;
|
||||
create policy "Admins can view audit log" on public.ethos_verification_audit_log
|
||||
for select using (
|
||||
exists(
|
||||
|
|
@ -74,6 +84,8 @@ create policy "Admins can view audit log" on public.ethos_verification_audit_log
|
|||
)
|
||||
);
|
||||
|
||||
create policy "System can write audit logs" on public.ethos_verification_audit_log
|
||||
drop policy if exists "System can write audit logs" on public.ethos_verification_audit_log;
|
||||
create policy "System can write audit logs" on public.ethos_verification_audit_log
|
||||
for insert with check (true);
|
||||
|
||||
|
|
|
|||
|
|
@ -44,9 +44,13 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_ethos_ecosystem_licenses_unique ON public.
|
|||
ALTER TABLE public.ethos_ecosystem_licenses ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- RLS Policies: ethos_ecosystem_licenses
|
||||
CREATE POLICY "Artists can view their own ecosystem licenses" ON public.ethos_ecosystem_licenses
|
||||
DROP POLICY IF EXISTS "Artists can view their own ecosystem licenses" ON public.ethos_ecosystem_licenses;
|
||||
CREATE POLICY "Artists can view their own ecosystem licenses" ON public.ethos_ecosystem_licenses
|
||||
FOR SELECT USING (auth.uid() = artist_id);
|
||||
|
||||
CREATE POLICY "Admins can view all ecosystem licenses" ON public.ethos_ecosystem_licenses
|
||||
DROP POLICY IF EXISTS "Admins can view all ecosystem licenses" ON public.ethos_ecosystem_licenses;
|
||||
CREATE POLICY "Admins can view all ecosystem licenses" ON public.ethos_ecosystem_licenses
|
||||
FOR SELECT USING (
|
||||
EXISTS(
|
||||
|
|
@ -55,6 +59,8 @@ CREATE POLICY "Admins can view all ecosystem licenses" ON public.ethos_ecosystem
|
|||
)
|
||||
);
|
||||
|
||||
CREATE POLICY "Artists can create ecosystem license records" ON public.ethos_ecosystem_licenses
|
||||
DROP POLICY IF EXISTS "Artists can create ecosystem license records" ON public.ethos_ecosystem_licenses;
|
||||
CREATE POLICY "Artists can create ecosystem license records" ON public.ethos_ecosystem_licenses
|
||||
FOR INSERT WITH CHECK (auth.uid() = artist_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -211,13 +211,19 @@ alter table public.foundation_mentorship_sessions enable row level security;
|
|||
alter table public.foundation_contributions enable row level security;
|
||||
|
||||
-- Courses: Published courses readable by all, all ops by instructor/admin
|
||||
create policy "Published courses readable by all" on public.foundation_courses
|
||||
drop policy if exists "Published courses readable by all" on public.foundation_courses;
|
||||
create policy "Published courses readable by all" on public.foundation_courses
|
||||
for select using (is_published = true or auth.uid() = instructor_id or exists(select 1 from public.user_profiles where id = auth.uid() and user_type = 'admin'));
|
||||
|
||||
create policy "Instructors manage own courses" on public.foundation_courses
|
||||
drop policy if exists "Instructors manage own courses" on public.foundation_courses;
|
||||
create policy "Instructors manage own courses" on public.foundation_courses
|
||||
for all using (auth.uid() = instructor_id) with check (auth.uid() = instructor_id);
|
||||
|
||||
-- Course modules: same as courses (published visible, instructor/admin manage)
|
||||
create policy "Published modules readable by all" on public.foundation_course_modules
|
||||
drop policy if exists "Published modules readable by all" on public.foundation_course_modules;
|
||||
create policy "Published modules readable by all" on public.foundation_course_modules
|
||||
for select using (
|
||||
is_published = true or
|
||||
|
|
@ -225,10 +231,14 @@ create policy "Published modules readable by all" on public.foundation_course_mo
|
|||
exists(select 1 from public.user_profiles where id = auth.uid() and user_type = 'admin')
|
||||
);
|
||||
|
||||
create policy "Instructors manage course modules" on public.foundation_course_modules
|
||||
drop policy if exists "Instructors manage course modules" on public.foundation_course_modules;
|
||||
create policy "Instructors manage course modules" on public.foundation_course_modules
|
||||
for all using (exists(select 1 from public.foundation_courses where id = course_id and instructor_id = auth.uid()));
|
||||
|
||||
-- Lessons: same pattern
|
||||
create policy "Published lessons readable by all" on public.foundation_course_lessons
|
||||
drop policy if exists "Published lessons readable by all" on public.foundation_course_lessons;
|
||||
create policy "Published lessons readable by all" on public.foundation_course_lessons
|
||||
for select using (
|
||||
is_published = true or
|
||||
|
|
@ -236,69 +246,107 @@ create policy "Published lessons readable by all" on public.foundation_course_le
|
|||
exists(select 1 from public.user_profiles where id = auth.uid() and user_type = 'admin')
|
||||
);
|
||||
|
||||
create policy "Instructors manage course lessons" on public.foundation_course_lessons
|
||||
drop policy if exists "Instructors manage course lessons" on public.foundation_course_lessons;
|
||||
create policy "Instructors manage course lessons" on public.foundation_course_lessons
|
||||
for all using (exists(select 1 from public.foundation_courses where id = course_id and instructor_id = auth.uid()));
|
||||
|
||||
-- Enrollments: users see own, instructors see their course enrollments
|
||||
create policy "Users see own enrollments" on public.foundation_enrollments
|
||||
drop policy if exists "Users see own enrollments" on public.foundation_enrollments;
|
||||
create policy "Users see own enrollments" on public.foundation_enrollments
|
||||
for select using (auth.uid() = user_id or
|
||||
exists(select 1 from public.foundation_courses where id = course_id and instructor_id = auth.uid()));
|
||||
|
||||
create policy "Users manage own enrollments" on public.foundation_enrollments
|
||||
drop policy if exists "Users manage own enrollments" on public.foundation_enrollments;
|
||||
create policy "Users manage own enrollments" on public.foundation_enrollments
|
||||
for insert with check (auth.uid() = user_id);
|
||||
|
||||
create policy "Users update own enrollments" on public.foundation_enrollments
|
||||
drop policy if exists "Users update own enrollments" on public.foundation_enrollments;
|
||||
create policy "Users update own enrollments" on public.foundation_enrollments
|
||||
for update using (auth.uid() = user_id);
|
||||
|
||||
-- Lesson progress: users see own
|
||||
create policy "Users see own lesson progress" on public.foundation_lesson_progress
|
||||
drop policy if exists "Users see own lesson progress" on public.foundation_lesson_progress;
|
||||
create policy "Users see own lesson progress" on public.foundation_lesson_progress
|
||||
for select using (auth.uid() = user_id);
|
||||
|
||||
create policy "Users update own lesson progress" on public.foundation_lesson_progress
|
||||
drop policy if exists "Users update own lesson progress" on public.foundation_lesson_progress;
|
||||
create policy "Users update own lesson progress" on public.foundation_lesson_progress
|
||||
for insert with check (auth.uid() = user_id);
|
||||
|
||||
create policy "Users update own lesson completion" on public.foundation_lesson_progress
|
||||
drop policy if exists "Users update own lesson completion" on public.foundation_lesson_progress;
|
||||
create policy "Users update own lesson completion" on public.foundation_lesson_progress
|
||||
for update using (auth.uid() = user_id);
|
||||
|
||||
-- Achievements: all readable, admin/system manages
|
||||
create policy "Achievements readable by all" on public.foundation_achievements
|
||||
drop policy if exists "Achievements readable by all" on public.foundation_achievements;
|
||||
create policy "Achievements readable by all" on public.foundation_achievements
|
||||
for select using (true);
|
||||
|
||||
-- User achievements: users see own, admin manages
|
||||
create policy "Users see own achievements" on public.foundation_user_achievements
|
||||
drop policy if exists "Users see own achievements" on public.foundation_user_achievements;
|
||||
create policy "Users see own achievements" on public.foundation_user_achievements
|
||||
for select using (auth.uid() = user_id or exists(select 1 from public.user_profiles where id = auth.uid() and user_type = 'admin'));
|
||||
|
||||
-- Mentors: approved mentors visible, mentors manage own
|
||||
create policy "Approved mentors visible to all" on public.foundation_mentors
|
||||
drop policy if exists "Approved mentors visible to all" on public.foundation_mentors;
|
||||
create policy "Approved mentors visible to all" on public.foundation_mentors
|
||||
for select using (approval_status = 'approved' or auth.uid() = user_id or exists(select 1 from public.user_profiles where id = auth.uid() and user_type = 'admin'));
|
||||
|
||||
create policy "Users manage own mentor profile" on public.foundation_mentors
|
||||
drop policy if exists "Users manage own mentor profile" on public.foundation_mentors;
|
||||
create policy "Users manage own mentor profile" on public.foundation_mentors
|
||||
for all using (auth.uid() = user_id) with check (auth.uid() = user_id);
|
||||
|
||||
-- Mentorship requests: involved parties can see
|
||||
create policy "Mentorship requests visible to involved" on public.foundation_mentorship_requests
|
||||
drop policy if exists "Mentorship requests visible to involved" on public.foundation_mentorship_requests;
|
||||
create policy "Mentorship requests visible to involved" on public.foundation_mentorship_requests
|
||||
for select using (auth.uid() = mentor_id or auth.uid() = mentee_id or exists(select 1 from public.user_profiles where id = auth.uid() and user_type = 'admin'));
|
||||
|
||||
create policy "Mentees request mentorship" on public.foundation_mentorship_requests
|
||||
drop policy if exists "Mentees request mentorship" on public.foundation_mentorship_requests;
|
||||
create policy "Mentees request mentorship" on public.foundation_mentorship_requests
|
||||
for insert with check (auth.uid() = mentee_id);
|
||||
|
||||
create policy "Mentors respond to requests" on public.foundation_mentorship_requests
|
||||
drop policy if exists "Mentors respond to requests" on public.foundation_mentorship_requests;
|
||||
create policy "Mentors respond to requests" on public.foundation_mentorship_requests
|
||||
for update using (auth.uid() = mentor_id);
|
||||
|
||||
-- Mentorship sessions: involved parties can see/manage
|
||||
create policy "Sessions visible to involved" on public.foundation_mentorship_sessions
|
||||
drop policy if exists "Sessions visible to involved" on public.foundation_mentorship_sessions;
|
||||
create policy "Sessions visible to involved" on public.foundation_mentorship_sessions
|
||||
for select using (auth.uid() = mentor_id or auth.uid() = mentee_id);
|
||||
|
||||
create policy "Mentorship sessions insert" on public.foundation_mentorship_sessions
|
||||
drop policy if exists "Mentorship sessions insert" on public.foundation_mentorship_sessions;
|
||||
create policy "Mentorship sessions insert" on public.foundation_mentorship_sessions
|
||||
for insert with check (auth.uid() = mentor_id or auth.uid() = mentee_id);
|
||||
|
||||
create policy "Mentorship sessions update" on public.foundation_mentorship_sessions
|
||||
drop policy if exists "Mentorship sessions update" on public.foundation_mentorship_sessions;
|
||||
create policy "Mentorship sessions update" on public.foundation_mentorship_sessions
|
||||
for update using (auth.uid() = mentor_id or auth.uid() = mentee_id);
|
||||
|
||||
-- Contributions: users see own, admin sees all
|
||||
create policy "Contributions visible to user and admin" on public.foundation_contributions
|
||||
drop policy if exists "Contributions visible to user and admin" on public.foundation_contributions;
|
||||
create policy "Contributions visible to user and admin" on public.foundation_contributions
|
||||
for select using (auth.uid() = user_id or exists(select 1 from public.user_profiles where id = auth.uid() and user_type = 'admin'));
|
||||
|
||||
create policy "System logs contributions" on public.foundation_contributions
|
||||
drop policy if exists "System logs contributions" on public.foundation_contributions;
|
||||
create policy "System logs contributions" on public.foundation_contributions
|
||||
for insert with check (true);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,14 +6,14 @@ alter table if exists storage.objects enable row level security;
|
|||
|
||||
-- Allow public read for objects in post_media bucket (because bucket is public)
|
||||
DO $$ BEGIN
|
||||
CREATE POLICY IF NOT EXISTS post_media_public_read ON storage.objects
|
||||
CREATE POLICY post_media_public_read ON storage.objects
|
||||
FOR SELECT TO public
|
||||
USING (bucket_id = 'post_media');
|
||||
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||
|
||||
-- Allow authenticated users to upload to post_media bucket
|
||||
DO $$ BEGIN
|
||||
CREATE POLICY IF NOT EXISTS post_media_auth_insert ON storage.objects
|
||||
CREATE POLICY post_media_auth_insert ON storage.objects
|
||||
FOR INSERT TO authenticated
|
||||
WITH CHECK (bucket_id = 'post_media');
|
||||
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||
|
|
|
|||
|
|
@ -158,15 +158,15 @@ ALTER TABLE api_keys ENABLE ROW LEVEL SECURITY;
|
|||
ALTER TABLE api_usage_logs ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE developer_profiles ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- Users can only see their own API keys
|
||||
DROP POLICY IF EXISTS api_keys_user_policy ON api_keys;
|
||||
CREATE POLICY api_keys_user_policy ON api_keys
|
||||
FOR ALL USING (auth.uid() = user_id);
|
||||
|
||||
-- Users can only see their own usage logs
|
||||
DROP POLICY IF EXISTS api_usage_logs_user_policy ON api_usage_logs;
|
||||
CREATE POLICY api_usage_logs_user_policy ON api_usage_logs
|
||||
FOR ALL USING (auth.uid() = user_id);
|
||||
|
||||
-- Users can only see their own developer profile
|
||||
DROP POLICY IF EXISTS developer_profiles_user_policy ON developer_profiles;
|
||||
CREATE POLICY developer_profiles_user_policy ON developer_profiles
|
||||
FOR ALL USING (auth.uid() = user_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
-- Update OAuth client redirect URIs to include localhost:8080 for local dev
|
||||
-- This enables Foundation login to work in both production and development
|
||||
|
||||
UPDATE public.oauth_clients
|
||||
SET redirect_uris = '["https://aethex.dev/auth/callback", "http://localhost:8080/auth/callback", "http://localhost:3000/auth/callback", "http://localhost:5173/auth/callback"]'::jsonb,
|
||||
updated_at = NOW()
|
||||
WHERE client_id = 'aethex_corp';
|
||||