Apply Composer changes: comprehensive API updates, migrations, middleware, and infrastructure improvements

- Add comprehensive database migrations (001-024) for schema evolution
- Enhance API schema with expanded type definitions and resolvers
- Add new middleware: audit logging, rate limiting, MFA enforcement, security, tenant auth
- Implement new services: AI optimization, billing, blockchain, compliance, marketplace
- Add adapter layer for cloud integrations (Cloudflare, Kubernetes, Proxmox, storage)
- Update Crossplane provider with enhanced VM management capabilities
- Add comprehensive test suite for API endpoints and services
- Update frontend components with improved GraphQL subscriptions and real-time updates
- Enhance security configurations and headers (CSP, CORS, etc.)
- Update documentation and configuration files
- Add new CI/CD workflows and validation scripts
- Implement design system improvements and UI enhancements
This commit is contained in:
defiQUG
2025-12-12 18:01:35 -08:00
parent e01131efaf
commit 9daf1fd378
968 changed files with 160890 additions and 1092 deletions

View File

@@ -9,7 +9,7 @@ export default function AboutPage() {
<header className="border-b border-studio-medium bg-studio-dark">
<div className="mx-auto flex max-w-7xl items-center justify-between px-4 py-4">
<Link href="/" className="text-2xl font-bold text-white">
Phoenix <span className="text-phoenix-fire">Sankofa</span> Cloud
<span className="text-sankofa-gold">Sankofa's</span> Phoenix <span className="text-phoenix-fire">Nexus</span> Cloud
</Link>
<nav className="flex gap-4">
<Link href="/" className="text-gray-400 hover:text-white">

View File

@@ -0,0 +1,74 @@
import { NextRequest, NextResponse } from 'next/server'
import { cookies } from 'next/headers'
/**
* API route for managing authentication tokens via httpOnly cookies
*/
const COOKIE_NAME = 'auth_token'
const MAX_AGE = 60 * 60 * 24 * 7 // 7 days
export async function POST(request: NextRequest) {
try {
const { token } = await request.json()
if (!token) {
return NextResponse.json(
{ error: 'Token is required' },
{ status: 400 }
)
}
const cookieStore = await cookies()
cookieStore.set(COOKIE_NAME, token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
maxAge: MAX_AGE,
path: '/',
})
return NextResponse.json({ success: true })
} catch (error) {
return NextResponse.json(
{ error: 'Failed to set token' },
{ status: 500 }
)
}
}
export async function GET() {
try {
const cookieStore = await cookies()
const token = cookieStore.get(COOKIE_NAME)?.value
if (!token) {
return NextResponse.json(
{ error: 'No token found' },
{ status: 404 }
)
}
return NextResponse.json({ token })
} catch (error) {
return NextResponse.json(
{ error: 'Failed to get token' },
{ status: 500 }
)
}
}
export async function DELETE() {
try {
const cookieStore = await cookies()
cookieStore.delete(COOKIE_NAME)
return NextResponse.json({ success: true })
} catch (error) {
return NextResponse.json(
{ error: 'Failed to delete token' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,86 @@
import { NextRequest, NextResponse } from 'next/server'
import * as fs from 'fs'
import * as path from 'path'
import * as zlib from 'zlib'
import { promisify } from 'util'
const gzip = promisify(zlib.gzip)
const DATA_DIR = path.join(process.cwd(), 'docs/infrastructure/data')
const BACKUP_DIR = path.join(process.cwd(), 'docs/infrastructure/backups')
export async function POST(request: NextRequest) {
try {
// Ensure backup directory exists
if (!fs.existsSync(BACKUP_DIR)) {
fs.mkdirSync(BACKUP_DIR, { recursive: true })
}
const timestamp = new Date().toISOString().replace(/[:.]/g, '-')
const backupFilename = `backup-${timestamp}.json.gz`
const backupPath = path.join(BACKUP_DIR, backupFilename)
// Read all data files
const files = fs.readdirSync(DATA_DIR).filter((f) => f.endsWith('.json'))
const backup: Record<string, any> = {}
for (const file of files) {
const filePath = path.join(DATA_DIR, file)
const content = fs.readFileSync(filePath, 'utf-8')
backup[file] = JSON.parse(content)
}
// Compress and save
const jsonData = JSON.stringify(backup, null, 2)
const compressed = await gzip(jsonData)
fs.writeFileSync(backupPath, compressed)
return NextResponse.json({
success: true,
filename: backupFilename,
timestamp: new Date().toISOString(),
files: files.length,
})
} catch (error) {
return NextResponse.json(
{
error: 'Failed to create backup',
message: error instanceof Error ? error.message : 'Unknown error',
},
{ status: 500 }
)
}
}
export async function GET() {
try {
if (!fs.existsSync(BACKUP_DIR)) {
return NextResponse.json({ backups: [] })
}
const files = fs
.readdirSync(BACKUP_DIR)
.filter((f) => f.endsWith('.json.gz'))
.map((f) => {
const filePath = path.join(BACKUP_DIR, f)
const stats = fs.statSync(filePath)
return {
filename: f,
size: stats.size,
created: stats.birthtime.toISOString(),
}
})
.sort((a, b) => new Date(b.created).getTime() - new Date(a.created).getTime())
return NextResponse.json({ backups: files })
} catch (error) {
return NextResponse.json(
{
error: 'Failed to list backups',
message: error instanceof Error ? error.message : 'Unknown error',
},
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,114 @@
import { NextRequest, NextResponse } from 'next/server'
import * as fs from 'fs'
import * as path from 'path'
/**
* API route for serving infrastructure data JSON files
*
* GET /api/infrastructure/data/[filename]
*
* Serves JSON files from docs/infrastructure/data/ with caching headers
*/
const DATA_DIR = path.join(process.cwd(), 'docs/infrastructure/data')
// Allowed file extensions
const ALLOWED_EXTENSIONS = ['.json']
// Security: Prevent directory traversal
function sanitizeFilename(filename: string): string {
// Remove any path separators and only allow alphanumeric, hyphens, underscores, and dots
const sanitized = filename.replace(/[^a-zA-Z0-9._-]/g, '')
// Ensure it has a valid extension
const ext = path.extname(sanitized)
if (!ALLOWED_EXTENSIONS.includes(ext)) {
throw new Error('Invalid file extension')
}
return sanitized
}
export async function GET(
request: NextRequest,
{ params }: { params: { filename: string } }
) {
try {
// Sanitize filename to prevent directory traversal
const filename = sanitizeFilename(params.filename)
const filePath = path.join(DATA_DIR, filename)
// Check if file exists
if (!fs.existsSync(filePath)) {
return NextResponse.json(
{ error: 'File not found' },
{ status: 404 }
)
}
// Read file content
const fileContent = fs.readFileSync(filePath, 'utf-8')
// Parse JSON to validate it's valid JSON
let data: unknown
try {
data = JSON.parse(fileContent)
} catch (parseError) {
return NextResponse.json(
{ error: 'Invalid JSON file' },
{ status: 500 }
)
}
// Get file stats for caching
const stats = fs.statSync(filePath)
// Create response
const response = NextResponse.json({
data,
metadata: {
filename,
lastModified: stats.mtime.toISOString(),
size: stats.size,
},
})
// Add caching headers
const etag = `"${stats.mtime.getTime()}-${stats.size}"`
response.headers.set('ETag', etag)
response.headers.set('Last-Modified', stats.mtime.toUTCString())
response.headers.set('Cache-Control', 'public, max-age=3600, stale-while-revalidate=86400')
response.headers.set('Content-Type', 'application/json')
// Check if client has cached version (304 Not Modified)
const ifNoneMatch = request.headers.get('if-none-match')
if (ifNoneMatch === etag) {
return new NextResponse(null, { status: 304 })
}
const ifModifiedSince = request.headers.get('if-modified-since')
if (ifModifiedSince) {
const ifModifiedSinceDate = new Date(ifModifiedSince)
if (stats.mtime <= ifModifiedSinceDate) {
return new NextResponse(null, { status: 304 })
}
}
return response
} catch (error) {
// Handle security errors
if (error instanceof Error && error.message === 'Invalid file extension') {
return NextResponse.json(
{ error: 'Invalid file type. Only JSON files are allowed.' },
{ status: 400 }
)
}
// Log error for debugging (in production, use proper logging)
console.error('Error serving infrastructure data:', error)
return NextResponse.json(
{ error: 'Failed to load file' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,67 @@
import { NextRequest, NextResponse } from 'next/server'
import * as fs from 'fs'
import * as path from 'path'
import * as XLSX from 'xlsx'
const DATA_DIR = path.join(process.cwd(), 'docs/infrastructure/data')
export async function POST(request: NextRequest) {
try {
const formData = await request.formData()
const file = formData.get('file') as File
const targetFile = formData.get('targetFile') as string
if (!file || !targetFile) {
return NextResponse.json(
{ error: 'File and targetFile are required' },
{ status: 400 }
)
}
const buffer = Buffer.from(await file.arrayBuffer())
const filePath = path.join(DATA_DIR, targetFile)
// Handle different file types
if (file.name.endsWith('.json')) {
const data = JSON.parse(buffer.toString())
fs.writeFileSync(filePath, JSON.stringify(data, null, 2))
} else if (file.name.endsWith('.xlsx') || file.name.endsWith('.xls')) {
const workbook = XLSX.read(buffer, { type: 'buffer' })
const sheetName = workbook.SheetNames[0]
const worksheet = workbook.Sheets[sheetName]
const data = XLSX.utils.sheet_to_json(worksheet)
fs.writeFileSync(filePath, JSON.stringify(data, null, 2))
} else if (file.name.endsWith('.csv')) {
const csv = buffer.toString()
const lines = csv.split('\n')
const headers = lines[0].split(',').map((h) => h.trim().replace(/^"|"$/g, ''))
const data = lines.slice(1).map((line) => {
const values = line.split(',').map((v) => v.trim().replace(/^"|"$/g, ''))
return headers.reduce((obj, header, idx) => {
obj[header] = values[idx] || ''
return obj
}, {} as Record<string, any>)
})
fs.writeFileSync(filePath, JSON.stringify(data, null, 2))
} else {
return NextResponse.json({ error: 'Unsupported file type' }, { status: 400 })
}
return NextResponse.json({
success: true,
filename: targetFile,
records: Array.isArray(JSON.parse(fs.readFileSync(filePath, 'utf-8')))
? JSON.parse(fs.readFileSync(filePath, 'utf-8')).length
: 1,
})
} catch (error) {
return NextResponse.json(
{
error: 'Failed to import file',
message: error instanceof Error ? error.message : 'Unknown error',
},
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,52 @@
import { NextRequest, NextResponse } from 'next/server'
import * as fs from 'fs'
import * as path from 'path'
import * as zlib from 'zlib'
import { promisify } from 'util'
const gunzip = promisify(zlib.gunzip)
const DATA_DIR = path.join(process.cwd(), 'docs/infrastructure/data')
const BACKUP_DIR = path.join(process.cwd(), 'docs/infrastructure/backups')
export async function POST(request: NextRequest) {
try {
const { filename } = await request.json()
if (!filename) {
return NextResponse.json({ error: 'Filename is required' }, { status: 400 })
}
const backupPath = path.join(BACKUP_DIR, filename)
if (!fs.existsSync(backupPath)) {
return NextResponse.json({ error: 'Backup file not found' }, { status: 404 })
}
// Read and decompress backup
const compressed = fs.readFileSync(backupPath)
const decompressed = await gunzip(compressed)
const backup = JSON.parse(decompressed.toString())
// Restore files
for (const [file, data] of Object.entries(backup)) {
const filePath = path.join(DATA_DIR, file)
fs.writeFileSync(filePath, JSON.stringify(data, null, 2))
}
return NextResponse.json({
success: true,
filesRestored: Object.keys(backup).length,
timestamp: new Date().toISOString(),
})
} catch (error) {
return NextResponse.json(
{
error: 'Failed to restore backup',
message: error instanceof Error ? error.message : 'Unknown error',
},
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,122 @@
import { PublicLayout } from '@/components/layout/public-layout'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Award, Book, CheckCircle, Clock } from 'lucide-react'
export default function CertificationPage() {
const certifications = [
{
id: 'phoenix-admin',
name: 'Phoenix Certified Administrator',
level: 'Associate',
duration: '3 months',
description: 'Learn to manage and operate Phoenix infrastructure',
skills: ['Infrastructure Management', 'Security', 'Monitoring'],
},
{
id: 'phoenix-architect',
name: 'Phoenix Certified Architect',
level: 'Professional',
duration: '6 months',
description: 'Design and architect solutions on Phoenix platform',
skills: ['Architecture Design', 'Best Practices', 'Scalability'],
},
{
id: 'phoenix-developer',
name: 'Phoenix Certified Developer',
level: 'Associate',
duration: '3 months',
description: 'Build applications using Phoenix APIs and services',
skills: ['API Development', 'SDKs', 'Integration'],
},
]
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black py-24 px-4">
<div className="mx-auto max-w-7xl">
<div className="mb-12 text-center">
<h1 className="mb-4 text-5xl font-bold text-white">Certification Program</h1>
<p className="text-xl text-gray-400">
Validate your expertise with Phoenix certifications
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-12">
{certifications.map((cert) => (
<Card key={cert.id} className="hover:border-phoenix-fire transition-colors">
<CardHeader>
<div className="flex items-center gap-3 mb-2">
<Award className="h-8 w-8 text-phoenix-fire" />
<span className="px-2 py-1 text-xs bg-studio-dark text-gray-400 rounded">
{cert.level}
</span>
</div>
<CardTitle className="text-white">{cert.name}</CardTitle>
<CardDescription className="text-gray-400">
{cert.description}
</CardDescription>
</CardHeader>
<CardContent>
<div className="mb-4">
<div className="flex items-center gap-2 text-sm text-gray-400 mb-2">
<Clock className="h-4 w-4" />
<span>{cert.duration}</span>
</div>
<div>
<p className="text-sm text-gray-300 mb-2">Skills covered:</p>
<ul className="space-y-1">
{cert.skills.map((skill) => (
<li key={skill} className="flex items-center gap-2 text-sm text-gray-400">
<CheckCircle className="h-4 w-4 text-green-400" />
<span>{skill}</span>
</li>
))}
</ul>
</div>
</div>
<Button variant="outline" className="w-full" asChild>
<Link href={`/certification/${cert.id}`}>Learn More</Link>
</Button>
</CardContent>
</Card>
))}
</div>
<Card className="bg-studio-dark border-studio-medium">
<CardHeader>
<CardTitle className="text-white">Why Get Certified?</CardTitle>
</CardHeader>
<CardContent>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<div>
<Award className="h-6 w-6 text-phoenix-fire mb-2" />
<h3 className="text-white font-semibold mb-2">Validate Skills</h3>
<p className="text-gray-400 text-sm">
Demonstrate your expertise to employers and clients
</p>
</div>
<div>
<Book className="h-6 w-6 text-sankofa-gold mb-2" />
<h3 className="text-white font-semibold mb-2">Career Growth</h3>
<p className="text-gray-400 text-sm">
Advance your career with recognized credentials
</p>
</div>
<div>
<CheckCircle className="h-6 w-6 text-neon-cyan mb-2" />
<h3 className="text-white font-semibold mb-2">Stay Current</h3>
<p className="text-gray-400 text-sm">
Keep up with latest Phoenix features and best practices
</p>
</div>
</div>
</CardContent>
</Card>
</div>
</div>
</PublicLayout>
)
}

171
src/app/community/page.tsx Normal file
View File

@@ -0,0 +1,171 @@
import { PublicLayout } from '@/components/layout/public-layout'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { MessageSquare, Users, TrendingUp, Clock } from 'lucide-react'
export default function CommunityForumPage() {
const categories = [
{
id: 'general',
name: 'General Discussion',
description: 'General questions and discussions',
posts: 1250,
latest: '2 hours ago',
},
{
id: 'support',
name: 'Support',
description: 'Get help with technical issues',
posts: 890,
latest: '1 hour ago',
},
{
id: 'announcements',
name: 'Announcements',
description: 'Product updates and news',
posts: 45,
latest: '1 day ago',
},
{
id: 'showcase',
name: 'Showcase',
description: 'Share your projects and solutions',
posts: 320,
latest: '3 hours ago',
},
]
const recentPosts = [
{
id: '1',
title: 'How to optimize costs on Phoenix?',
author: 'john_doe',
category: 'Support',
replies: 12,
views: 245,
time: '2 hours ago',
},
{
id: '2',
title: 'New feature: Cost forecasting',
author: 'sankofa_team',
category: 'Announcements',
replies: 8,
views: 189,
time: '5 hours ago',
},
{
id: '3',
title: 'Showcase: My Phoenix deployment',
author: 'dev_user',
category: 'Showcase',
replies: 15,
views: 312,
time: '1 day ago',
},
]
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black py-24 px-4">
<div className="mx-auto max-w-7xl">
<div className="mb-12">
<h1 className="mb-4 text-5xl font-bold text-white">Community Forum</h1>
<p className="text-xl text-gray-400">
Connect with other users, share knowledge, and get support
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-12">
{categories.map((category) => (
<Card key={category.id} className="hover:border-phoenix-fire transition-colors cursor-pointer">
<CardHeader>
<MessageSquare className="h-8 w-8 text-phoenix-fire mb-2" />
<CardTitle className="text-white">{category.name}</CardTitle>
<CardDescription className="text-gray-400">
{category.description}
</CardDescription>
</CardHeader>
<CardContent>
<div className="flex items-center justify-between text-sm text-gray-400">
<span>{category.posts} posts</span>
<span className="flex items-center gap-1">
<Clock className="h-4 w-4" />
{category.latest}
</span>
</div>
</CardContent>
</Card>
))}
</div>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
<div className="lg:col-span-2">
<Card className="bg-studio-dark border-studio-medium">
<CardHeader>
<CardTitle className="text-white">Recent Posts</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-4">
{recentPosts.map((post) => (
<div
key={post.id}
className="p-4 bg-studio-black rounded-lg hover:bg-studio-medium transition-colors cursor-pointer"
>
<div className="flex items-start justify-between mb-2">
<h3 className="text-white font-semibold">{post.title}</h3>
<span className="px-2 py-1 text-xs bg-studio-dark text-gray-400 rounded">
{post.category}
</span>
</div>
<div className="flex items-center gap-4 text-sm text-gray-400">
<span>by {post.author}</span>
<span>{post.replies} replies</span>
<span>{post.views} views</span>
<span>{post.time}</span>
</div>
</div>
))}
</div>
</CardContent>
</Card>
</div>
<div>
<Card className="bg-studio-dark border-studio-medium mb-6">
<CardHeader>
<CardTitle className="text-white flex items-center gap-2">
<Users className="h-5 w-5 text-phoenix-fire" />
Community Stats
</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-3">
<div className="flex justify-between">
<span className="text-gray-400">Members</span>
<span className="text-white font-semibold">12,450</span>
</div>
<div className="flex justify-between">
<span className="text-gray-400">Posts</span>
<span className="text-white font-semibold">2,505</span>
</div>
<div className="flex justify-between">
<span className="text-gray-400">Online</span>
<span className="text-white font-semibold">234</span>
</div>
</div>
</CardContent>
</Card>
<Button variant="phoenix" className="w-full" asChild>
<Link href="/community/new-post">Create New Post</Link>
</Button>
</div>
</div>
</div>
</div>
</PublicLayout>
)
}

View File

@@ -0,0 +1,63 @@
import { PublicLayout } from '@/components/layout/public-layout'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Accessibility, CheckCircle } from 'lucide-react'
export default function AccessibilityPage() {
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black py-24 px-4">
<div className="mx-auto max-w-4xl">
<h1 className="mb-8 text-4xl font-bold text-white">Accessibility</h1>
<div className="space-y-8">
<Card>
<CardHeader>
<div className="flex items-center gap-3">
<Accessibility className="h-8 w-8 text-phoenix-fire" />
<CardTitle className="text-white">Accessibility Commitment</CardTitle>
</div>
</CardHeader>
<CardContent>
<p className="text-gray-300 mb-4">
Sankofa Phoenix is committed to making our platform accessible to all users.
We follow WCAG 2.1 Level AA guidelines and continuously work to improve accessibility.
</p>
<ul className="space-y-2 text-gray-300">
<li className="flex items-start gap-2">
<CheckCircle className="h-5 w-5 text-green-400 mt-0.5" />
<span>WCAG 2.1 Level AA compliant</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="h-5 w-5 text-green-400 mt-0.5" />
<span>Keyboard navigation support</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="h-5 w-5 text-green-400 mt-0.5" />
<span>Screen reader compatible</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="h-5 w-5 text-green-400 mt-0.5" />
<span>High contrast mode support</span>
</li>
</ul>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-white">Feedback</CardTitle>
</CardHeader>
<CardContent>
<p className="text-gray-300 mb-4">
We welcome feedback on accessibility. If you encounter any accessibility issues,
please contact our support team.
</p>
</CardContent>
</Card>
</div>
</div>
</div>
</PublicLayout>
)
}

View File

@@ -0,0 +1,67 @@
import { PublicLayout } from '@/components/layout/public-layout'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Shield, CheckCircle } from 'lucide-react'
export default function CompliancePage() {
const complianceFrameworks = [
{ name: 'SOC 2 Type II', status: 'Certified', description: 'Security, availability, and confidentiality controls' },
{ name: 'ISO 27001', status: 'Certified', description: 'Information security management system' },
{ name: 'GDPR', status: 'Compliant', description: 'European data protection regulation' },
{ name: 'HIPAA', status: 'Ready', description: 'Healthcare data protection (when applicable)' },
{ name: 'PCI-DSS', status: 'Compliant', description: 'Payment card industry data security' },
]
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black py-24 px-4">
<div className="mx-auto max-w-4xl">
<h1 className="mb-8 text-4xl font-bold text-white">Compliance</h1>
<div className="space-y-6">
<Card>
<CardHeader>
<div className="flex items-center gap-3">
<Shield className="h-8 w-8 text-phoenix-fire" />
<CardTitle className="text-white">Regulatory Compliance</CardTitle>
</div>
</CardHeader>
<CardContent>
<p className="text-gray-300 mb-6">
Sankofa Phoenix maintains compliance with major regulatory frameworks and industry
standards to meet enterprise and government requirements.
</p>
<div className="space-y-4">
{complianceFrameworks.map((framework) => (
<div key={framework.name} className="p-4 bg-studio-dark rounded-lg">
<div className="flex items-center justify-between mb-2">
<h3 className="text-lg font-semibold text-white">{framework.name}</h3>
<span className="px-3 py-1 bg-green-500/20 text-green-400 text-xs font-semibold rounded-full">
{framework.status}
</span>
</div>
<p className="text-sm text-gray-400">{framework.description}</p>
</div>
))}
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-white">Compliance Certifications</CardTitle>
</CardHeader>
<CardContent>
<p className="text-gray-300 mb-4">
We undergo regular audits and assessments to maintain our compliance certifications.
Certificates and audit reports are available upon request for enterprise customers.
</p>
</CardContent>
</Card>
</div>
</div>
</div>
</PublicLayout>
)
}

View File

@@ -0,0 +1,80 @@
import { PublicLayout } from '@/components/layout/public-layout'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Lock, Eye, FileText, CheckCircle } from 'lucide-react'
export default function PrivacyPage() {
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black py-24 px-4">
<div className="mx-auto max-w-4xl">
<h1 className="mb-8 text-4xl font-bold text-white">Privacy</h1>
<div className="space-y-8">
<Card>
<CardHeader>
<div className="flex items-center gap-3">
<Lock className="h-8 w-8 text-phoenix-fire" />
<CardTitle className="text-white">Data Privacy & Sovereignty</CardTitle>
</div>
</CardHeader>
<CardContent>
<p className="text-gray-300 mb-4">
Sankofa Phoenix is committed to protecting your privacy and ensuring data sovereignty.
We implement privacy by design principles and comply with global privacy regulations.
</p>
<ul className="space-y-2 text-gray-300">
<li className="flex items-start gap-2">
<CheckCircle className="h-5 w-5 text-green-400 mt-0.5" />
<span>GDPR compliant</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="h-5 w-5 text-green-400 mt-0.5" />
<span>Data residency controls</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="h-5 w-5 text-green-400 mt-0.5" />
<span>Right to deletion</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="h-5 w-5 text-green-400 mt-0.5" />
<span>Privacy by design</span>
</li>
</ul>
</CardContent>
</Card>
<Card>
<CardHeader>
<div className="flex items-center gap-3">
<Eye className="h-8 w-8 text-sankofa-gold" />
<CardTitle className="text-white">Transparency</CardTitle>
</div>
</CardHeader>
<CardContent>
<p className="text-gray-300 mb-4">
We are transparent about how we collect, use, and protect your data. Our privacy
policy clearly outlines our data handling practices.
</p>
</CardContent>
</Card>
<Card>
<CardHeader>
<div className="flex items-center gap-3">
<FileText className="h-8 w-8 text-neon-cyan" />
<CardTitle className="text-white">Privacy Policy</CardTitle>
</div>
</CardHeader>
<CardContent>
<p className="text-gray-300 mb-4">
For detailed information about our privacy practices, please review our Privacy Policy.
</p>
</CardContent>
</Card>
</div>
</div>
</div>
</PublicLayout>
)
}

View File

@@ -0,0 +1,82 @@
import { PublicLayout } from '@/components/layout/public-layout'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Shield, Lock, Eye, CheckCircle } from 'lucide-react'
export default function SecurityPage() {
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black py-24 px-4">
<div className="mx-auto max-w-4xl">
<h1 className="mb-8 text-4xl font-bold text-white">Security</h1>
<div className="space-y-8">
<Card>
<CardHeader>
<div className="flex items-center gap-3">
<Shield className="h-8 w-8 text-phoenix-fire" />
<CardTitle className="text-white">Enterprise-Grade Security</CardTitle>
</div>
</CardHeader>
<CardContent>
<p className="text-gray-300 mb-4">
Sankofa Phoenix is built with security as a foundational principle. Our infrastructure
implements defense-in-depth strategies, zero-trust networking, and comprehensive
security monitoring.
</p>
<ul className="space-y-2 text-gray-300">
<li className="flex items-start gap-2">
<CheckCircle className="h-5 w-5 text-green-400 mt-0.5" />
<span>SOC 2 Type II certified</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="h-5 w-5 text-green-400 mt-0.5" />
<span>ISO 27001 compliant</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="h-5 w-5 text-green-400 mt-0.5" />
<span>Zero Trust architecture</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="h-5 w-5 text-green-400 mt-0.5" />
<span>End-to-end encryption</span>
</li>
</ul>
</CardContent>
</Card>
<Card>
<CardHeader>
<div className="flex items-center gap-3">
<Lock className="h-8 w-8 text-sankofa-gold" />
<CardTitle className="text-white">Data Protection</CardTitle>
</div>
</CardHeader>
<CardContent>
<p className="text-gray-300 mb-4">
All data is encrypted at rest and in transit using industry-standard encryption
algorithms. We implement comprehensive access controls and audit logging.
</p>
</CardContent>
</Card>
<Card>
<CardHeader>
<div className="flex items-center gap-3">
<Eye className="h-8 w-8 text-neon-cyan" />
<CardTitle className="text-white">Security Monitoring</CardTitle>
</div>
</CardHeader>
<CardContent>
<p className="text-gray-300 mb-4">
Continuous security monitoring, threat detection, and incident response capabilities
ensure rapid detection and mitigation of security threats.
</p>
</CardContent>
</Card>
</div>
</div>
</div>
</PublicLayout>
)
}

View File

@@ -0,0 +1,156 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Header } from '@/components/layout/header'
import { Shield, Lock, FileCheck, Globe, CheckCircle } from 'lucide-react'
export default function TrustPage() {
return (
<>
<Header />
<main className="min-h-screen bg-studio-black">
{/* Hero */}
<section className="relative border-b border-studio-medium bg-gradient-to-br from-phoenix-fire/10 via-transparent to-sankofa-gold/10 py-24 px-4">
<div className="mx-auto max-w-4xl text-center">
<h1 className="mb-6 text-5xl font-bold text-white md:text-6xl">
Trust & Compliance
</h1>
<p className="mb-8 text-xl text-gray-300">
Enterprise-grade security, compliance, and data sovereignty
</p>
</div>
</section>
{/* Compliance Standards */}
<section className="py-24 px-4">
<div className="mx-auto max-w-6xl">
<h2 className="mb-12 text-center text-4xl font-bold text-white">
Compliance & Certifications
</h2>
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
<Card>
<CardHeader>
<Shield className="mb-2 h-10 w-10 text-phoenix-fire" />
<CardTitle>DoD/MilSpec Compliance</CardTitle>
</CardHeader>
<CardContent>
<p className="text-sm text-gray-300 mb-4">
STIG-compliant infrastructure with security hardening and audit controls.
</p>
<ul className="space-y-2 text-sm text-gray-400">
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-4 w-4 flex-shrink-0 text-phoenix-fire" />
<span>Security Technical Implementation Guides (STIG)</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-4 w-4 flex-shrink-0 text-phoenix-fire" />
<span>RMF authorization ready</span>
</li>
</ul>
</CardContent>
</Card>
<Card>
<CardHeader>
<Lock className="mb-2 h-10 w-10 text-sankofa-gold" />
<CardTitle>Data Sovereignty</CardTitle>
</CardHeader>
<CardContent>
<p className="text-sm text-gray-300 mb-4">
Complete control over data location, access, and governance.
</p>
<ul className="space-y-2 text-sm text-gray-400">
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-4 w-4 flex-shrink-0 text-sankofa-gold" />
<span>Regional data residency controls</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-4 w-4 flex-shrink-0 text-sankofa-gold" />
<span>No vendor lock-in</span>
</li>
</ul>
</CardContent>
</Card>
<Card>
<CardHeader>
<FileCheck className="mb-2 h-10 w-10 text-neon-cyan" />
<CardTitle>Audit & Reporting</CardTitle>
</CardHeader>
<CardContent>
<p className="text-sm text-gray-300 mb-4">
Comprehensive audit logging and compliance reporting.
</p>
<ul className="space-y-2 text-sm text-gray-400">
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-4 w-4 flex-shrink-0 text-neon-cyan" />
<span>Immutable audit logs</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-4 w-4 flex-shrink-0 text-neon-cyan" />
<span>Compliance dashboards</span>
</li>
</ul>
</CardContent>
</Card>
</div>
</div>
</section>
{/* Security Features */}
<section className="border-t border-studio-medium bg-studio-dark py-24 px-4">
<div className="mx-auto max-w-6xl">
<h2 className="mb-12 text-center text-4xl font-bold text-white">
Security Features
</h2>
<div className="grid gap-8 md:grid-cols-2">
<div>
<h3 className="mb-4 text-2xl font-bold text-white">Sovereign Identity</h3>
<p className="mb-4 text-gray-300">
Keycloak-based identity management with zero Azure dependencies.
Complete control over authentication, authorization, and user management.
</p>
<ul className="space-y-2 text-sm text-gray-400">
<li> Multi-factor authentication (MFA)</li>
<li> SSO integration (SAML, OIDC)</li>
<li> Role-based access control (RBAC)</li>
<li> Identity federation</li>
</ul>
</div>
<div>
<h3 className="mb-4 text-2xl font-bold text-white">Zero Trust Architecture</h3>
<p className="mb-4 text-gray-300">
Every request is verified, every connection is encrypted, and access is
granted on a least-privilege basis.
</p>
<ul className="space-y-2 text-sm text-gray-400">
<li> Network segmentation</li>
<li> End-to-end encryption</li>
<li> Continuous verification</li>
<li> Threat detection and response</li>
</ul>
</div>
</div>
</div>
</section>
{/* CTA */}
<section className="py-24 px-4">
<div className="mx-auto max-w-4xl text-center">
<h2 className="mb-6 text-4xl font-bold text-white">
Questions About Compliance?
</h2>
<p className="mb-8 text-xl text-gray-400">
Contact our compliance team for detailed information
</p>
<Button variant="phoenix" size="lg" asChild>
<Link href="/support">Contact Support</Link>
</Button>
</div>
</section>
</main>
</>
)
}

View File

@@ -0,0 +1,249 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Header } from '@/components/layout/header'
import { Code, Book, Terminal, ExternalLink } from 'lucide-react'
export default function GraphQLAPIPage() {
return (
<>
<Header />
<main className="min-h-screen bg-studio-black">
<div className="container mx-auto py-12 px-4 max-w-6xl">
<div className="mb-8">
<h1 className="text-4xl font-bold text-white mb-4">GraphQL API Reference</h1>
<p className="text-xl text-gray-300">
Complete reference for the Phoenix Nexus GraphQL API
</p>
</div>
{/* Quick Start */}
<Card className="mb-8 border-phoenix-fire/50">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Terminal className="h-5 w-5 text-phoenix-fire" />
Quick Start
</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div>
<h3 className="text-sm font-semibold text-gray-400 mb-2">Endpoint</h3>
<code className="block rounded bg-studio-dark px-4 py-2 font-mono text-sm text-white">
https://api.sankofa.nexus/graphql
</code>
</div>
<div>
<h3 className="text-sm font-semibold text-gray-400 mb-2">Authentication</h3>
<code className="block rounded bg-studio-dark px-4 py-2 font-mono text-sm text-white">
Authorization: Bearer {'<token>'}
</code>
</div>
<Button variant="outline" asChild>
<Link href="/portal/developers">
Get API Key <ExternalLink className="ml-2 h-4 w-4" />
</Link>
</Button>
</div>
</CardContent>
</Card>
{/* Queries */}
<section className="mb-12">
<h2 className="text-3xl font-bold text-white mb-6">Queries</h2>
<div className="space-y-6">
<Card>
<CardHeader>
<CardTitle className="text-lg">Get Resources</CardTitle>
<CardDescription>Retrieve a list of resources</CardDescription>
</CardHeader>
<CardContent>
<pre className="rounded bg-studio-dark p-4 text-sm text-white overflow-x-auto">
{`query GetResources($filter: ResourceFilter) {
resources(filter: $filter) {
id
name
type
status
site {
id
name
}
}
}`}
</pre>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-lg">Get Current User</CardTitle>
<CardDescription>Get authenticated user information</CardDescription>
</CardHeader>
<CardContent>
<pre className="rounded bg-studio-dark p-4 text-sm text-white overflow-x-auto">
{`query GetMe {
me {
id
email
name
role
tenant {
id
name
}
}
}`}
</pre>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-lg">Get Tenants</CardTitle>
<CardDescription>List all tenants (admin only)</CardDescription>
</CardHeader>
<CardContent>
<pre className="rounded bg-studio-dark p-4 text-sm text-white overflow-x-auto">
{`query GetTenants {
tenants {
id
name
status
createdAt
quotas {
compute
storage
network
}
}
}`}
</pre>
</CardContent>
</Card>
</div>
</section>
{/* Mutations */}
<section className="mb-12">
<h2 className="text-3xl font-bold text-white mb-6">Mutations</h2>
<div className="space-y-6">
<Card>
<CardHeader>
<CardTitle className="text-lg">Create Resource</CardTitle>
<CardDescription>Create a new resource</CardDescription>
</CardHeader>
<CardContent>
<pre className="rounded bg-studio-dark p-4 text-sm text-white overflow-x-auto">
{`mutation CreateResource($input: CreateResourceInput!) {
createResource(input: $input) {
id
name
type
status
}
}`}
</pre>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-lg">Create Tenant</CardTitle>
<CardDescription>Create a new tenant (admin only)</CardDescription>
</CardHeader>
<CardContent>
<pre className="rounded bg-studio-dark p-4 text-sm text-white overflow-x-auto">
{`mutation CreateTenant($input: CreateTenantInput!) {
createTenant(input: $input) {
id
name
status
}
}`}
</pre>
</CardContent>
</Card>
</div>
</section>
{/* Types */}
<section className="mb-12">
<h2 className="text-3xl font-bold text-white mb-6">Types</h2>
<div className="space-y-6">
<Card>
<CardHeader>
<CardTitle className="text-lg">Resource</CardTitle>
</CardHeader>
<CardContent>
<pre className="rounded bg-studio-dark p-4 text-sm text-white overflow-x-auto">
{`type Resource {
id: ID!
name: String!
type: ResourceType!
status: ResourceStatus!
site: Site
tenant: Tenant
createdAt: DateTime!
updatedAt: DateTime!
}`}
</pre>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-lg">Tenant</CardTitle>
</CardHeader>
<CardContent>
<pre className="rounded bg-studio-dark p-4 text-sm text-white overflow-x-auto">
{`type Tenant {
id: ID!
name: String!
status: TenantStatus!
quotas: TenantQuotas!
usage: TenantQuotaUsage!
createdAt: DateTime!
updatedAt: DateTime!
}`}
</pre>
</CardContent>
</Card>
</div>
</section>
{/* Interactive Explorer */}
<Card className="mb-8 border-sankofa-gold/50">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Code className="h-5 w-5 text-sankofa-gold" />
Interactive API Explorer
</CardTitle>
<CardDescription>
Try queries and mutations in the interactive GraphQL playground
</CardDescription>
</CardHeader>
<CardContent>
<Button variant="outline" asChild>
<Link href="/portal/developers/explorer">
Open API Explorer <ExternalLink className="ml-2 h-4 w-4" />
</Link>
</Button>
</CardContent>
</Card>
{/* Related Links */}
<div className="flex gap-4">
<Button variant="outline" asChild>
<Link href="/developers/docs/api/rest">REST API Reference </Link>
</Button>
<Button variant="outline" asChild>
<Link href="/developers/docs/guides/authentication">Authentication Guide </Link>
</Button>
</div>
</div>
</main>
</>
)
}

View File

@@ -0,0 +1,125 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Header } from '@/components/layout/header'
import { Code, Book, Terminal, ExternalLink } from 'lucide-react'
export default function RESTAPIPage() {
return (
<>
<Header />
<main className="min-h-screen bg-studio-black">
<div className="container mx-auto py-12 px-4 max-w-6xl">
<div className="mb-8">
<h1 className="text-4xl font-bold text-white mb-4">REST API Reference</h1>
<p className="text-xl text-gray-300">
Complete reference for the Phoenix Nexus REST API
</p>
</div>
{/* Quick Start */}
<Card className="mb-8 border-phoenix-fire/50">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Terminal className="h-5 w-5 text-phoenix-fire" />
Quick Start
</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div>
<h3 className="text-sm font-semibold text-gray-400 mb-2">Base URL</h3>
<code className="block rounded bg-studio-dark px-4 py-2 font-mono text-sm text-white">
https://api.sankofa.nexus/v1
</code>
</div>
<div>
<h3 className="text-sm font-semibold text-gray-400 mb-2">Authentication</h3>
<code className="block rounded bg-studio-dark px-4 py-2 font-mono text-sm text-white">
Authorization: Bearer {'<token>'}
</code>
</div>
<Button variant="outline" asChild>
<Link href="/portal/developers">
Get API Key <ExternalLink className="ml-2 h-4 w-4" />
</Link>
</Button>
</div>
</CardContent>
</Card>
{/* Endpoints */}
<section className="mb-12">
<h2 className="text-3xl font-bold text-white mb-6">Endpoints</h2>
<div className="space-y-6">
<Card>
<CardHeader>
<CardTitle className="text-lg">Get Resources</CardTitle>
<CardDescription>GET /v1/resources</CardDescription>
</CardHeader>
<CardContent>
<pre className="rounded bg-studio-dark p-4 text-sm text-white overflow-x-auto">
{`GET /v1/resources
Authorization: Bearer <token>
Response:
{
"data": [
{
"id": "uuid",
"name": "string",
"type": "VM|CONTAINER|STORAGE|NETWORK",
"status": "RUNNING|STOPPED|...",
"createdAt": "2024-01-01T00:00:00Z"
}
]
}`}
</pre>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-lg">Create Resource</CardTitle>
<CardDescription>POST /v1/resources</CardDescription>
</CardHeader>
<CardContent>
<pre className="rounded bg-studio-dark p-4 text-sm text-white overflow-x-auto">
{`POST /v1/resources
Authorization: Bearer <token>
Content-Type: application/json
{
"name": "My Resource",
"type": "VM",
"siteId": "uuid"
}
Response:
{
"id": "uuid",
"name": "My Resource",
"status": "PROVISIONING",
...
}`}
</pre>
</CardContent>
</Card>
</div>
</section>
{/* Related Links */}
<div className="flex gap-4">
<Button variant="outline" asChild>
<Link href="/developers/docs/api/graphql">GraphQL API Reference </Link>
</Button>
<Button variant="outline" asChild>
<Link href="/developers/docs/guides/authentication">Authentication Guide </Link>
</Button>
</div>
</div>
</main>
</>
)
}

View File

@@ -0,0 +1,130 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Header } from '@/components/layout/header'
import { Shield, Key, Lock } from 'lucide-react'
export default function AuthenticationGuidePage() {
return (
<>
<Header />
<main className="min-h-screen bg-studio-black">
<div className="container mx-auto py-12 px-4 max-w-4xl">
<div className="mb-12 text-center">
<div className="mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-phoenix-fire/20">
<Shield className="h-8 w-8 text-phoenix-fire" />
</div>
<h1 className="text-5xl font-bold text-white mb-4">Authentication Guide</h1>
<p className="text-xl text-gray-300">
Learn how to authenticate with Phoenix Nexus APIs
</p>
</div>
{/* API Keys */}
<Card className="mb-8">
<CardHeader>
<div className="flex items-center gap-3">
<Key className="h-6 w-6 text-sankofa-gold" />
<div>
<CardTitle>API Key Authentication</CardTitle>
<CardDescription>Simple and secure API key-based authentication</CardDescription>
</div>
</div>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div>
<h3 className="font-semibold text-white mb-2">1. Create an API Key</h3>
<p className="text-gray-300 mb-4">
Navigate to the Developer Portal and create a new API key.
</p>
<Button variant="outline" asChild>
<Link href="/portal/developers/keys">Create API Key </Link>
</Button>
</div>
<div>
<h3 className="font-semibold text-white mb-2">2. Use the API Key</h3>
<p className="text-gray-300 mb-2">Include the API key in the Authorization header:</p>
<pre className="rounded bg-studio-dark p-4 text-sm text-white overflow-x-auto">
{`curl -X GET https://api.sankofa.nexus/graphql \\
-H "Authorization: Bearer sk_live_your_key_here" \\
-H "Content-Type: application/json"`}
</pre>
</div>
</div>
</CardContent>
</Card>
{/* JWT Tokens */}
<Card className="mb-8">
<CardHeader>
<div className="flex items-center gap-3">
<Lock className="h-6 w-6 text-neon-cyan" />
<div>
<CardTitle>JWT Token Authentication</CardTitle>
<CardDescription>For user-based authentication</CardDescription>
</div>
</div>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div>
<h3 className="font-semibold text-white mb-2">1. Login</h3>
<pre className="rounded bg-studio-dark p-4 text-sm text-white overflow-x-auto">
{`mutation {
login(email: "user@example.com", password: "password") {
token
user {
id
email
name
}
}
}`}
</pre>
</div>
<div>
<h3 className="font-semibold text-white mb-2">2. Use the Token</h3>
<pre className="rounded bg-studio-dark p-4 text-sm text-white overflow-x-auto">
{`curl -X POST https://api.sankofa.nexus/graphql \\
-H "Authorization: Bearer <jwt_token>" \\
-H "Content-Type: application/json" \\
-d '{"query": "{ me { id email } }"}'`}
</pre>
</div>
</div>
</CardContent>
</Card>
{/* Security Best Practices */}
<Card className="mb-8 border-studio-medium">
<CardHeader>
<CardTitle>Security Best Practices</CardTitle>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li> Never commit API keys or tokens to version control</li>
<li> Use environment variables to store credentials</li>
<li> Rotate API keys regularly</li>
<li> Use HTTPS for all API requests</li>
<li> Implement token refresh for long-lived sessions</li>
<li> Monitor API key usage for suspicious activity</li>
</ul>
</CardContent>
</Card>
{/* Related Links */}
<div className="flex gap-4">
<Button variant="outline" asChild>
<Link href="/developers/docs/quickstart">Quick Start Guide </Link>
</Button>
<Button variant="outline" asChild>
<Link href="/developers/docs/api/graphql">GraphQL API </Link>
</Button>
</div>
</div>
</main>
</>
)
}

View File

@@ -0,0 +1,200 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Header } from '@/components/layout/header'
import { Book, Code, Terminal, GitBranch, Zap, FileText, Search } from 'lucide-react'
export default function DocsPage() {
return (
<>
<Header />
<main className="min-h-screen bg-studio-black">
{/* Hero */}
<section className="relative border-b border-studio-medium bg-gradient-to-br from-phoenix-fire/10 via-transparent to-sankofa-gold/10 py-24 px-4">
<div className="mx-auto max-w-4xl">
<div className="mb-8 flex items-center justify-center">
<Search className="mr-4 h-8 w-8 text-gray-400" />
<input
type="search"
placeholder="Search documentation..."
className="w-full max-w-md rounded-lg border border-studio-medium bg-studio-dark px-4 py-3 text-white placeholder-gray-400 focus:border-phoenix-fire focus:outline-none focus:ring-1 focus:ring-phoenix-fire"
/>
</div>
<h1 className="mb-6 text-center text-5xl font-bold text-white md:text-6xl">
Documentation
</h1>
<p className="mb-8 text-center text-xl text-gray-300">
Comprehensive guides, API references, and tutorials
</p>
</div>
</section>
{/* Quick Start */}
<section className="py-24 px-4">
<div className="mx-auto max-w-6xl">
<h2 className="mb-8 text-3xl font-bold text-white">Getting Started</h2>
<div className="grid gap-6 md:grid-cols-3">
<Card className="hover:border-phoenix-fire transition-colors cursor-pointer" asChild>
<Link href="/developers/docs/quickstart">
<CardHeader>
<Zap className="mb-2 h-8 w-8 text-phoenix-fire" />
<CardTitle>Quick Start</CardTitle>
<CardDescription>
Get up and running in 5 minutes
</CardDescription>
</CardHeader>
</Link>
</Card>
<Card className="hover:border-phoenix-fire transition-colors cursor-pointer" asChild>
<Link href="/developers/docs/installation">
<CardHeader>
<Terminal className="mb-2 h-8 w-8 text-sankofa-gold" />
<CardTitle>Installation</CardTitle>
<CardDescription>
Install and configure Phoenix Nexus
</CardDescription>
</CardHeader>
</Link>
</Card>
<Card className="hover:border-phoenix-fire transition-colors cursor-pointer" asChild>
<Link href="/developers/docs/concepts">
<CardHeader>
<Book className="mb-2 h-8 w-8 text-neon-cyan" />
<CardTitle>Core Concepts</CardTitle>
<CardDescription>
Understand the architecture
</CardDescription>
</CardHeader>
</Link>
</Card>
</div>
</div>
</section>
{/* Documentation Sections */}
<section className="border-t border-studio-medium bg-studio-dark py-24 px-4">
<div className="mx-auto max-w-6xl">
<h2 className="mb-8 text-3xl font-bold text-white">Documentation</h2>
<div className="grid gap-8 md:grid-cols-2">
<div>
<Code className="mb-4 h-8 w-8 text-phoenix-fire" />
<h3 className="mb-4 text-2xl font-bold text-white">API Reference</h3>
<ul className="space-y-2 text-gray-300">
<li>
<Link href="/developers/docs/api/graphql" className="hover:text-phoenix-fire">
GraphQL API
</Link>
</li>
<li>
<Link href="/developers/docs/api/rest" className="hover:text-phoenix-fire">
REST APIs
</Link>
</li>
<li>
<Link href="/developers/docs/api/websocket" className="hover:text-phoenix-fire">
WebSocket APIs
</Link>
</li>
<li>
<Link href="/developers/docs/api/authentication" className="hover:text-phoenix-fire">
Authentication
</Link>
</li>
</ul>
</div>
<div>
<FileText className="mb-4 h-8 w-8 text-sankofa-gold" />
<h3 className="mb-4 text-2xl font-bold text-white">Guides</h3>
<ul className="space-y-2 text-gray-300">
<li>
<Link href="/developers/docs/guides/architecture" className="hover:text-sankofa-gold">
Architecture Guides
</Link>
</li>
<li>
<Link href="/developers/docs/guides/security" className="hover:text-sankofa-gold">
Security Guides
</Link>
</li>
<li>
<Link href="/developers/docs/guides/compliance" className="hover:text-sankofa-gold">
Compliance Guides
</Link>
</li>
<li>
<Link href="/developers/docs/guides/best-practices" className="hover:text-sankofa-gold">
Best Practices
</Link>
</li>
</ul>
</div>
<div>
<Book className="mb-4 h-8 w-8 text-neon-cyan" />
<h3 className="mb-4 text-2xl font-bold text-white">Tutorials</h3>
<ul className="space-y-2 text-gray-300">
<li>
<Link href="/developers/docs/tutorials/first-app" className="hover:text-neon-cyan">
Build Your First App
</Link>
</li>
<li>
<Link href="/developers/docs/tutorials/multi-tenancy" className="hover:text-neon-cyan">
Multi-Tenancy Setup
</Link>
</li>
<li>
<Link href="/developers/docs/tutorials/integration" className="hover:text-neon-cyan">
Integration Examples
</Link>
</li>
</ul>
</div>
<div>
<GitBranch className="mb-4 h-8 w-8 text-phoenix-fire" />
<h3 className="mb-4 text-2xl font-bold text-white">SDKs & Tools</h3>
<ul className="space-y-2 text-gray-300">
<li>
<Link href="/developers/docs/sdks/cli" className="hover:text-phoenix-fire">
CLI Documentation
</Link>
</li>
<li>
<Link href="/developers/docs/sdks/typescript" className="hover:text-phoenix-fire">
TypeScript SDK
</Link>
</li>
<li>
<Link href="/developers/docs/sdks/terraform" className="hover:text-phoenix-fire">
Terraform Provider
</Link>
</li>
</ul>
</div>
</div>
</div>
</section>
{/* CTA */}
<section className="py-24 px-4">
<div className="mx-auto max-w-4xl text-center">
<h2 className="mb-6 text-4xl font-bold text-white">
Need More Help?
</h2>
<p className="mb-8 text-xl text-gray-400">
Access the developer portal for API keys and test environments
</p>
<Button variant="phoenix" size="lg" asChild>
<Link href="/portal/developers">Developer Portal</Link>
</Button>
</div>
</section>
</main>
</>
)
}

View File

@@ -0,0 +1,238 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Header } from '@/components/layout/header'
import { CheckCircle, Code, Key, Terminal, ArrowRight } from 'lucide-react'
export default function QuickStartPage() {
return (
<>
<Header />
<main className="min-h-screen bg-studio-black">
<div className="container mx-auto py-12 px-4 max-w-4xl">
<div className="mb-12 text-center">
<h1 className="text-5xl font-bold text-white mb-4">Quick Start Guide</h1>
<p className="text-xl text-gray-300">
Get up and running with Phoenix Nexus Cloud in 5 minutes
</p>
</div>
{/* Steps */}
<div className="space-y-8">
{/* Step 1 */}
<Card>
<CardHeader>
<div className="flex items-center gap-4">
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-phoenix-fire text-white font-bold">
1
</div>
<div>
<CardTitle>Create an Account</CardTitle>
<CardDescription>Sign up for Phoenix Nexus Cloud</CardDescription>
</div>
</div>
</CardHeader>
<CardContent>
<div className="space-y-4">
<p className="text-gray-300">
If you don't have an account yet, create one to get started.
</p>
<Button variant="phoenix" asChild>
<Link href="/portal/get-started">
Get Started <ArrowRight className="ml-2 h-4 w-4" />
</Link>
</Button>
</div>
</CardContent>
</Card>
{/* Step 2 */}
<Card>
<CardHeader>
<div className="flex items-center gap-4">
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-sankofa-gold text-studio-black font-bold">
2
</div>
<div>
<CardTitle>Get Your API Key</CardTitle>
<CardDescription>Generate an API key from the Developer Portal</CardDescription>
</div>
</div>
</CardHeader>
<CardContent>
<div className="space-y-4">
<p className="text-gray-300">
Navigate to the Developer Portal and create your first API key.
</p>
<ol className="list-decimal list-inside space-y-2 text-gray-300">
<li>Go to Developer Portal</li>
<li>Click "Create API Key"</li>
<li>Give it a descriptive name</li>
<li>Copy the key (you won't see it again!)</li>
</ol>
<Button variant="outline" asChild>
<Link href="/portal/developers/keys">
<Key className="mr-2 h-4 w-4" />
Manage API Keys
</Link>
</Button>
</div>
</CardContent>
</Card>
{/* Step 3 */}
<Card>
<CardHeader>
<div className="flex items-center gap-4">
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-neon-cyan text-studio-black font-bold">
3
</div>
<div>
<CardTitle>Install the CLI</CardTitle>
<CardDescription>Install the Phoenix Nexus CLI tool</CardDescription>
</div>
</div>
</CardHeader>
<CardContent>
<div className="space-y-4">
<p className="text-gray-300">
Install the CLI using your preferred package manager:
</p>
<div className="space-y-2">
<div>
<p className="text-sm font-semibold text-gray-400 mb-1">npm</p>
<code className="block rounded bg-studio-dark px-4 py-2 font-mono text-sm text-white">
npm install -g @sankofa/phoenix-cli
</code>
</div>
<div>
<p className="text-sm font-semibold text-gray-400 mb-1">pnpm</p>
<code className="block rounded bg-studio-dark px-4 py-2 font-mono text-sm text-white">
pnpm add -g @sankofa/phoenix-cli
</code>
</div>
</div>
</div>
</CardContent>
</Card>
{/* Step 4 */}
<Card>
<CardHeader>
<div className="flex items-center gap-4">
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-phoenix-fire text-white font-bold">
4
</div>
<div>
<CardTitle>Authenticate</CardTitle>
<CardDescription>Configure the CLI with your API key</CardDescription>
</div>
</div>
</CardHeader>
<CardContent>
<div className="space-y-4">
<p className="text-gray-300">
Set your API key as an environment variable or use the login command:
</p>
<div className="space-y-2">
<div>
<p className="text-sm font-semibold text-gray-400 mb-1">Environment Variable</p>
<code className="block rounded bg-studio-dark px-4 py-2 font-mono text-sm text-white">
export PHOENIX_API_KEY=sk_live_your_key_here
</code>
</div>
<div>
<p className="text-sm font-semibold text-gray-400 mb-1">Or use login</p>
<code className="block rounded bg-studio-dark px-4 py-2 font-mono text-sm text-white">
phoenix login
</code>
</div>
</div>
</div>
</CardContent>
</Card>
{/* Step 5 */}
<Card>
<CardHeader>
<div className="flex items-center gap-4">
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-sankofa-gold text-studio-black font-bold">
5
</div>
<div>
<CardTitle>Make Your First API Call</CardTitle>
<CardDescription>Test the connection with a simple query</CardDescription>
</div>
</div>
</CardHeader>
<CardContent>
<div className="space-y-4">
<p className="text-gray-300">
Test your setup with a simple GraphQL query:
</p>
<pre className="rounded bg-studio-dark p-4 text-sm text-white overflow-x-auto">
{`phoenix query '
query {
me {
id
email
name
}
}
'`}
</pre>
<p className="text-sm text-gray-400">
Or use curl to make a direct HTTP request:
</p>
<pre className="rounded bg-studio-dark p-4 text-sm text-white overflow-x-auto">
{`curl -X POST https://api.sankofa.nexus/graphql \\
-H "Authorization: Bearer $PHOENIX_API_KEY" \\
-H "Content-Type: application/json" \\
-d '{"query": "{ me { id email name } }"}'`}
</pre>
</div>
</CardContent>
</Card>
</div>
{/* Next Steps */}
<Card className="mt-12 border-phoenix-fire/50">
<CardHeader>
<CardTitle>Next Steps</CardTitle>
<CardDescription>Continue your journey with Phoenix Nexus</CardDescription>
</CardHeader>
<CardContent>
<div className="grid gap-4 md:grid-cols-2">
<div className="flex items-start gap-3">
<CheckCircle className="mt-1 h-5 w-5 text-phoenix-fire flex-shrink-0" />
<div>
<h4 className="font-semibold text-white mb-1">Read the API Reference</h4>
<p className="text-sm text-gray-400 mb-2">
Learn about all available queries and mutations
</p>
<Button variant="outline" size="sm" asChild>
<Link href="/developers/docs/api/graphql">API Reference </Link>
</Button>
</div>
</div>
<div className="flex items-start gap-3">
<CheckCircle className="mt-1 h-5 w-5 text-sankofa-gold flex-shrink-0" />
<div>
<h4 className="font-semibold text-white mb-1">Explore Examples</h4>
<p className="text-sm text-gray-400 mb-2">
See real-world integration examples
</p>
<Button variant="outline" size="sm" asChild>
<Link href="/developers/docs/tutorials">Tutorials </Link>
</Button>
</div>
</div>
</div>
</CardContent>
</Card>
</div>
</main>
</>
)
}

View File

@@ -0,0 +1,105 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Header } from '@/components/layout/header'
import { BookOpen, Code, Rocket, Zap } from 'lucide-react'
export default function TutorialsPage() {
const tutorials = [
{
title: 'Getting Started with Phoenix Nexus',
description: 'Build your first application using the Phoenix Nexus API',
icon: Rocket,
href: '/developers/docs/tutorials/getting-started',
level: 'Beginner',
},
{
title: 'Building a Multi-Tenant Application',
description: 'Learn how to leverage multi-tenancy in your applications',
icon: Code,
href: '/developers/docs/tutorials/multi-tenant',
level: 'Intermediate',
},
{
title: 'Real-Time Resource Monitoring',
description: 'Implement real-time monitoring with GraphQL subscriptions',
icon: Zap,
href: '/developers/docs/tutorials/realtime-monitoring',
level: 'Advanced',
},
{
title: 'Integrating with Keycloak SSO',
description: 'Add single sign-on to your application',
icon: BookOpen,
href: '/developers/docs/tutorials/keycloak-sso',
level: 'Intermediate',
},
]
return (
<>
<Header />
<main className="min-h-screen bg-studio-black">
<div className="container mx-auto py-12 px-4 max-w-6xl">
<div className="mb-12 text-center">
<h1 className="text-5xl font-bold text-white mb-4">Tutorials</h1>
<p className="text-xl text-gray-300">
Step-by-step guides to help you build with Phoenix Nexus
</p>
</div>
<div className="grid gap-6 md:grid-cols-2">
{tutorials.map((tutorial) => {
const Icon = tutorial.icon
return (
<Card key={tutorial.href} className="border-studio-medium hover:border-phoenix-fire/50 transition-colors">
<CardHeader>
<div className="flex items-start gap-4">
<div className="rounded-lg bg-phoenix-fire/20 p-3">
<Icon className="h-6 w-6 text-phoenix-fire" />
</div>
<div className="flex-1">
<div className="flex items-center gap-2 mb-2">
<CardTitle>{tutorial.title}</CardTitle>
<span className="rounded-full bg-studio-medium px-2 py-1 text-xs text-gray-400">
{tutorial.level}
</span>
</div>
<CardDescription>{tutorial.description}</CardDescription>
</div>
</div>
</CardHeader>
<CardContent>
<Button variant="outline" asChild>
<Link href={tutorial.href}>Start Tutorial </Link>
</Button>
</CardContent>
</Card>
)
})}
</div>
<Card className="mt-12 border-studio-medium">
<CardHeader>
<CardTitle>More Resources</CardTitle>
</CardHeader>
<CardContent>
<div className="grid gap-4 md:grid-cols-3">
<Button variant="outline" asChild>
<Link href="/developers/docs/api/graphql">API Reference</Link>
</Button>
<Button variant="outline" asChild>
<Link href="/developers/docs/quickstart">Quick Start</Link>
</Button>
<Button variant="outline" asChild>
<Link href="/developers/docs/guides/authentication">Authentication</Link>
</Button>
</div>
</CardContent>
</Card>
</div>
</main>
</>
)
}

182
src/app/developers/page.tsx Normal file
View File

@@ -0,0 +1,182 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { PublicLayout } from '@/components/layout/public-layout'
import { Code, Book, Key, Terminal, Zap, GitBranch } from 'lucide-react'
export default function DevelopersPage() {
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black">
{/* Hero */}
<section className="relative border-b border-studio-medium bg-gradient-to-br from-phoenix-fire/10 via-transparent to-sankofa-gold/10 py-24 px-4">
<div className="mx-auto max-w-4xl text-center">
<h1 className="mb-6 text-5xl font-bold text-white md:text-6xl">
Developer Resources
</h1>
<p className="mb-8 text-xl text-gray-300">
Build on Sankofa's Phoenix Nexus Cloud with comprehensive APIs, SDKs, and documentation
</p>
<div className="flex flex-col gap-4 sm:flex-row sm:justify-center">
<Button variant="phoenix" size="lg" asChild>
<Link href="/developers/docs">View Documentation</Link>
</Button>
<Button variant="outline" size="lg" asChild>
<Link href="/portal/developers">Developer Portal</Link>
</Button>
</div>
</div>
</section>
{/* Quick Links */}
<section className="py-24 px-4">
<div className="mx-auto max-w-6xl">
<h2 className="mb-12 text-center text-4xl font-bold text-white">
Get Started
</h2>
<div className="grid gap-6 md:grid-cols-3">
<Card className="hover:border-phoenix-fire transition-colors cursor-pointer" asChild>
<Link href="/developers/docs">
<CardHeader>
<Book className="mb-2 h-10 w-10 text-phoenix-fire" />
<CardTitle>Documentation</CardTitle>
<CardDescription>
API references, guides, tutorials, and architecture blueprints
</CardDescription>
</CardHeader>
</Link>
</Card>
<Card className="hover:border-phoenix-fire transition-colors cursor-pointer" asChild>
<Link href="/portal/developers">
<CardHeader>
<Key className="mb-2 h-10 w-10 text-sankofa-gold" />
<CardTitle>Developer Portal</CardTitle>
<CardDescription>
API keys, test environments, logs, and developer tools
</CardDescription>
</CardHeader>
</Link>
</Card>
<Card className="hover:border-phoenix-fire transition-colors cursor-pointer" asChild>
<Link href="/developers/quickstart">
<CardHeader>
<Zap className="mb-2 h-10 w-10 text-neon-cyan" />
<CardTitle>Quick Start</CardTitle>
<CardDescription>
Get up and running in minutes with our step-by-step guides
</CardDescription>
</CardHeader>
</Link>
</Card>
</div>
</div>
</section>
{/* Developer Tools */}
<section className="border-t border-studio-medium bg-studio-dark py-24 px-4">
<div className="mx-auto max-w-6xl">
<h2 className="mb-12 text-center text-4xl font-bold text-white">
Developer Tools & Resources
</h2>
<div className="grid gap-8 md:grid-cols-2">
<div>
<Code className="mb-4 h-8 w-8 text-phoenix-fire" />
<h3 className="mb-4 text-2xl font-bold text-white">GraphQL API</h3>
<p className="mb-4 text-gray-300">
Powerful GraphQL API with real-time subscriptions, comprehensive type system,
and built-in authentication.
</p>
<ul className="space-y-2 text-sm text-gray-400">
<li> Interactive API explorer</li>
<li> TypeScript SDK</li>
<li> WebSocket subscriptions</li>
<li> Rate limiting and quotas</li>
</ul>
<Button variant="outline" className="mt-4" asChild>
<Link href="/developers/docs/api">API Reference </Link>
</Button>
</div>
<div>
<Terminal className="mb-4 h-8 w-8 text-sankofa-gold" />
<h3 className="mb-4 text-2xl font-bold text-white">CLI & SDKs</h3>
<p className="mb-4 text-gray-300">
Command-line tools and SDKs for popular languages to integrate Phoenix Nexus
into your workflow.
</p>
<ul className="space-y-2 text-sm text-gray-400">
<li> Phoenix CLI (Node.js, Python, Go)</li>
<li> Terraform provider</li>
<li> Kubernetes operators</li>
<li> CI/CD integrations</li>
</ul>
<Button variant="outline" className="mt-4" asChild>
<Link href="/developers/docs/sdks">View SDKs </Link>
</Button>
</div>
<div>
<GitBranch className="mb-4 h-8 w-8 text-neon-cyan" />
<h3 className="mb-4 text-2xl font-bold text-white">GitOps & Infrastructure</h3>
<p className="mb-4 text-gray-300">
Infrastructure as Code with Crossplane, ArgoCD, and GitOps workflows for
declarative infrastructure management.
</p>
<ul className="space-y-2 text-sm text-gray-400">
<li> Crossplane providers</li>
<li> ArgoCD integration</li>
<li> GitOps templates</li>
<li> Infrastructure blueprints</li>
</ul>
<Button variant="outline" className="mt-4" asChild>
<Link href="/developers/docs/gitops">GitOps Guide </Link>
</Button>
</div>
<div>
<Zap className="mb-4 h-8 w-8 text-phoenix-fire" />
<h3 className="mb-4 text-2xl font-bold text-white">Test Environments</h3>
<p className="mb-4 text-gray-300">
Sandbox environments for testing and development, with instant provisioning
and automatic cleanup.
</p>
<ul className="space-y-2 text-sm text-gray-400">
<li> Free tier for development</li>
<li> Isolated test environments</li>
<li> Pre-configured templates</li>
<li> Integration testing tools</li>
</ul>
<Button variant="outline" className="mt-4" asChild>
<Link href="/portal/developers">Get API Keys </Link>
</Button>
</div>
</div>
</div>
</section>
{/* CTA */}
<section className="py-24 px-4">
<div className="mx-auto max-w-4xl text-center">
<h2 className="mb-6 text-4xl font-bold text-white">
Ready to Build?
</h2>
<p className="mb-8 text-xl text-gray-400">
Start building on sovereign cloud infrastructure today
</p>
<div className="flex flex-col gap-4 sm:flex-row sm:justify-center">
<Button variant="phoenix" size="lg" asChild>
<Link href="/portal/developers">Access Developer Portal</Link>
</Button>
<Button variant="outline" size="lg" asChild>
<Link href="/developers/docs">Read Documentation</Link>
</Button>
</div>
</div>
</section>
</div>
</PublicLayout>
)
}

View File

@@ -0,0 +1,131 @@
'use client'
import { PublicLayout } from '@/components/layout/public-layout'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { useState } from 'react'
import { Play, Code, Book } from 'lucide-react'
export default function GraphQLExplorerPage() {
const [query, setQuery] = useState(`query {
resources {
id
name
type
status
}
}`)
const [variables, setVariables] = useState('{}')
const [response, setResponse] = useState<string | null>(null)
const [loading, setLoading] = useState(false)
const executeQuery = async () => {
setLoading(true)
try {
// In production, this would call the actual GraphQL API
const res = await fetch('/api/graphql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query, variables: JSON.parse(variables) }),
})
const data = await res.json()
setResponse(JSON.stringify(data, null, 2))
} catch (error) {
setResponse(JSON.stringify({ error: error.message }, null, 2))
} finally {
setLoading(false)
}
}
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black py-24 px-4">
<div className="mx-auto max-w-7xl">
<div className="mb-8">
<h1 className="mb-4 text-4xl font-bold text-white">GraphQL API Explorer</h1>
<p className="text-gray-400">
Interactive GraphQL API explorer with live query execution and schema documentation
</p>
</div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
<Card className="bg-studio-dark border-studio-medium">
<CardHeader>
<CardTitle className="text-white flex items-center gap-2">
<Code className="h-5 w-5 text-phoenix-fire" />
Query Editor
</CardTitle>
</CardHeader>
<CardContent>
<textarea
value={query}
onChange={(e) => setQuery(e.target.value)}
className="w-full h-64 p-4 bg-studio-black border border-studio-medium rounded text-white font-mono text-sm"
placeholder="Enter your GraphQL query..."
/>
</CardContent>
</Card>
<Card className="bg-studio-dark border-studio-medium">
<CardHeader>
<CardTitle className="text-white flex items-center gap-2">
<Code className="h-5 w-5 text-sankofa-gold" />
Variables (JSON)
</CardTitle>
</CardHeader>
<CardContent>
<textarea
value={variables}
onChange={(e) => setVariables(e.target.value)}
className="w-full h-64 p-4 bg-studio-black border border-studio-medium rounded text-white font-mono text-sm"
placeholder='{"key": "value"}'
/>
</CardContent>
</Card>
</div>
<div className="mb-6">
<button
onClick={executeQuery}
disabled={loading}
className="px-6 py-3 bg-phoenix-fire text-white rounded-lg hover:bg-phoenix-fire/90 transition-colors disabled:opacity-50 flex items-center gap-2"
>
<Play className="h-4 w-4" />
{loading ? 'Executing...' : 'Execute Query'}
</button>
</div>
{response && (
<Card className="bg-studio-dark border-studio-medium">
<CardHeader>
<CardTitle className="text-white flex items-center gap-2">
<Book className="h-5 w-5 text-neon-cyan" />
Response
</CardTitle>
</CardHeader>
<CardContent>
<pre className="p-4 bg-studio-black border border-studio-medium rounded text-white font-mono text-sm overflow-auto">
{response}
</pre>
</CardContent>
</Card>
)}
<Card className="mt-6 bg-studio-dark border-studio-medium">
<CardHeader>
<CardTitle className="text-white">Schema Documentation</CardTitle>
</CardHeader>
<CardContent>
<p className="text-gray-300 mb-4">
Explore the GraphQL schema to discover available queries, mutations, and types.
</p>
<button className="px-4 py-2 bg-studio-medium text-white rounded hover:bg-studio-medium/80 transition-colors">
View Schema Documentation
</button>
</CardContent>
</Card>
</div>
</div>
</PublicLayout>
)
}

73
src/app/docs/api/page.tsx Normal file
View File

@@ -0,0 +1,73 @@
import { PublicLayout } from '@/components/layout/public-layout'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import Link from 'next/link'
import { Button } from '@/components/ui/button'
export default function APIDocsPage() {
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black py-24 px-4">
<div className="mx-auto max-w-4xl">
<h1 className="mb-8 text-4xl font-bold text-white">API Reference</h1>
<div className="space-y-6">
<Card>
<CardHeader>
<CardTitle className="text-white">GraphQL API</CardTitle>
<CardDescription>
Comprehensive GraphQL API with real-time subscriptions
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-gray-300 mb-4">
Our GraphQL API provides a flexible, type-safe interface for querying and mutating
infrastructure resources, with built-in authentication and real-time subscriptions.
</p>
<Button variant="outline" asChild>
<Link href="/docs/api/graphql">View GraphQL Schema </Link>
</Button>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-white">REST API</CardTitle>
<CardDescription>
Traditional REST endpoints for resource management
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-gray-300 mb-4">
RESTful API endpoints following standard HTTP conventions for managing
resources, with comprehensive OpenAPI documentation.
</p>
<Button variant="outline" asChild>
<Link href="/docs/api/rest">View REST API Docs </Link>
</Button>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-white">SDKs</CardTitle>
<CardDescription>
Client libraries for popular programming languages
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-gray-300 mb-4">
Official SDKs for TypeScript, Python, Go, and more, with type definitions
and comprehensive examples.
</p>
<Button variant="outline" asChild>
<Link href="/docs/api/sdks">View SDK Documentation </Link>
</Button>
</CardContent>
</Card>
</div>
</div>
</div>
</PublicLayout>
)
}

View File

@@ -0,0 +1,73 @@
import { PublicLayout } from '@/components/layout/public-layout'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import Link from 'next/link'
import { Button } from '@/components/ui/button'
export default function GovernancePage() {
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black py-24 px-4">
<div className="mx-auto max-w-4xl">
<h1 className="mb-8 text-4xl font-bold text-white">Governance & Architecture</h1>
<div className="space-y-6">
<Card>
<CardHeader>
<CardTitle className="text-white">Architecture Blueprints</CardTitle>
<CardDescription>
Reference architectures for common patterns
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-gray-300 mb-4">
Pre-built architecture blueprints for common deployment patterns,
including multi-region, high-availability, and disaster recovery setups.
</p>
<Button variant="outline" asChild>
<Link href="/docs/governance/blueprints">View Blueprints </Link>
</Button>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-white">Compliance Guides</CardTitle>
<CardDescription>
Compliance frameworks and requirements
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-gray-300 mb-4">
Guides for meeting compliance requirements including SOC 2, ISO 27001,
GDPR, HIPAA, and other regulatory frameworks.
</p>
<Button variant="outline" asChild>
<Link href="/docs/governance/compliance">View Compliance Guides </Link>
</Button>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-white">Security Frameworks</CardTitle>
<CardDescription>
Security best practices and frameworks
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-gray-300 mb-4">
Security frameworks, threat modeling, and best practices for securing
your infrastructure and applications.
</p>
<Button variant="outline" asChild>
<Link href="/docs/governance/security">View Security Frameworks </Link>
</Button>
</CardContent>
</Card>
</div>
</div>
</div>
</PublicLayout>
)
}

View File

@@ -0,0 +1,73 @@
import { PublicLayout } from '@/components/layout/public-layout'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import Link from 'next/link'
import { Button } from '@/components/ui/button'
export default function GuidesPage() {
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black py-24 px-4">
<div className="mx-auto max-w-4xl">
<h1 className="mb-8 text-4xl font-bold text-white">Conceptual Guides</h1>
<div className="space-y-6">
<Card>
<CardHeader>
<CardTitle className="text-white">Architecture Overview</CardTitle>
<CardDescription>
Understanding the Sankofa Phoenix architecture
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-gray-300 mb-4">
Learn about the multi-tier architecture, global deployment model, and
how components work together to deliver sovereign cloud infrastructure.
</p>
<Button variant="outline" asChild>
<Link href="/docs/guides/architecture">Read Architecture Guide </Link>
</Button>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-white">Well-Architected Framework</CardTitle>
<CardDescription>
Best practices for building on Sankofa Phoenix
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-gray-300 mb-4">
Guidelines for building reliable, secure, performant, and cost-effective
applications on the Phoenix platform.
</p>
<Button variant="outline" asChild>
<Link href="/docs/guides/well-architected">View Framework </Link>
</Button>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-white">Best Practices</CardTitle>
<CardDescription>
Recommended patterns and practices
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-gray-300 mb-4">
Learn from real-world examples and recommended patterns for common
use cases and scenarios.
</p>
<Button variant="outline" asChild>
<Link href="/docs/guides/best-practices">View Best Practices </Link>
</Button>
</CardContent>
</Card>
</div>
</div>
</div>
</PublicLayout>
)
}

134
src/app/docs/page.tsx Normal file
View File

@@ -0,0 +1,134 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { PublicLayout } from '@/components/layout/public-layout'
import { Book, Code, GraduationCap, Shield, ArrowRight } from 'lucide-react'
export default function DocsPage() {
const docSections = [
{
title: 'API Reference',
description: 'REST API documentation, GraphQL schema, and SDK references',
icon: Code,
href: '/docs/api',
categories: ['REST API', 'GraphQL', 'SDKs'],
},
{
title: 'Conceptual Guides',
description: 'Architecture overview, Well-Architected Framework, and best practices',
icon: Book,
href: '/docs/guides',
categories: ['Architecture', 'Best Practices', 'Framework'],
},
{
title: 'Tutorials & Quickstarts',
description: 'Getting started guides, step-by-step tutorials, and sample code',
icon: GraduationCap,
href: '/docs/tutorials',
categories: ['Quickstarts', 'Tutorials', 'Samples'],
},
{
title: 'Governance & Architecture',
description: 'Architecture blueprints, compliance guides, and security frameworks',
icon: Shield,
href: '/docs/governance',
categories: ['Blueprints', 'Compliance', 'Security'],
},
]
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black">
{/* Hero Section */}
<section className="relative flex min-h-[40vh] flex-col items-center justify-center overflow-hidden px-4">
<div className="absolute inset-0 bg-gradient-to-br from-phoenix-fire/20 via-transparent to-sankofa-gold/20" />
<div className="relative z-10 max-w-4xl text-center">
<h1 className="mb-6 text-5xl font-bold tracking-tight text-white md:text-7xl">
Documentation & Learning
</h1>
<p className="mb-8 text-xl text-gray-300 md:text-2xl">
Comprehensive guides, tutorials, and references for building on Sankofa Phoenix
</p>
</div>
</section>
{/* Documentation Sections */}
<section className="py-24 px-4">
<div className="mx-auto max-w-7xl">
<div className="grid gap-8 md:grid-cols-2">
{docSections.map((section) => {
const Icon = section.icon
return (
<Card key={section.href} className="hover:border-phoenix-fire transition-colors">
<CardHeader>
<div className="flex items-center gap-3 mb-2">
<Icon className="h-8 w-8 text-phoenix-fire" />
<CardTitle className="text-2xl text-white">{section.title}</CardTitle>
</div>
<CardDescription className="text-gray-400">
{section.description}
</CardDescription>
</CardHeader>
<CardContent>
<div className="flex flex-wrap gap-2 mb-4">
{section.categories.map((category) => (
<span
key={category}
className="px-2 py-1 text-xs bg-studio-dark text-gray-400 rounded"
>
{category}
</span>
))}
</div>
<Button variant="outline" className="w-full" asChild>
<Link href={section.href}>
Explore {section.title}
<ArrowRight className="ml-2 h-4 w-4" />
</Link>
</Button>
</CardContent>
</Card>
)
})}
</div>
</div>
</section>
{/* Quick Links */}
<section className="py-16 px-4 bg-studio-dark">
<div className="mx-auto max-w-4xl">
<h2 className="mb-8 text-center text-3xl font-bold text-white">
Quick Links
</h2>
<div className="grid gap-4 md:grid-cols-3">
<Link
href="/docs/api/graphql"
className="p-4 bg-studio-black rounded-lg hover:border-phoenix-fire border border-studio-medium transition-colors"
>
<h3 className="text-lg font-semibold text-white mb-2">GraphQL API</h3>
<p className="text-sm text-gray-400">Interactive API explorer</p>
</Link>
<Link
href="/docs/tutorials/getting-started"
className="p-4 bg-studio-black rounded-lg hover:border-phoenix-fire border border-studio-medium transition-colors"
>
<h3 className="text-lg font-semibold text-white mb-2">Getting Started</h3>
<p className="text-sm text-gray-400">Your first deployment</p>
</Link>
<Link
href="/docs/guides/architecture"
className="p-4 bg-studio-black rounded-lg hover:border-phoenix-fire border border-studio-medium transition-colors"
>
<h3 className="text-lg font-semibold text-white mb-2">Architecture</h3>
<p className="text-sm text-gray-400">System architecture overview</p>
</Link>
</div>
</div>
</section>
</div>
</PublicLayout>
)
}

View File

@@ -0,0 +1,73 @@
import { PublicLayout } from '@/components/layout/public-layout'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import Link from 'next/link'
import { Button } from '@/components/ui/button'
export default function TutorialsPage() {
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black py-24 px-4">
<div className="mx-auto max-w-4xl">
<h1 className="mb-8 text-4xl font-bold text-white">Tutorials & Quickstarts</h1>
<div className="space-y-6">
<Card>
<CardHeader>
<CardTitle className="text-white">Getting Started</CardTitle>
<CardDescription>
Your first deployment on Sankofa Phoenix
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-gray-300 mb-4">
Get up and running in minutes with our step-by-step getting started guide.
Deploy your first application and learn the basics.
</p>
<Button variant="outline" asChild>
<Link href="/docs/tutorials/getting-started">Start Tutorial </Link>
</Button>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-white">Step-by-Step Tutorials</CardTitle>
<CardDescription>
Comprehensive tutorials for common scenarios
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-gray-300 mb-4">
Follow along with detailed tutorials covering infrastructure provisioning,
application deployment, monitoring, and more.
</p>
<Button variant="outline" asChild>
<Link href="/docs/tutorials/step-by-step">Browse Tutorials </Link>
</Button>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-white">Sample Code</CardTitle>
<CardDescription>
Ready-to-use code samples and examples
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-gray-300 mb-4">
Explore sample code, configuration files, and complete examples that you
can use as starting points for your projects.
</p>
<Button variant="outline" asChild>
<Link href="/docs/tutorials/samples">View Samples </Link>
</Button>
</CardContent>
</Card>
</div>
</div>
</div>
</PublicLayout>
)
}

260
src/app/enterprise/page.tsx Normal file
View File

@@ -0,0 +1,260 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { PublicLayout } from '@/components/layout/public-layout'
import { Shield, Lock, Globe, CheckCircle } from 'lucide-react'
export default function EnterprisePage() {
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black">
{/* Hero Section */}
<section className="relative flex min-h-[60vh] flex-col items-center justify-center overflow-hidden px-4">
<div className="absolute inset-0 bg-gradient-to-br from-phoenix-fire/20 via-transparent to-sankofa-gold/20" />
<div className="relative z-10 max-w-4xl text-center">
<h1 className="mb-6 text-5xl font-bold tracking-tight text-white md:text-7xl">
Enterprise & Government
</h1>
<p className="mb-8 text-xl text-gray-300 md:text-2xl">
Sovereign cloud infrastructure built for enterprise scale and government compliance
</p>
<p className="mb-12 text-lg text-gray-400">
Trust, security, and compliance at the core of every deployment
</p>
<div className="flex flex-col gap-4 sm:flex-row sm:justify-center">
<Button variant="phoenix" size="lg" asChild>
<Link href="/portal">Contact Sales</Link>
</Button>
<Button variant="outline" size="lg" asChild>
<Link href="/company/trust">Learn About Trust</Link>
</Button>
</div>
</div>
</section>
{/* Trust & Compliance Section */}
<section className="py-24 px-4">
<div className="mx-auto max-w-6xl">
<h2 className="mb-12 text-center text-4xl font-bold text-white">
Trust & Compliance
</h2>
<div className="grid gap-8 md:grid-cols-3">
<Card>
<CardHeader>
<Shield className="mb-4 h-12 w-12 text-phoenix-fire" />
<CardTitle className="text-phoenix-fire">Security</CardTitle>
<CardDescription>
Enterprise-grade security
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-500" />
SOC 2 Type II certified
</li>
<li className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-500" />
ISO 27001 compliant
</li>
<li className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-500" />
Zero Trust architecture
</li>
<li className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-500" />
End-to-end encryption
</li>
</ul>
</CardContent>
</Card>
<Card>
<CardHeader>
<Lock className="mb-4 h-12 w-12 text-sankofa-gold" />
<CardTitle className="text-sankofa-gold">Privacy</CardTitle>
<CardDescription>
Data sovereignty and privacy
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-500" />
GDPR compliant
</li>
<li className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-500" />
Data residency controls
</li>
<li className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-500" />
Right to deletion
</li>
<li className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-500" />
Privacy by design
</li>
</ul>
</CardContent>
</Card>
<Card>
<CardHeader>
<Globe className="mb-4 h-12 w-12 text-neon-cyan" />
<CardTitle className="text-neon-cyan">Compliance</CardTitle>
<CardDescription>
Regulatory compliance
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-500" />
HIPAA ready
</li>
<li className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-500" />
PCI-DSS compliant
</li>
<li className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-500" />
FedRAMP in progress
</li>
<li className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-500" />
Regional compliance
</li>
</ul>
</CardContent>
</Card>
</div>
</div>
</section>
{/* Sovereignty Messaging */}
<section className="py-24 px-4 bg-studio-dark">
<div className="mx-auto max-w-4xl text-center">
<h2 className="mb-6 text-4xl font-bold text-white">
True Technological Sovereignty
</h2>
<p className="mb-8 text-xl text-gray-300">
Sankofa Phoenix delivers complete control over infrastructure, data, and destiny.
No vendor lock-in. No dependencies on foreign cloud providers.
Sovereign identity and self-determined policy frameworks.
</p>
<p className="text-lg text-gray-400">
Built for organizations that require true sovereignty, cultural alignment,
and infrastructure that honors identity while delivering world-class performance.
</p>
</div>
</section>
{/* Case Studies / Use Cases */}
<section className="py-24 px-4">
<div className="mx-auto max-w-6xl">
<h2 className="mb-12 text-center text-4xl font-bold text-white">
Enterprise Use Cases
</h2>
<div className="grid gap-8 md:grid-cols-2">
<Card>
<CardHeader>
<CardTitle>Government & Public Sector</CardTitle>
<CardDescription>
Sovereign infrastructure for government agencies
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li> Data residency and sovereignty requirements</li>
<li> Compliance with government regulations</li>
<li> Secure multi-agency collaboration</li>
<li> Disaster recovery and business continuity</li>
</ul>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>Financial Services</CardTitle>
<CardDescription>
Secure, compliant infrastructure for financial institutions
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li> PCI-DSS compliant infrastructure</li>
<li> Real-time transaction processing</li>
<li> Regulatory reporting and compliance</li>
<li> High-availability and fault tolerance</li>
</ul>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>Healthcare & Life Sciences</CardTitle>
<CardDescription>
HIPAA-compliant infrastructure for healthcare organizations
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-gray-300">
<li> Protected health information (PHI) handling</li>
<li> HIPAA compliance and audit trails</li>
<li> Research data management</li>
<li> Interoperability and data exchange</li>
</ul>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>Global Enterprises</CardTitle>
<CardDescription>
Multi-region infrastructure for global operations
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li> 325-region global deployment</li>
<li> Cultural intelligence and localization</li>
<li> Multi-tenant isolation</li>
<li> Enterprise-scale resource management</li>
</ul>
</CardContent>
</Card>
</div>
</div>
</section>
{/* CTA Section */}
<section className="py-24 px-4 bg-studio-dark">
<div className="mx-auto max-w-4xl text-center">
<h2 className="mb-6 text-4xl font-bold text-white">
Ready to Get Started?
</h2>
<p className="mb-8 text-xl text-gray-400">
Contact our enterprise sales team to discuss your requirements
</p>
<div className="flex flex-col gap-4 sm:flex-row sm:justify-center">
<Button variant="phoenix" size="lg" asChild>
<Link href="/portal">Contact Sales</Link>
</Button>
<Button variant="outline" size="lg" asChild>
<Link href="/company/trust">View Trust Center</Link>
</Button>
</div>
</div>
</section>
</div>
</PublicLayout>
)
}

View File

@@ -14,7 +14,11 @@
body {
@apply bg-studio-black text-foreground;
/* Cross-browser text size adjustment */
-webkit-text-size-adjust: 100%;
text-size-adjust: 100%;
}
}
@layer utilities {
@@ -34,6 +38,12 @@
box-shadow: 0 0 20px rgba(0, 255, 209, 0.5);
}
/* Cross-browser backdrop filter support */
.backdrop-blur-safari {
-webkit-backdrop-filter: blur(8px);
backdrop-filter: blur(8px);
}
.sr-only {
position: absolute;
width: 1px;
@@ -56,5 +66,45 @@
clip: auto;
white-space: normal;
}
/* Chart container styles */
.chart-container {
height: 100%;
width: 100%;
}
/* Status indicator colors */
.status-pass {
background-color: #00FF88;
color: #000;
}
.status-fail {
background-color: #FF0040;
color: #000;
}
.status-warning {
background-color: #FFB800;
color: #000;
}
/* Dynamic color utilities - use data attributes for dynamic colors */
[data-pillar-color] {
color: var(--pillar-color);
}
[data-score-color] {
color: var(--score-color);
}
[data-health-color] {
color: var(--health-color);
}
[data-pillar-bg] {
background-color: var(--pillar-bg);
}
}

View File

@@ -0,0 +1,13 @@
import { ComplianceMapping } from '@/components/infrastructure/ComplianceMapping'
import { InfrastructureErrorBoundary } from '@/components/infrastructure/InfrastructureErrorBoundary'
export default function CompliancePage() {
return (
<InfrastructureErrorBoundary>
<div className="container mx-auto py-8 px-4">
<ComplianceMapping />
</div>
</InfrastructureErrorBoundary>
)
}

View File

@@ -0,0 +1,13 @@
import { CostEstimates } from '@/components/infrastructure/CostEstimates'
import { InfrastructureErrorBoundary } from '@/components/infrastructure/InfrastructureErrorBoundary'
export default function CostsPage() {
return (
<InfrastructureErrorBoundary>
<div className="container mx-auto py-8 px-4">
<CostEstimates />
</div>
</InfrastructureErrorBoundary>
)
}

View File

@@ -0,0 +1,20 @@
import { SkipLink, useKeyboardNavigation, FocusIndicator } from '@/components/infrastructure/AccessibilityEnhancements'
export default function InfrastructureLayout({
children,
}: {
children: React.ReactNode
}) {
useKeyboardNavigation()
return (
<>
<SkipLink />
<FocusIndicator />
<div id="main-content" className="min-h-screen">
{children}
</div>
</>
)
}

View File

@@ -0,0 +1,13 @@
import { DocsDashboard } from '@/components/infrastructure/DocsDashboard'
import { InfrastructureErrorBoundary } from '@/components/infrastructure/InfrastructureErrorBoundary'
export default function InfrastructureDocsPage() {
return (
<InfrastructureErrorBoundary>
<div className="container mx-auto py-8 px-4">
<DocsDashboard />
</div>
</InfrastructureErrorBoundary>
)
}

View File

@@ -0,0 +1,13 @@
import { DeploymentTimeline } from '@/components/infrastructure/DeploymentTimeline'
import { InfrastructureErrorBoundary } from '@/components/infrastructure/InfrastructureErrorBoundary'
export default function TimelinePage() {
return (
<InfrastructureErrorBoundary>
<div className="container mx-auto py-8 px-4">
<DeploymentTimeline />
</div>
</InfrastructureErrorBoundary>
)
}

View File

@@ -0,0 +1,13 @@
import { NetworkTopologyDocs } from '@/components/infrastructure/NetworkTopologyDocs'
import { InfrastructureErrorBoundary } from '@/components/infrastructure/InfrastructureErrorBoundary'
export default function TopologyPage() {
return (
<InfrastructureErrorBoundary>
<div className="container mx-auto py-8 px-4">
<NetworkTopologyDocs />
</div>
</InfrastructureErrorBoundary>
)
}

View File

@@ -1,4 +1,4 @@
import type { Metadata } from 'next'
import type { Metadata, Viewport } from 'next'
import { Inter } from 'next/font/google'
import './globals.css'
import { Providers } from './providers'
@@ -10,8 +10,19 @@ const inter = Inter({
})
export const metadata: Metadata = {
title: 'Phoenix Sankofa Cloud',
title: {
default: "Sankofa's Phoenix Nexus Cloud",
template: "%s | Sankofa's Phoenix Nexus Cloud",
},
description: 'The sovereign cloud born of fire and ancestral wisdom.',
metadataBase: new URL(process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000'),
}
// Viewport configuration without maximum-scale and user-scalable for accessibility compliance
export const viewport: Viewport = {
width: 'device-width',
initialScale: 1,
// Note: maximum-scale and user-scalable removed per accessibility best practices
}
export default function RootLayout({

View File

@@ -36,7 +36,7 @@ export default function ManifestoPage() {
<header className="border-b border-studio-medium bg-studio-dark">
<div className="mx-auto flex max-w-7xl items-center justify-between px-4 py-4">
<Link href="/" className="text-2xl font-bold text-white">
Phoenix <span className="text-phoenix-fire">Sankofa</span> Cloud
<span className="text-sankofa-gold">Sankofa's</span> Phoenix <span className="text-phoenix-fire">Nexus</span> Cloud
</Link>
<nav className="flex gap-4">
<Link href="/" className="text-gray-400 hover:text-white">
@@ -137,7 +137,10 @@ export default function ManifestoPage() {
This is the Sankofa cycle. This is the Phoenix transformation.
</p>
<p className="text-center text-2xl font-bold text-phoenix-fire">
This is Phoenix Sankofa Cloud.
This is Sankofa.
</p>
<p className="text-center text-2xl font-bold text-phoenix-fire">
This is Sankofa Phoenix.
</p>
</CardContent>
</Card>

View File

@@ -0,0 +1,113 @@
import { PublicLayout } from '@/components/layout/public-layout'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Globe, Star, TrendingUp } from 'lucide-react'
export default function APIMarketplacePage() {
const apis = [
{
id: '1',
name: 'Weather API',
provider: 'WeatherCorp',
description: 'Real-time weather data and forecasts',
rating: 4.7,
requests: '10M+',
category: 'Data',
pricing: 'Free tier available',
},
{
id: '2',
name: 'Payment Gateway',
provider: 'PayFlow',
description: 'Secure payment processing API',
rating: 4.9,
requests: '50M+',
category: 'Payment',
pricing: 'Pay per transaction',
},
{
id: '3',
name: 'AI Image Processing',
provider: 'VisionAI',
description: 'Advanced image recognition and processing',
rating: 4.6,
requests: '5M+',
category: 'AI/ML',
pricing: 'Usage-based',
},
]
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black py-24 px-4">
<div className="mx-auto max-w-7xl">
<div className="mb-12">
<h1 className="mb-4 text-5xl font-bold text-white">API Marketplace</h1>
<p className="text-xl text-gray-400">
Discover and integrate third-party APIs into your applications
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{apis.map((api) => (
<Card key={api.id} className="hover:border-phoenix-fire transition-colors">
<CardHeader>
<div className="flex items-start justify-between mb-2">
<Globe className="h-8 w-8 text-phoenix-fire" />
<span className="px-2 py-1 text-xs bg-studio-dark text-gray-400 rounded">
{api.category}
</span>
</div>
<CardTitle className="text-white">{api.name}</CardTitle>
<CardDescription className="text-gray-400">
by {api.provider}
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm text-gray-300 mb-4">{api.description}</p>
<div className="space-y-2 mb-4">
<div className="flex items-center gap-2 text-sm text-gray-400">
<Star className="h-4 w-4 text-yellow-400 fill-yellow-400" />
<span>{api.rating}</span>
</div>
<div className="flex items-center gap-2 text-sm text-gray-400">
<TrendingUp className="h-4 w-4" />
<span>{api.requests} requests/month</span>
</div>
<p className="text-xs text-gray-500">{api.pricing}</p>
</div>
<div className="flex gap-2">
<Button variant="outline" className="flex-1" asChild>
<Link href={`/marketplace/api/${api.id}`}>
View Docs
</Link>
</Button>
<Button variant="phoenix" asChild>
<Link href={`/marketplace/api/${api.id}/subscribe`}>
Subscribe
</Link>
</Button>
</div>
</CardContent>
</Card>
))}
</div>
<div className="mt-12 text-center">
<h2 className="mb-4 text-2xl font-bold text-white">Publish Your API</h2>
<p className="mb-6 text-gray-400">
Monetize your API and reach developers worldwide
</p>
<Button variant="phoenix" size="lg" asChild>
<Link href="/developers/api/publish">Publish API</Link>
</Button>
</div>
</div>
</div>
</PublicLayout>
)
}

View File

@@ -0,0 +1,238 @@
'use client'
import { useQuery } from '@tanstack/react-query'
import { useParams, useRouter } from 'next/navigation'
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 { ArrowLeft, Trash2, RefreshCw } from 'lucide-react'
async function fetchDeployment(id: string) {
const response = await fetch('/api/graphql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
query: `
query GetDeployment($id: ID!) {
deployment(id: $id) {
id
name
status
deploymentType
region
parameters
outputs
errorMessage
createdAt
startedAt
completedAt
logs(limit: 100) {
id
level
message
createdAt
}
}
}
`,
variables: { id },
}),
})
const data = await response.json()
return data.data?.deployment
}
export default function DeploymentDetailPage() {
const params = useParams()
const router = useRouter()
const id = params.id as string
const { data: deployment, isLoading, refetch } = useQuery({
queryKey: ['deployment', id],
queryFn: () => fetchDeployment(id),
refetchInterval: 5000,
})
if (isLoading) {
return (
<div className="container mx-auto py-8 px-4">
<div className="animate-pulse space-y-4">
<div className="h-8 bg-muted rounded w-1/3" />
<div className="h-64 bg-muted rounded" />
</div>
</div>
)
}
if (!deployment) {
return (
<div className="container mx-auto py-8 px-4">
<Card>
<CardContent className="py-12 text-center">
<p className="text-muted-foreground mb-4">Deployment not found</p>
<Button onClick={() => router.push('/marketplace/deployments')}>
Back to Deployments
</Button>
</CardContent>
</Card>
</div>
)
}
return (
<div className="container mx-auto py-8 px-4">
<div className="mb-6 flex items-center justify-between">
<Button variant="ghost" onClick={() => router.back()}>
<ArrowLeft className="mr-2 h-4 w-4" />
Back
</Button>
<div className="flex gap-2">
<Button variant="outline" onClick={() => refetch()}>
<RefreshCw className="mr-2 h-4 w-4" />
Refresh
</Button>
<Button variant="destructive">
<Trash2 className="mr-2 h-4 w-4" />
Delete
</Button>
</div>
</div>
<div className="mb-6">
<h1 className="text-4xl font-bold mb-2">{deployment.name}</h1>
<div className="flex items-center gap-2">
<Badge>{deployment.status}</Badge>
<Badge variant="outline">{deployment.deploymentType}</Badge>
{deployment.region && (
<Badge variant="outline">Region: {deployment.region}</Badge>
)}
</div>
</div>
<Tabs defaultValue="overview" className="space-y-4">
<TabsList>
<TabsTrigger value="overview">Overview</TabsTrigger>
<TabsTrigger value="logs">Logs</TabsTrigger>
<TabsTrigger value="outputs">Outputs</TabsTrigger>
<TabsTrigger value="parameters">Parameters</TabsTrigger>
</TabsList>
<TabsContent value="overview" className="space-y-4">
<Card>
<CardHeader>
<CardTitle>Deployment Information</CardTitle>
</CardHeader>
<CardContent className="space-y-2">
<div className="flex justify-between">
<span className="text-muted-foreground">Status:</span>
<Badge>{deployment.status}</Badge>
</div>
<div className="flex justify-between">
<span className="text-muted-foreground">Type:</span>
<span>{deployment.deploymentType}</span>
</div>
{deployment.region && (
<div className="flex justify-between">
<span className="text-muted-foreground">Region:</span>
<span>{deployment.region}</span>
</div>
)}
<div className="flex justify-between">
<span className="text-muted-foreground">Created:</span>
<span>{new Date(deployment.createdAt).toLocaleString()}</span>
</div>
{deployment.startedAt && (
<div className="flex justify-between">
<span className="text-muted-foreground">Started:</span>
<span>{new Date(deployment.startedAt).toLocaleString()}</span>
</div>
)}
{deployment.completedAt && (
<div className="flex justify-between">
<span className="text-muted-foreground">Completed:</span>
<span>{new Date(deployment.completedAt).toLocaleString()}</span>
</div>
)}
{deployment.errorMessage && (
<div className="mt-4 p-4 bg-red-50 border border-red-200 rounded">
<p className="text-sm font-medium text-red-800">Error:</p>
<p className="text-sm text-red-600">{deployment.errorMessage}</p>
</div>
)}
</CardContent>
</Card>
</TabsContent>
<TabsContent value="logs">
<Card>
<CardHeader>
<CardTitle>Deployment Logs</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-2 max-h-96 overflow-y-auto">
{deployment.logs && deployment.logs.length > 0 ? (
deployment.logs.map((log: any) => (
<div
key={log.id}
className={`p-2 rounded text-sm font-mono ${
log.level === 'ERROR'
? 'bg-red-50 text-red-800'
: log.level === 'WARN'
? 'bg-yellow-50 text-yellow-800'
: 'bg-gray-50'
}`}
>
<span className="text-muted-foreground">
[{new Date(log.createdAt).toLocaleTimeString()}] [{log.level}]
</span>{' '}
{log.message}
</div>
))
) : (
<p className="text-muted-foreground">No logs available</p>
)}
</div>
</CardContent>
</Card>
</TabsContent>
<TabsContent value="outputs">
<Card>
<CardHeader>
<CardTitle>Deployment Outputs</CardTitle>
</CardHeader>
<CardContent>
{deployment.outputs && Object.keys(deployment.outputs).length > 0 ? (
<pre className="p-4 bg-muted rounded overflow-auto">
{JSON.stringify(deployment.outputs, null, 2)}
</pre>
) : (
<p className="text-muted-foreground">No outputs available</p>
)}
</CardContent>
</Card>
</TabsContent>
<TabsContent value="parameters">
<Card>
<CardHeader>
<CardTitle>Deployment Parameters</CardTitle>
</CardHeader>
<CardContent>
{deployment.parameters && Object.keys(deployment.parameters).length > 0 ? (
<pre className="p-4 bg-muted rounded overflow-auto">
{JSON.stringify(deployment.parameters, null, 2)}
</pre>
) : (
<p className="text-muted-foreground">No parameters available</p>
)}
</CardContent>
</Card>
</TabsContent>
</Tabs>
</div>
)
}

View File

@@ -0,0 +1,145 @@
'use client'
import { useQuery } from '@tanstack/react-query'
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Badge } from '@/components/ui/badge'
import { Clock, CheckCircle, XCircle, Loader } from 'lucide-react'
async function fetchDeployments() {
const response = await fetch('/api/graphql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
query: `
query GetDeployments {
deployments {
id
name
status
deploymentType
region
createdAt
completedAt
}
}
`,
}),
})
const data = await response.json()
return data.data?.deployments || []
}
const STATUS_COLORS: Record<string, string> = {
PENDING: 'bg-yellow-100 text-yellow-800',
PROVISIONING: 'bg-blue-100 text-blue-800',
DEPLOYING: 'bg-blue-100 text-blue-800',
RUNNING: 'bg-green-100 text-green-800',
FAILED: 'bg-red-100 text-red-800',
STOPPED: 'bg-gray-100 text-gray-800',
}
const STATUS_ICONS: Record<string, any> = {
PENDING: Clock,
PROVISIONING: Loader,
DEPLOYING: Loader,
RUNNING: CheckCircle,
FAILED: XCircle,
STOPPED: Clock,
}
export default function DeploymentsPage() {
const { data: deployments = [], isLoading } = useQuery({
queryKey: ['deployments'],
queryFn: fetchDeployments,
refetchInterval: 5000, // Refresh every 5 seconds
})
if (isLoading) {
return (
<div className="container mx-auto py-8 px-4">
<div className="animate-pulse space-y-4">
<div className="h-8 bg-muted rounded w-1/3" />
<div className="h-64 bg-muted rounded" />
</div>
</div>
)
}
return (
<div className="container mx-auto py-8 px-4">
<div className="mb-8 flex items-center justify-between">
<div>
<h1 className="text-4xl font-bold mb-2">Deployments</h1>
<p className="text-muted-foreground">
Monitor and manage your deployments
</p>
</div>
<Link href="/marketplace">
<Button>New Deployment</Button>
</Link>
</div>
{deployments.length === 0 ? (
<Card>
<CardContent className="py-12 text-center">
<p className="text-muted-foreground mb-4">No deployments found</p>
<Link href="/marketplace">
<Button>Browse Marketplace</Button>
</Link>
</CardContent>
</Card>
) : (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{deployments.map((deployment: any) => {
const StatusIcon = STATUS_ICONS[deployment.status] || Clock
return (
<Card key={deployment.id} className="hover:shadow-lg transition-shadow">
<CardHeader>
<div className="flex items-start justify-between">
<CardTitle className="text-xl">
<Link
href={`/marketplace/deployments/${deployment.id}`}
className="hover:underline"
>
{deployment.name}
</Link>
</CardTitle>
<StatusIcon
className={`h-5 w-5 ${
deployment.status === 'RUNNING'
? 'text-green-500'
: deployment.status === 'FAILED'
? 'text-red-500'
: 'text-blue-500'
}`}
/>
</div>
<CardDescription>
{deployment.region && (
<span className="mr-2">Region: {deployment.region}</span>
)}
<span>Type: {deployment.deploymentType}</span>
</CardDescription>
</CardHeader>
<CardContent>
<div className="flex items-center justify-between">
<Badge className={STATUS_COLORS[deployment.status] || ''}>
{deployment.status}
</Badge>
<span className="text-sm text-muted-foreground">
{new Date(deployment.createdAt).toLocaleDateString()}
</span>
</div>
</CardContent>
</Card>
)
})}
</div>
)}
</div>
)
}

View File

@@ -0,0 +1,113 @@
import { PublicLayout } from '@/components/layout/public-layout'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Code, Star, Download, ExternalLink } from 'lucide-react'
export default function DeveloperMarketplacePage() {
const tools = [
{
id: '1',
name: 'Phoenix CLI',
author: 'Sankofa Team',
description: 'Command-line interface for managing Phoenix resources',
rating: 4.9,
downloads: 5000,
category: 'CLI Tools',
language: 'TypeScript',
},
{
id: '2',
name: 'Terraform Provider',
author: 'Community',
description: 'Terraform provider for infrastructure as code',
rating: 4.7,
downloads: 3200,
category: 'IaC',
language: 'Go',
},
{
id: '3',
name: 'Python SDK',
author: 'Sankofa Team',
description: 'Official Python SDK for Phoenix API',
rating: 4.8,
downloads: 2800,
category: 'SDK',
language: 'Python',
},
]
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black py-24 px-4">
<div className="mx-auto max-w-7xl">
<div className="mb-12">
<h1 className="mb-4 text-5xl font-bold text-white">Developer Marketplace</h1>
<p className="text-xl text-gray-400">
Tools, libraries, and integrations built by the community
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{tools.map((tool) => (
<Card key={tool.id} className="hover:border-phoenix-fire transition-colors">
<CardHeader>
<div className="flex items-start justify-between mb-2">
<Code className="h-8 w-8 text-phoenix-fire" />
<span className="px-2 py-1 text-xs bg-studio-dark text-gray-400 rounded">
{tool.category}
</span>
</div>
<CardTitle className="text-white">{tool.name}</CardTitle>
<CardDescription className="text-gray-400">
by {tool.author}
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm text-gray-300 mb-4">{tool.description}</p>
<div className="flex items-center gap-4 mb-4 text-sm text-gray-400">
<div className="flex items-center gap-1">
<Star className="h-4 w-4 text-yellow-400 fill-yellow-400" />
<span>{tool.rating}</span>
</div>
<div className="flex items-center gap-1">
<Download className="h-4 w-4" />
<span>{tool.downloads.toLocaleString()}</span>
</div>
<span className="text-xs">{tool.language}</span>
</div>
<div className="flex gap-2">
<Button variant="outline" className="flex-1" asChild>
<Link href={`/marketplace/developers/${tool.id}`}>
View Details
</Link>
</Button>
<Button variant="phoenix" asChild>
<Link href={`/marketplace/developers/${tool.id}/install`}>
Install
</Link>
</Button>
</div>
</CardContent>
</Card>
))}
</div>
<div className="mt-12 text-center">
<h2 className="mb-4 text-2xl font-bold text-white">Publish Your Tool</h2>
<p className="mb-6 text-gray-400">
Share your tools and libraries with the developer community
</p>
<Button variant="phoenix" size="lg" asChild>
<Link href="/developers/marketplace/publish">Publish Tool</Link>
</Button>
</div>
</div>
</div>
</PublicLayout>
)
}

View File

@@ -0,0 +1,156 @@
'use client'
import { useQuery } from '@tanstack/react-query'
import { useState } from 'react'
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Badge } from '@/components/ui/badge'
import { ProductCard } from '@/components/marketplace/ProductCard'
import { Search, Filter } from 'lucide-react'
const PRODUCT_CATEGORIES = [
{ value: 'COMPUTE', label: 'Compute' },
{ value: 'NETWORK_INFRA', label: 'Network & Infrastructure' },
{ value: 'BLOCKCHAIN_STACK', label: 'Blockchain Stacks' },
{ value: 'BLOCKCHAIN_TOOLS', label: 'Blockchain Tools' },
{ value: 'FINANCIAL_MESSAGING', label: 'Financial Messaging' },
{ value: 'INTERNET_REGISTRY', label: 'Internet Registry' },
{ value: 'AI_LLM_AGENT', label: 'AI/LLM Agent' },
]
async function fetchProducts(filter?: any) {
const queryParams = new URLSearchParams()
if (filter?.category) queryParams.set('category', filter.category)
if (filter?.search) queryParams.set('search', filter.search)
if (filter?.featured !== undefined) queryParams.set('featured', String(filter.featured))
const response = await fetch(`/api/graphql?query=${encodeURIComponent(`
query GetProducts($filter: ProductFilter) {
products(filter: $filter) {
id
name
slug
category
shortDescription
featured
iconUrl
publisher {
displayName
verified
}
averageRating
reviewCount
}
}
`)}&variables=${encodeURIComponent(JSON.stringify({ filter }))}`)
const data = await response.json()
return data.data?.products || []
}
export default function MarketplacePage() {
const [searchQuery, setSearchQuery] = useState('')
const [selectedCategory, setSelectedCategory] = useState<string | undefined>()
const [showFeatured, setShowFeatured] = useState(false)
const filter = {
...(selectedCategory && { category: selectedCategory }),
...(searchQuery && { search: searchQuery }),
...(showFeatured && { featured: true }),
}
const { data: products = [], isLoading } = useQuery({
queryKey: ['marketplace-products', filter],
queryFn: () => fetchProducts(filter),
})
return (
<div className="container mx-auto py-8 px-4">
<div className="mb-8">
<h1 className="text-4xl font-bold mb-2">Phoenix Marketplace</h1>
<p className="text-muted-foreground">
Discover and deploy cloud resources, blockchain stacks, and developer tools
</p>
</div>
{/* Search and Filters */}
<div className="mb-8 space-y-4">
<div className="flex gap-4">
<div className="flex-1 relative">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-muted-foreground h-4 w-4" />
<Input
placeholder="Search products..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="pl-10"
/>
</div>
<Button
variant={showFeatured ? 'default' : 'outline'}
onClick={() => setShowFeatured(!showFeatured)}
>
<Filter className="mr-2 h-4 w-4" />
Featured Only
</Button>
</div>
{/* Category Filters */}
<div className="flex flex-wrap gap-2">
<Button
variant={!selectedCategory ? 'default' : 'outline'}
size="sm"
onClick={() => setSelectedCategory(undefined)}
>
All Categories
</Button>
{PRODUCT_CATEGORIES.map((category) => (
<Button
key={category.value}
variant={selectedCategory === category.value ? 'default' : 'outline'}
size="sm"
onClick={() =>
setSelectedCategory(
selectedCategory === category.value ? undefined : category.value
)
}
>
{category.label}
</Button>
))}
</div>
</div>
{/* Products Grid */}
{isLoading ? (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{[1, 2, 3, 4, 5, 6].map((i) => (
<Card key={i} className="animate-pulse">
<CardHeader>
<div className="h-4 bg-muted rounded w-3/4 mb-2" />
<div className="h-3 bg-muted rounded w-1/2" />
</CardHeader>
<CardContent>
<div className="h-20 bg-muted rounded" />
</CardContent>
</Card>
))}
</div>
) : products.length === 0 ? (
<Card>
<CardContent className="py-12 text-center">
<p className="text-muted-foreground">No products found. Try adjusting your filters.</p>
</CardContent>
</Card>
) : (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{products.map((product: any) => (
<ProductCard key={product.id} product={product} />
))}
</div>
)}
</div>
)
}

View File

@@ -0,0 +1,112 @@
import { PublicLayout } from '@/components/layout/public-layout'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Star, Download, ExternalLink } from 'lucide-react'
export default function PartnerMarketplacePage() {
const solutions = [
{
id: '1',
name: 'Enterprise Security Suite',
partner: 'SecureCorp',
description: 'Comprehensive security solution for enterprise deployments',
rating: 4.8,
downloads: 1250,
category: 'Security',
logo: '🔒',
},
{
id: '2',
name: 'Data Analytics Platform',
partner: 'DataFlow Inc',
description: 'Advanced analytics and reporting for cloud infrastructure',
rating: 4.6,
downloads: 890,
category: 'Analytics',
logo: '📊',
},
{
id: '3',
name: 'DevOps Automation Tools',
partner: 'AutoDev Solutions',
description: 'Automated CI/CD pipelines and deployment workflows',
rating: 4.9,
downloads: 2100,
category: 'DevOps',
logo: '⚙️',
},
]
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black py-24 px-4">
<div className="mx-auto max-w-7xl">
<div className="mb-12">
<h1 className="mb-4 text-5xl font-bold text-white">Partner Marketplace</h1>
<p className="text-xl text-gray-400">
Discover solutions from our certified partners
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{solutions.map((solution) => (
<Card key={solution.id} className="hover:border-phoenix-fire transition-colors">
<CardHeader>
<div className="flex items-start justify-between mb-2">
<div className="text-4xl">{solution.logo}</div>
<span className="px-2 py-1 text-xs bg-studio-dark text-gray-400 rounded">
{solution.category}
</span>
</div>
<CardTitle className="text-white">{solution.name}</CardTitle>
<CardDescription className="text-gray-400">
by {solution.partner}
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm text-gray-300 mb-4">{solution.description}</p>
<div className="flex items-center gap-4 mb-4 text-sm text-gray-400">
<div className="flex items-center gap-1">
<Star className="h-4 w-4 text-yellow-400 fill-yellow-400" />
<span>{solution.rating}</span>
</div>
<div className="flex items-center gap-1">
<Download className="h-4 w-4" />
<span>{solution.downloads.toLocaleString()}</span>
</div>
</div>
<div className="flex gap-2">
<Button variant="outline" className="flex-1" asChild>
<Link href={`/marketplace/partners/${solution.id}`}>
View Details
</Link>
</Button>
<Button variant="phoenix" asChild>
<Link href={`/marketplace/partners/${solution.id}/install`}>
Install
</Link>
</Button>
</div>
</CardContent>
</Card>
))}
</div>
<div className="mt-12 text-center">
<h2 className="mb-4 text-2xl font-bold text-white">Become a Partner</h2>
<p className="mb-6 text-gray-400">
List your solution in our marketplace and reach thousands of customers
</p>
<Button variant="phoenix" size="lg" asChild>
<Link href="/partners/register">Register as Partner</Link>
</Button>
</div>
</div>
</div>
</PublicLayout>
)
}

View File

@@ -0,0 +1,291 @@
'use client'
import { useState } from 'react'
import { useQuery } from '@tanstack/react-query'
import { useParams, useRouter } from 'next/navigation'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Badge } from '@/components/ui/badge'
import { DeploymentWizard } from '@/components/marketplace/DeploymentWizard'
import { Star, Verified, ArrowLeft, ExternalLink } from 'lucide-react'
import Link from 'next/link'
async function fetchProduct(slug: string) {
const response = await fetch(`/api/graphql?query=${encodeURIComponent(`
query GetProduct($slug: String!) {
productBySlug(slug: $slug) {
id
name
slug
category
description
shortDescription
featured
iconUrl
documentationUrl
supportUrl
metadata
tags
publisher {
id
name
displayName
verified
websiteUrl
logoUrl
}
versions {
id
version
isLatest
status
releasedAt
}
pricing {
id
pricingType
basePrice
currency
billingPeriod
}
averageRating
reviewCount
}
}
`)}&variables=${encodeURIComponent(JSON.stringify({ slug }))}`)
const data = await response.json()
return data.data?.productBySlug
}
export default function ProductDetailPage() {
const params = useParams()
const router = useRouter()
const slug = params.slug as string
const [showDeployWizard, setShowDeployWizard] = useState(false)
const { data: product, isLoading } = useQuery({
queryKey: ['product', slug],
queryFn: () => fetchProduct(slug),
})
if (isLoading) {
return (
<div className="container mx-auto py-8 px-4">
<div className="animate-pulse space-y-4">
<div className="h-8 bg-muted rounded w-1/3" />
<div className="h-4 bg-muted rounded w-1/2" />
<div className="h-64 bg-muted rounded" />
</div>
</div>
)
}
if (!product) {
return (
<div className="container mx-auto py-8 px-4">
<Card>
<CardContent className="py-12 text-center">
<p className="text-muted-foreground mb-4">Product not found</p>
<Link href="/marketplace">
<Button>Back to Marketplace</Button>
</Link>
</CardContent>
</Card>
</div>
)
}
return (
<div className="container mx-auto py-8 px-4">
<Button
variant="ghost"
onClick={() => router.back()}
className="mb-6"
>
<ArrowLeft className="mr-2 h-4 w-4" />
Back
</Button>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
{/* Main Content */}
<div className="lg:col-span-2 space-y-6">
{/* Header */}
<div>
<div className="flex items-start gap-4 mb-4">
{product.iconUrl && (
<img
src={product.iconUrl}
alt={product.name}
className="w-20 h-20 rounded-lg object-cover"
/>
)}
<div className="flex-1">
<h1 className="text-4xl font-bold mb-2">{product.name}</h1>
<div className="flex items-center gap-2 text-muted-foreground mb-2">
{product.publisher && (
<>
<span>by {product.publisher.displayName}</span>
{product.publisher.verified && (
<Verified className="h-4 w-4 text-blue-500" />
)}
</>
)}
</div>
<div className="flex items-center gap-2 flex-wrap">
<Badge variant="secondary">{product.category}</Badge>
{product.featured && <Badge>Featured</Badge>}
{product.averageRating !== undefined && product.averageRating > 0 && (
<div className="flex items-center gap-1">
<Star className="h-4 w-4 fill-yellow-400 text-yellow-400" />
<span className="text-sm font-medium">
{product.averageRating.toFixed(1)}
</span>
{product.reviewCount !== undefined && product.reviewCount > 0 && (
<span className="text-sm text-muted-foreground">
({product.reviewCount} reviews)
</span>
)}
</div>
)}
</div>
</div>
</div>
</div>
{/* Description */}
<Card>
<CardHeader>
<CardTitle>Description</CardTitle>
</CardHeader>
<CardContent>
<p className="text-muted-foreground whitespace-pre-wrap">
{product.description || product.shortDescription || 'No description available'}
</p>
</CardContent>
</Card>
{/* Versions */}
{product.versions && product.versions.length > 0 && (
<Card>
<CardHeader>
<CardTitle>Versions</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-2">
{product.versions.map((version: any) => (
<div
key={version.id}
className="flex items-center justify-between p-2 border rounded"
>
<div>
<span className="font-medium">v{version.version}</span>
{version.isLatest && (
<Badge variant="outline" className="ml-2">
Latest
</Badge>
)}
</div>
{version.releasedAt && (
<span className="text-sm text-muted-foreground">
{new Date(version.releasedAt).toLocaleDateString()}
</span>
)}
</div>
))}
</div>
</CardContent>
</Card>
)}
{/* Tags */}
{product.tags && product.tags.length > 0 && (
<Card>
<CardHeader>
<CardTitle>Tags</CardTitle>
</CardHeader>
<CardContent>
<div className="flex flex-wrap gap-2">
{product.tags.map((tag: string) => (
<Badge key={tag} variant="outline">
{tag}
</Badge>
))}
</div>
</CardContent>
</Card>
)}
</div>
{/* Sidebar */}
<div className="space-y-6">
{/* Pricing */}
{product.pricing && (
<Card>
<CardHeader>
<CardTitle>Pricing</CardTitle>
</CardHeader>
<CardContent>
{product.pricing.pricingType === 'FREE' ? (
<div className="text-2xl font-bold">Free</div>
) : (
<div>
{product.pricing.basePrice !== null && (
<div className="text-2xl font-bold">
${product.pricing.basePrice}
{product.pricing.billingPeriod && (
<span className="text-sm font-normal text-muted-foreground">
/{product.pricing.billingPeriod.toLowerCase()}
</span>
)}
</div>
)}
<div className="text-sm text-muted-foreground mt-1">
{product.pricing.pricingType}
</div>
</div>
)}
</CardContent>
</Card>
)}
{/* Actions */}
<Card>
<CardContent className="pt-6">
<Button
className="w-full mb-2"
onClick={() => setShowDeployWizard(true)}
>
Deploy Now
</Button>
{product.documentationUrl && (
<Link href={product.documentationUrl} target="_blank">
<Button variant="outline" className="w-full mb-2">
<ExternalLink className="mr-2 h-4 w-4" />
Documentation
</Button>
</Link>
)}
{product.supportUrl && (
<Link href={product.supportUrl} target="_blank">
<Button variant="outline" className="w-full">
Get Support
</Button>
</Link>
)}
</CardContent>
</Card>
</div>
</div>
{/* Deployment Wizard Modal */}
{showDeployWizard && (
<DeploymentWizard
product={product}
onClose={() => setShowDeployWizard(false)}
/>
)}
</div>
)
}

View File

@@ -1,19 +1,24 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { PublicLayout } from '@/components/layout/public-layout'
export default function Home() {
return (
<main className="min-h-screen bg-studio-black">
<PublicLayout>
<div className="min-h-screen bg-studio-black">
{/* Hero Section */}
<section className="relative flex min-h-screen flex-col items-center justify-center overflow-hidden px-4">
<div className="absolute inset-0 bg-gradient-to-br from-phoenix-fire/20 via-transparent to-sankofa-gold/20" />
<div className="relative z-10 max-w-4xl text-center">
<h1 className="mb-6 text-5xl font-bold tracking-tight text-white md:text-7xl">
<span className="bg-gradient-to-r from-phoenix-fire to-sankofa-gold bg-clip-text text-transparent">
Sankofa's
</span>{' '}
Phoenix{' '}
<span className="bg-gradient-to-r from-phoenix-fire to-sankofa-gold bg-clip-text text-transparent">
Sankofa
Nexus
</span>{' '}
Cloud
</h1>
@@ -104,7 +109,8 @@ export default function Home() {
</Link>
</div>
</section>
</main>
</div>
</PublicLayout>
)
}

158
src/app/partners/page.tsx Normal file
View File

@@ -0,0 +1,158 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { PublicLayout } from '@/components/layout/public-layout'
import { Handshake, TrendingUp, Users, Award, Zap, BookOpen } from 'lucide-react'
export default function PartnersPage() {
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black">
{/* Hero */}
<section className="relative border-b border-studio-medium bg-gradient-to-br from-phoenix-fire/10 via-transparent to-sankofa-gold/10 py-24 px-4">
<div className="mx-auto max-w-4xl text-center">
<h1 className="mb-6 text-5xl font-bold text-white md:text-6xl">
Partner Program
</h1>
<p className="mb-8 text-xl text-gray-300">
Build, sell, and grow with Sankofa's Phoenix Nexus Cloud
</p>
<div className="flex flex-col gap-4 sm:flex-row sm:justify-center">
<Button variant="phoenix" size="lg" asChild>
<Link href="/portal/partners">Join as Partner</Link>
</Button>
<Button variant="outline" size="lg" asChild>
<Link href="/partners/benefits">View Benefits</Link>
</Button>
</div>
</div>
</section>
{/* Partner Benefits */}
<section className="py-24 px-4">
<div className="mx-auto max-w-6xl">
<h2 className="mb-12 text-center text-4xl font-bold text-white">
Partner Benefits
</h2>
<div className="grid gap-8 md:grid-cols-3">
<Card>
<CardHeader>
<TrendingUp className="mb-2 h-10 w-10 text-phoenix-fire" />
<CardTitle>Revenue Opportunities</CardTitle>
<CardDescription>
Competitive margins and co-sell opportunities
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li> Attractive partner margins</li>
<li> Co-sell deal registration</li>
<li> Recurring revenue streams</li>
<li> Marketing development funds</li>
</ul>
</CardContent>
</Card>
<Card>
<CardHeader>
<Zap className="mb-2 h-10 w-10 text-sankofa-gold" />
<CardTitle>Technical Enablement</CardTitle>
<CardDescription>
Comprehensive training and support resources
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li> Technical onboarding programs</li>
<li> Solution architecture support</li>
<li> Dedicated partner engineering</li>
<li> Test environments and sandboxes</li>
</ul>
</CardContent>
</Card>
<Card>
<CardHeader>
<Users className="mb-2 h-10 w-10 text-neon-cyan" />
<CardTitle>Go-to-Market Support</CardTitle>
<CardDescription>
Marketing resources and co-marketing opportunities
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li> Co-marketing campaigns</li>
<li> Partner portal access</li>
<li> Sales enablement materials</li>
<li> Joint customer events</li>
</ul>
</CardContent>
</Card>
</div>
</div>
</section>
{/* Partner Types */}
<section className="border-t border-studio-medium bg-studio-dark py-24 px-4">
<div className="mx-auto max-w-6xl">
<h2 className="mb-12 text-center text-4xl font-bold text-white">
Partner Types
</h2>
<div className="grid gap-8 md:grid-cols-2">
<div>
<Handshake className="mb-4 h-8 w-8 text-phoenix-fire" />
<h3 className="mb-4 text-2xl font-bold text-white">Solution Partners</h3>
<p className="mb-4 text-gray-300">
Build and deliver solutions on Phoenix Nexus Cloud. Integrate your
products and services with our platform.
</p>
<ul className="space-y-2 text-sm text-gray-400">
<li> Solution marketplace listing</li>
<li> Technical integration support</li>
<li> Joint go-to-market</li>
<li> Solution certification</li>
</ul>
</div>
<div>
<Award className="mb-4 h-8 w-8 text-sankofa-gold" />
<h3 className="mb-4 text-2xl font-bold text-white">Reseller Partners</h3>
<p className="mb-4 text-gray-300">
Sell Phoenix Nexus Cloud to your customers. Leverage our infrastructure
to deliver value to your client base.
</p>
<ul className="space-y-2 text-sm text-gray-400">
<li> Reseller discounts</li>
<li> Deal registration</li>
<li> Sales training</li>
<li> Customer support tools</li>
</ul>
</div>
</div>
</div>
</section>
{/* CTA */}
<section className="py-24 px-4">
<div className="mx-auto max-w-4xl text-center">
<h2 className="mb-6 text-4xl font-bold text-white">
Ready to Partner With Us?
</h2>
<p className="mb-8 text-xl text-gray-400">
Join our partner program and grow your business
</p>
<div className="flex flex-col gap-4 sm:flex-row sm:justify-center">
<Button variant="phoenix" size="lg" asChild>
<Link href="/portal/partners">Access Partner Portal</Link>
</Button>
<Button variant="outline" size="lg" asChild>
<Link href="/support">Contact Partner Team</Link>
</Button>
</div>
</div>
</section>
</div>
</PublicLayout>
)
}

View File

@@ -0,0 +1,161 @@
'use client'
import { useState } from 'react'
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Header } from '@/components/layout/header'
import { Users, Building2, CreditCard, Settings, Shield, BarChart3 } from 'lucide-react'
export default function AdminPortalPage() {
return (
<>
<Header />
<main className="min-h-screen bg-studio-black">
<div className="container mx-auto py-12 px-4">
<div className="mb-8">
<h1 className="text-4xl font-bold text-white">Tenant Administration</h1>
<p className="mt-2 text-gray-400">
Manage your organization, users, permissions, and billing
</p>
</div>
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
<Card className="border-studio-medium hover:border-phoenix-fire/50 transition-colors">
<CardHeader>
<div className="flex items-center gap-3">
<div className="rounded-lg bg-phoenix-fire/20 p-3">
<Building2 className="h-6 w-6 text-phoenix-fire" />
</div>
<div>
<CardTitle>Organization</CardTitle>
<CardDescription>Manage organization settings</CardDescription>
</div>
</div>
</CardHeader>
<CardContent>
<p className="mb-4 text-sm text-gray-400">
Configure organization details, domains, and branding
</p>
<Button variant="outline" className="w-full" asChild>
<Link href="/portal/admin/organization">Manage Organization</Link>
</Button>
</CardContent>
</Card>
<Card className="border-studio-medium hover:border-phoenix-fire/50 transition-colors">
<CardHeader>
<div className="flex items-center gap-3">
<div className="rounded-lg bg-sankofa-gold/20 p-3">
<Users className="h-6 w-6 text-sankofa-gold" />
</div>
<div>
<CardTitle>Users & Roles</CardTitle>
<CardDescription>Manage team members</CardDescription>
</div>
</div>
</CardHeader>
<CardContent>
<p className="mb-4 text-sm text-gray-400">
Invite users, assign roles, and manage permissions
</p>
<Button variant="outline" className="w-full" asChild>
<Link href="/portal/admin/users">Manage Users</Link>
</Button>
</CardContent>
</Card>
<Card className="border-studio-medium hover:border-phoenix-fire/50 transition-colors">
<CardHeader>
<div className="flex items-center gap-3">
<div className="rounded-lg bg-neon-cyan/20 p-3">
<Shield className="h-6 w-6 text-neon-cyan" />
</div>
<div>
<CardTitle>Permissions</CardTitle>
<CardDescription>Configure access controls</CardDescription>
</div>
</div>
</CardHeader>
<CardContent>
<p className="mb-4 text-sm text-gray-400">
Set up role-based access control and permissions
</p>
<Button variant="outline" className="w-full" asChild>
<Link href="/portal/admin/permissions">Manage Permissions</Link>
</Button>
</CardContent>
</Card>
<Card className="border-studio-medium hover:border-phoenix-fire/50 transition-colors">
<CardHeader>
<div className="flex items-center gap-3">
<div className="rounded-lg bg-phoenix-fire/20 p-3">
<CreditCard className="h-6 w-6 text-phoenix-fire" />
</div>
<div>
<CardTitle>Billing</CardTitle>
<CardDescription>Manage subscriptions</CardDescription>
</div>
</div>
</CardHeader>
<CardContent>
<p className="mb-4 text-sm text-gray-400">
View invoices, manage payment methods, and billing settings
</p>
<Button variant="outline" className="w-full" asChild>
<Link href="/portal/admin/billing">Manage Billing</Link>
</Button>
</CardContent>
</Card>
<Card className="border-studio-medium hover:border-phoenix-fire/50 transition-colors">
<CardHeader>
<div className="flex items-center gap-3">
<div className="rounded-lg bg-sankofa-gold/20 p-3">
<BarChart3 className="h-6 w-6 text-sankofa-gold" />
</div>
<div>
<CardTitle>Usage & Analytics</CardTitle>
<CardDescription>Monitor resource usage</CardDescription>
</div>
</div>
</CardHeader>
<CardContent>
<p className="mb-4 text-sm text-gray-400">
Track usage, costs, and performance metrics
</p>
<Button variant="outline" className="w-full" asChild>
<Link href="/portal/admin/analytics">View Analytics</Link>
</Button>
</CardContent>
</Card>
<Card className="border-studio-medium hover:border-phoenix-fire/50 transition-colors">
<CardHeader>
<div className="flex items-center gap-3">
<div className="rounded-lg bg-neon-cyan/20 p-3">
<Settings className="h-6 w-6 text-neon-cyan" />
</div>
<div>
<CardTitle>Settings</CardTitle>
<CardDescription>Configure preferences</CardDescription>
</div>
</div>
</CardHeader>
<CardContent>
<p className="mb-4 text-sm text-gray-400">
Manage security, notifications, and integrations
</p>
<Button variant="outline" className="w-full" asChild>
<Link href="/portal/admin/settings">Manage Settings</Link>
</Button>
</CardContent>
</Card>
</div>
</div>
</main>
</>
)
}

View File

@@ -0,0 +1,58 @@
'use client'
import { useEffect } from 'react'
import { useRouter, useSearchParams } from 'next/navigation'
import { handleSSOCallback, getPortalForRole } from '@/lib/auth/sso'
export default function SSOCallbackPage() {
const router = useRouter()
const searchParams = useSearchParams()
useEffect(() => {
const code = searchParams?.get('code')
const state = searchParams?.get('state')
if (code && state) {
const keycloakUrl = process.env.NEXT_PUBLIC_KEYCLOAK_URL || 'https://keycloak.sankofa.nexus'
const realm = process.env.NEXT_PUBLIC_KEYCLOAK_REALM || 'sankofa'
const clientId = process.env.NEXT_PUBLIC_KEYCLOAK_CLIENT_ID || 'phoenix-portal'
const redirectUri = `${window.location.origin}/portal/callback`
handleSSOCallback(code, state, {
keycloakUrl,
realm,
clientId,
redirectUri,
})
.then(({ token, user, role }) => {
// Store token
if (typeof window !== 'undefined') {
sessionStorage.setItem('auth_token', token)
localStorage.setItem('phoenix_token', token)
localStorage.setItem('phoenix_user', JSON.stringify(user))
}
// Route to appropriate portal
const portal = getPortalForRole(role)
router.push(portal)
})
.catch((error) => {
console.error('SSO callback error:', error)
router.push('/portal/signin?error=sso_failed')
})
} else {
// No code/state, redirect to sign in
router.push('/portal/signin')
}
}, [searchParams, router])
return (
<div className="flex min-h-screen items-center justify-center bg-studio-black">
<div className="text-center">
<div className="mb-4 inline-block h-8 w-8 animate-spin rounded-full border-4 border-phoenix-fire border-t-transparent" />
<p className="text-gray-400">Completing sign in...</p>
</div>
</div>
)
}

View File

@@ -0,0 +1,394 @@
'use client'
import { useState, useEffect } from 'react'
import Link from 'next/link'
import { useQuery, useMutation } from '@apollo/client'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Header } from '@/components/layout/header'
import { Terminal, Plus, Trash2, Play, Square, RefreshCw, Loader2 } from 'lucide-react'
import { Badge } from '@/components/ui/badge'
import {
GET_TEST_ENVIRONMENTS,
CREATE_TEST_ENVIRONMENT,
START_TEST_ENVIRONMENT,
STOP_TEST_ENVIRONMENT,
DELETE_TEST_ENVIRONMENT,
} from '@/lib/graphql/queries/test-environments'
interface Environment {
id: string
name: string
status: 'RUNNING' | 'STOPPED' | 'PROVISIONING' | 'ERROR' | 'DELETING'
region: string
resources: {
vms: number
storage: string
network: string
}
created: string
expires?: string
}
export default function EnvironmentsPage() {
const [showCreate, setShowCreate] = useState(false)
const [newEnvName, setNewEnvName] = useState('')
const [newEnvRegion, setNewEnvRegion] = useState('us-east-1')
// Fetch test environments
const { data, loading, error, refetch } = useQuery(GET_TEST_ENVIRONMENTS, {
onCompleted: (data) => {
// Data is handled in the component
},
onError: (error) => {
console.error('Error fetching test environments:', error)
},
})
// Create environment mutation
const [createEnvironment, { loading: creating }] = useMutation(CREATE_TEST_ENVIRONMENT, {
onCompleted: () => {
setNewEnvName('')
setNewEnvRegion('us-east-1')
setShowCreate(false)
refetch()
},
onError: (error) => {
console.error('Error creating environment:', error)
alert('Failed to create environment: ' + error.message)
},
})
// Start environment mutation
const [startEnvironment, { loading: starting }] = useMutation(START_TEST_ENVIRONMENT, {
onCompleted: () => {
refetch()
},
onError: (error) => {
console.error('Error starting environment:', error)
alert('Failed to start environment: ' + error.message)
},
})
// Stop environment mutation
const [stopEnvironment, { loading: stopping }] = useMutation(STOP_TEST_ENVIRONMENT, {
onCompleted: () => {
refetch()
},
onError: (error) => {
console.error('Error stopping environment:', error)
alert('Failed to stop environment: ' + error.message)
},
})
// Delete environment mutation
const [deleteEnvironment, { loading: deleting }] = useMutation(DELETE_TEST_ENVIRONMENT, {
onCompleted: () => {
refetch()
},
onError: (error) => {
console.error('Error deleting environment:', error)
alert('Failed to delete environment: ' + error.message)
},
})
const environments: Environment[] = data?.testEnvironments?.map((env: any) => ({
id: env.id,
name: env.name,
status: env.status,
region: env.region,
resources: env.resources,
created: new Date(env.createdAt).toLocaleDateString(),
expires: env.expiresAt ? new Date(env.expiresAt).toLocaleDateString() : undefined,
})) || []
const handleCreate = () => {
if (!newEnvName.trim()) return
createEnvironment({
variables: {
input: {
name: newEnvName,
region: newEnvRegion,
resources: {
vms: 1,
storage: '20 GB',
network: '10.0.0.0/16',
},
},
},
})
}
const handleStart = (id: string) => {
startEnvironment({ variables: { id } })
}
const handleStop = (id: string) => {
stopEnvironment({ variables: { id } })
}
const handleDelete = (id: string) => {
if (confirm('Are you sure you want to delete this environment? All data will be lost.')) {
deleteEnvironment({ variables: { id } })
}
}
const getStatusColor = (status: string) => {
switch (status) {
case 'RUNNING':
return 'bg-green-500'
case 'STOPPED':
return 'bg-gray-500'
case 'PROVISIONING':
return 'bg-yellow-500'
case 'ERROR':
return 'bg-red-500'
default:
return 'bg-gray-500'
}
}
if (loading) {
return (
<>
<Header />
<main className="min-h-screen bg-studio-black flex items-center justify-center">
<Loader2 className="h-8 w-8 animate-spin text-phoenix-fire" />
</main>
</>
)
}
return (
<>
<Header />
<main className="min-h-screen bg-studio-black">
<div className="container mx-auto py-12 px-4">
<div className="mb-8 flex items-center justify-between">
<div>
<h1 className="text-4xl font-bold text-white">Test Environments</h1>
<p className="mt-2 text-gray-400">
Provision and manage sandbox environments for testing
</p>
</div>
<Button
variant="phoenix"
onClick={() => setShowCreate(!showCreate)}
disabled={creating}
>
<Plus className="mr-2 h-4 w-4" />
Create Environment
</Button>
</div>
{error && (
<Card className="mb-8 border-red-500/50">
<CardContent className="py-4">
<p className="text-red-500">
Error loading environments: {error.message}
</p>
</CardContent>
</Card>
)}
{showCreate && (
<Card className="mb-8 border-phoenix-fire/50">
<CardHeader>
<CardTitle>Create New Test Environment</CardTitle>
<CardDescription>
Provision a new sandbox environment for testing
</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">
Environment Name
</label>
<input
type="text"
value={newEnvName}
onChange={(e) => setNewEnvName(e.target.value)}
placeholder="e.g., Development Sandbox"
className="w-full rounded bg-studio-dark px-4 py-2 text-white border border-studio-medium"
disabled={creating}
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">
Region
</label>
<select
value={newEnvRegion}
onChange={(e) => setNewEnvRegion(e.target.value)}
className="w-full rounded bg-studio-dark px-4 py-2 text-white border border-studio-medium"
disabled={creating}
>
<option value="us-east-1">US East (N. Virginia)</option>
<option value="us-west-2">US West (Oregon)</option>
<option value="eu-west-1">EU (Ireland)</option>
<option value="ap-southeast-1">Asia Pacific (Singapore)</option>
</select>
</div>
<div className="flex gap-2">
<Button
onClick={handleCreate}
disabled={!newEnvName.trim() || creating}
>
{creating ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Creating...
</>
) : (
'Create Environment'
)}
</Button>
<Button
variant="outline"
onClick={() => setShowCreate(false)}
disabled={creating}
>
Cancel
</Button>
</div>
</div>
</CardContent>
</Card>
)}
{environments.length === 0 && !loading ? (
<Card>
<CardContent className="py-12 text-center">
<Terminal className="mx-auto mb-4 h-12 w-12 text-gray-400" />
<h3 className="mb-2 text-lg font-semibold text-white">No Environments</h3>
<p className="mb-4 text-gray-400">
Create a test environment to start developing
</p>
<Button variant="phoenix" onClick={() => setShowCreate(true)}>
<Plus className="mr-2 h-4 w-4" />
Create Environment
</Button>
</CardContent>
</Card>
) : (
<div className="grid gap-6 md:grid-cols-2">
{environments.map((env) => (
<Card key={env.id}>
<CardHeader>
<div className="flex items-center justify-between">
<div>
<CardTitle className="flex items-center gap-2">
<Terminal className="h-5 w-5 text-sankofa-gold" />
{env.name}
</CardTitle>
<CardDescription className="mt-1">
{env.region} Created {env.created}
</CardDescription>
</div>
<div className="flex items-center gap-2">
<div className={`h-3 w-3 rounded-full ${getStatusColor(env.status)}`} />
<Badge variant="outline">{env.status}</Badge>
</div>
</div>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div>
<h4 className="mb-2 text-sm font-semibold text-gray-400">Resources</h4>
<div className="grid grid-cols-3 gap-2 text-sm">
<div>
<div className="text-gray-500">VMs</div>
<div className="font-semibold text-white">{env.resources.vms}</div>
</div>
<div>
<div className="text-gray-500">Storage</div>
<div className="font-semibold text-white">{env.resources.storage}</div>
</div>
<div>
<div className="text-gray-500">Network</div>
<div className="font-semibold text-white">{env.resources.network}</div>
</div>
</div>
</div>
{env.expires && (
<div className="rounded bg-yellow-500/10 px-3 py-2 text-sm text-yellow-500">
Expires: {env.expires}
</div>
)}
<div className="flex gap-2">
{env.status === 'STOPPED' ? (
<Button
variant="outline"
size="sm"
onClick={() => handleStart(env.id)}
disabled={starting}
>
{starting ? (
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
) : (
<Play className="mr-2 h-4 w-4" />
)}
Start
</Button>
) : env.status === 'RUNNING' ? (
<Button
variant="outline"
size="sm"
onClick={() => handleStop(env.id)}
disabled={stopping}
>
{stopping ? (
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
) : (
<Square className="mr-2 h-4 w-4" />
)}
Stop
</Button>
) : env.status === 'PROVISIONING' ? (
<Button variant="outline" size="sm" disabled>
<RefreshCw className="mr-2 h-4 w-4 animate-spin" />
Provisioning...
</Button>
) : null}
<Button
variant="outline"
size="sm"
onClick={() => handleDelete(env.id)}
disabled={deleting || env.status === 'PROVISIONING'}
>
{deleting ? (
<Loader2 className="h-4 w-4 animate-spin" />
) : (
<Trash2 className="h-4 w-4" />
)}
</Button>
</div>
</div>
</CardContent>
</Card>
))}
</div>
)}
<Card className="mt-8 border-studio-medium">
<CardHeader>
<CardTitle>About Test Environments</CardTitle>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li> Environments are automatically cleaned up after 30 days</li>
<li> Free tier includes 2 environments with basic resources</li>
<li> All data is isolated and secure</li>
<li> Environments can be started/stopped on demand</li>
</ul>
</CardContent>
</Card>
</div>
</main>
</>
)
}

View File

@@ -0,0 +1,359 @@
'use client'
import { useState, useEffect } from 'react'
import Link from 'next/link'
import { useQuery, useMutation } from '@apollo/client'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Header } from '@/components/layout/header'
import { Key, Plus, Trash2, Eye, EyeOff, Copy, CheckCircle, Loader2 } from 'lucide-react'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import {
GET_API_KEYS,
CREATE_API_KEY,
REVOKE_API_KEY,
} from '@/lib/graphql/queries/api-keys'
interface ApiKey {
id: string
name: string
keyPrefix: string
created: string
lastUsed: string
permissions: string[]
masked: boolean
fullKey?: string // Only available immediately after creation
}
export default function ApiKeysPage() {
const [keys, setKeys] = useState<ApiKey[]>([])
const [showCreate, setShowCreate] = useState(false)
const [newKeyName, setNewKeyName] = useState('')
const [copiedId, setCopiedId] = useState<string | null>(null)
const [newlyCreatedKey, setNewlyCreatedKey] = useState<string | null>(null)
// Fetch API keys
const { data, loading, error, refetch } = useQuery(GET_API_KEYS, {
onCompleted: (data) => {
if (data?.apiKeys) {
setKeys(
data.apiKeys.map((key: any) => ({
id: key.id,
name: key.name,
keyPrefix: key.keyPrefix,
key: `${key.keyPrefix}...`,
created: new Date(key.createdAt).toLocaleDateString(),
lastUsed: key.lastUsedAt
? new Date(key.lastUsedAt).toLocaleDateString()
: 'Never',
permissions: key.permissions || [],
masked: true,
}))
)
}
},
onError: (error) => {
console.error('Error fetching API keys:', error)
},
})
// Create API key mutation
const [createApiKey, { loading: creating }] = useMutation(CREATE_API_KEY, {
onCompleted: (data) => {
if (data?.createApiKey) {
const newKey = data.createApiKey
setNewlyCreatedKey(newKey.key)
setKeys([
{
id: newKey.id,
name: newKey.name,
keyPrefix: newKey.key.substring(0, 12),
key: newKey.key,
created: new Date(newKey.createdAt).toLocaleDateString(),
lastUsed: 'Never',
permissions: ['read', 'write'],
masked: false,
fullKey: newKey.key,
},
...keys,
])
setNewKeyName('')
setShowCreate(false)
// Refetch to get updated list
refetch()
}
},
onError: (error) => {
console.error('Error creating API key:', error)
alert('Failed to create API key: ' + error.message)
},
})
// Revoke API key mutation
const [revokeApiKey, { loading: revoking }] = useMutation(REVOKE_API_KEY, {
onCompleted: () => {
refetch()
},
onError: (error) => {
console.error('Error revoking API key:', error)
alert('Failed to revoke API key: ' + error.message)
},
})
const handleCreateKey = () => {
if (!newKeyName.trim()) return
createApiKey({
variables: {
input: {
name: newKeyName,
permissions: ['read', 'write'],
},
},
})
}
const handleDeleteKey = (id: string) => {
if (confirm('Are you sure you want to revoke this API key? It will no longer work.')) {
revokeApiKey({
variables: { id },
})
}
}
const toggleMask = (id: string) => {
setKeys(keys.map((k) => (k.id === id ? { ...k, masked: !k.masked } : k)))
}
const copyKey = (key: string, id: string) => {
navigator.clipboard.writeText(key)
setCopiedId(id)
setTimeout(() => setCopiedId(null), 2000)
}
if (loading) {
return (
<>
<Header />
<main className="min-h-screen bg-studio-black flex items-center justify-center">
<Loader2 className="h-8 w-8 animate-spin text-phoenix-fire" />
</main>
</>
)
}
return (
<>
<Header />
<main className="min-h-screen bg-studio-black">
<div className="container mx-auto py-12 px-4">
<div className="mb-8 flex items-center justify-between">
<div>
<h1 className="text-4xl font-bold text-white">API Keys</h1>
<p className="mt-2 text-gray-400">
Manage API keys for your applications
</p>
</div>
<Button
variant="phoenix"
onClick={() => setShowCreate(!showCreate)}
disabled={creating}
>
<Plus className="mr-2 h-4 w-4" />
Create API Key
</Button>
</div>
{error && (
<Card className="mb-8 border-red-500/50">
<CardContent className="py-4">
<p className="text-red-500">
Error loading API keys: {error.message}
</p>
</CardContent>
</Card>
)}
{newlyCreatedKey && (
<Card className="mb-8 border-green-500/50 bg-green-500/10">
<CardHeader>
<CardTitle className="text-green-500">API Key Created!</CardTitle>
<CardDescription>
Copy this key now. You won't be able to see it again.
</CardDescription>
</CardHeader>
<CardContent>
<div className="flex items-center gap-2">
<code className="flex-1 rounded bg-studio-dark px-4 py-2 font-mono text-sm text-white break-all">
{newlyCreatedKey}
</code>
<Button
variant="outline"
size="sm"
onClick={() => {
navigator.clipboard.writeText(newlyCreatedKey)
setNewlyCreatedKey(null)
}}
>
<Copy className="h-4 w-4" />
</Button>
</div>
</CardContent>
</Card>
)}
{showCreate && (
<Card className="mb-8 border-phoenix-fire/50">
<CardHeader>
<CardTitle>Create New API Key</CardTitle>
<CardDescription>
Give your API key a descriptive name to identify its purpose
</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div>
<Label htmlFor="key-name">Key Name</Label>
<Input
id="key-name"
value={newKeyName}
onChange={(e) => setNewKeyName(e.target.value)}
placeholder="e.g., Production App, Test Environment"
className="mt-2"
disabled={creating}
/>
</div>
<div className="flex gap-2">
<Button
onClick={handleCreateKey}
disabled={!newKeyName.trim() || creating}
>
{creating ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Creating...
</>
) : (
'Create Key'
)}
</Button>
<Button
variant="outline"
onClick={() => setShowCreate(false)}
disabled={creating}
>
Cancel
</Button>
</div>
</div>
</CardContent>
</Card>
)}
{keys.length === 0 && !loading ? (
<Card>
<CardContent className="py-12 text-center">
<Key className="mx-auto mb-4 h-12 w-12 text-gray-400" />
<h3 className="mb-2 text-lg font-semibold text-white">No API Keys</h3>
<p className="mb-4 text-gray-400">
Create your first API key to start using the Phoenix Nexus API
</p>
<Button variant="phoenix" onClick={() => setShowCreate(true)}>
<Plus className="mr-2 h-4 w-4" />
Create API Key
</Button>
</CardContent>
</Card>
) : (
<div className="space-y-4">
{keys.map((key) => (
<Card key={key.id}>
<CardHeader>
<div className="flex items-center justify-between">
<div>
<CardTitle className="flex items-center gap-2">
<Key className="h-5 w-5 text-phoenix-fire" />
{key.name}
</CardTitle>
<CardDescription className="mt-1">
Created {key.created} Last used {key.lastUsed}
</CardDescription>
</div>
<Button
variant="outline"
size="sm"
onClick={() => handleDeleteKey(key.id)}
disabled={revoking}
>
{revoking ? (
<Loader2 className="h-4 w-4 animate-spin" />
) : (
<Trash2 className="h-4 w-4" />
)}
</Button>
</div>
</CardHeader>
<CardContent>
<div className="flex items-center gap-2">
<code className="flex-1 rounded bg-studio-dark px-4 py-2 font-mono text-sm text-white">
{key.masked && !key.fullKey ? key.key : key.fullKey || key.key}
</code>
{key.fullKey && (
<>
<Button
variant="outline"
size="sm"
onClick={() => toggleMask(key.id)}
>
{key.masked ? <Eye className="h-4 w-4" /> : <EyeOff className="h-4 w-4" />}
</Button>
<Button
variant="outline"
size="sm"
onClick={() => copyKey(key.fullKey || key.key, key.id)}
>
{copiedId === key.id ? (
<CheckCircle className="h-4 w-4 text-green-500" />
) : (
<Copy className="h-4 w-4" />
)}
</Button>
</>
)}
</div>
<div className="mt-4 flex flex-wrap gap-2">
{key.permissions.map((perm) => (
<span
key={perm}
className="rounded-full bg-phoenix-fire/20 px-3 py-1 text-xs text-phoenix-fire"
>
{perm}
</span>
))}
</div>
</CardContent>
</Card>
))}
</div>
)}
<Card className="mt-8 border-studio-medium">
<CardHeader>
<CardTitle>Security Best Practices</CardTitle>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li> Never commit API keys to version control</li>
<li> Use environment variables to store keys</li>
<li> Rotate keys regularly</li>
<li> Delete unused keys immediately</li>
<li> Use different keys for different environments</li>
</ul>
</CardContent>
</Card>
</div>
</main>
</>
)
}

View File

@@ -0,0 +1,183 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Header } from '@/components/layout/header'
import { Key, Terminal, FileText, Activity, Code, Settings } from 'lucide-react'
export default function DeveloperPortalPage() {
return (
<>
<Header />
<main className="min-h-screen bg-studio-black">
{/* Hero */}
<section className="relative border-b border-studio-medium bg-gradient-to-br from-phoenix-fire/10 via-transparent to-sankofa-gold/10 py-24 px-4">
<div className="mx-auto max-w-4xl text-center">
<h1 className="mb-6 text-5xl font-bold text-white md:text-6xl">
Developer Portal
</h1>
<p className="mb-8 text-xl text-gray-300">
Manage API keys, test environments, and developer resources
</p>
<div className="flex flex-col gap-4 sm:flex-row sm:justify-center">
<Button variant="phoenix" size="lg" asChild>
<Link href="/portal/developers/keys">Get API Keys</Link>
</Button>
<Button variant="outline" size="lg" asChild>
<Link href="/developers/docs">View Documentation</Link>
</Button>
</div>
</div>
</section>
{/* Developer Tools */}
<section className="py-24 px-4">
<div className="mx-auto max-w-6xl">
<h2 className="mb-12 text-center text-4xl font-bold text-white">
Developer Tools
</h2>
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
<Card className="hover:border-phoenix-fire transition-colors cursor-pointer" asChild>
<Link href="/portal/developers/keys">
<CardHeader>
<Key className="mb-2 h-10 w-10 text-phoenix-fire" />
<CardTitle>API Keys</CardTitle>
<CardDescription>
Create and manage API keys for your applications
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm text-gray-400">
Generate keys, set permissions, and monitor usage
</p>
</CardContent>
</Link>
</Card>
<Card className="hover:border-phoenix-fire transition-colors cursor-pointer" asChild>
<Link href="/portal/developers/environments">
<CardHeader>
<Terminal className="mb-2 h-10 w-10 text-sankofa-gold" />
<CardTitle>Test Environments</CardTitle>
<CardDescription>
Provision and manage sandbox environments
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm text-gray-400">
Instant provisioning with automatic cleanup
</p>
</CardContent>
</Link>
</Card>
<Card className="hover:border-phoenix-fire transition-colors cursor-pointer" asChild>
<Link href="/portal/developers/logs">
<CardHeader>
<FileText className="mb-2 h-10 w-10 text-neon-cyan" />
<CardTitle>API Logs</CardTitle>
<CardDescription>
View and analyze API request logs
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm text-gray-400">
Real-time log streaming and search
</p>
</CardContent>
</Link>
</Card>
<Card className="hover:border-phoenix-fire transition-colors cursor-pointer" asChild>
<Link href="/portal/developers/analytics">
<CardHeader>
<Activity className="mb-2 h-10 w-10 text-phoenix-fire" />
<CardTitle>Usage Analytics</CardTitle>
<CardDescription>
Monitor API usage and performance
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm text-gray-400">
Track requests, errors, and quotas
</p>
</CardContent>
</Link>
</Card>
<Card className="hover:border-phoenix-fire transition-colors cursor-pointer" asChild>
<Link href="/developers/docs">
<CardHeader>
<Code className="mb-2 h-10 w-10 text-sankofa-gold" />
<CardTitle>Documentation</CardTitle>
<CardDescription>
API references and integration guides
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm text-gray-400">
Comprehensive guides and examples
</p>
</CardContent>
</Link>
</Card>
<Card className="hover:border-phoenix-fire transition-colors cursor-pointer" asChild>
<Link href="/portal/developers/settings">
<CardHeader>
<Settings className="mb-2 h-10 w-10 text-neon-cyan" />
<CardTitle>Settings</CardTitle>
<CardDescription>
Configure developer account settings
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm text-gray-400">
Manage preferences and notifications
</p>
</CardContent>
</Link>
</Card>
</div>
</div>
</section>
{/* Quick Actions */}
<section className="border-t border-studio-medium bg-studio-dark py-24 px-4">
<div className="mx-auto max-w-6xl">
<h2 className="mb-8 text-3xl font-bold text-white">Quick Actions</h2>
<div className="grid gap-4 md:grid-cols-2">
<Card>
<CardHeader>
<CardTitle>Get Started</CardTitle>
</CardHeader>
<CardContent>
<p className="mb-4 text-gray-300">
New to Phoenix Nexus? Create your first API key and start building.
</p>
<Button variant="outline" asChild>
<Link href="/developers/docs/quickstart">Quick Start Guide </Link>
</Button>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>Need Help?</CardTitle>
</CardHeader>
<CardContent>
<p className="mb-4 text-gray-300">
Check the documentation or contact our developer support team.
</p>
<Button variant="outline" asChild>
<Link href="/support">Contact Support </Link>
</Button>
</CardContent>
</Card>
</div>
</div>
</section>
</main>
</>
)
}

View File

@@ -0,0 +1,139 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Header } from '@/components/layout/header'
import { Handshake, TrendingUp, FileText, Users, Award, Settings } from 'lucide-react'
export default function PartnerPortalPage() {
return (
<>
<Header />
<main className="min-h-screen bg-studio-black">
{/* Hero */}
<section className="relative border-b border-studio-medium bg-gradient-to-br from-phoenix-fire/10 via-transparent to-sankofa-gold/10 py-24 px-4">
<div className="mx-auto max-w-4xl text-center">
<h1 className="mb-6 text-5xl font-bold text-white md:text-6xl">
Partner Portal
</h1>
<p className="mb-8 text-xl text-gray-300">
Manage deals, solutions, and partner resources
</p>
</div>
</section>
{/* Partner Tools */}
<section className="py-24 px-4">
<div className="mx-auto max-w-6xl">
<h2 className="mb-12 text-center text-4xl font-bold text-white">
Partner Resources
</h2>
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
<Card className="hover:border-phoenix-fire transition-colors cursor-pointer" asChild>
<Link href="/portal/partners/deals">
<CardHeader>
<TrendingUp className="mb-2 h-10 w-10 text-phoenix-fire" />
<CardTitle>Deal Registration</CardTitle>
<CardDescription>
Register and track co-sell opportunities
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm text-gray-400">
Submit deals, track status, and manage opportunities
</p>
</CardContent>
</Link>
</Card>
<Card className="hover:border-phoenix-fire transition-colors cursor-pointer" asChild>
<Link href="/portal/partners/solutions">
<CardHeader>
<FileText className="mb-2 h-10 w-10 text-sankofa-gold" />
<CardTitle>Solution Marketplace</CardTitle>
<CardDescription>
List and manage your solutions
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm text-gray-400">
Submit solutions for marketplace listing
</p>
</CardContent>
</Link>
</Card>
<Card className="hover:border-phoenix-fire transition-colors cursor-pointer" asChild>
<Link href="/portal/partners/onboarding">
<CardHeader>
<Users className="mb-2 h-10 w-10 text-neon-cyan" />
<CardTitle>Technical Onboarding</CardTitle>
<CardDescription>
Access onboarding resources and training
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm text-gray-400">
Technical enablement and certification
</p>
</CardContent>
</Link>
</Card>
<Card className="hover:border-phoenix-fire transition-colors cursor-pointer" asChild>
<Link href="/portal/partners/resources">
<CardHeader>
<Award className="mb-2 h-10 w-10 text-phoenix-fire" />
<CardTitle>Marketing Resources</CardTitle>
<CardDescription>
Co-marketing materials and assets
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm text-gray-400">
Logos, templates, and campaign materials
</p>
</CardContent>
</Link>
</Card>
<Card className="hover:border-phoenix-fire transition-colors cursor-pointer" asChild>
<Link href="/portal/partners/analytics">
<CardHeader>
<TrendingUp className="mb-2 h-10 w-10 text-sankofa-gold" />
<CardTitle>Partner Analytics</CardTitle>
<CardDescription>
Track performance and revenue
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm text-gray-400">
View deal pipeline and performance metrics
</p>
</CardContent>
</Link>
</Card>
<Card className="hover:border-phoenix-fire transition-colors cursor-pointer" asChild>
<Link href="/portal/partners/settings">
<CardHeader>
<Settings className="mb-2 h-10 w-10 text-neon-cyan" />
<CardTitle>Partner Settings</CardTitle>
<CardDescription>
Manage partner account and preferences
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm text-gray-400">
Update profile and notification preferences
</p>
</CardContent>
</Link>
</Card>
</div>
</div>
</section>
</main>
</>
)
}

View File

@@ -0,0 +1,242 @@
'use client'
import { useState, useEffect } from 'react'
import { useRouter, useSearchParams } from 'next/navigation'
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Header } from '@/components/layout/header'
import { Key, ArrowRight, Loader2 } from 'lucide-react'
import { initiateSSO, getPortalForRole, isAuthenticated } from '@/lib/auth/sso'
export default function SignInPage() {
const router = useRouter()
const searchParams = useSearchParams()
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [loading, setLoading] = useState(false)
const [error, setError] = useState('')
const [ssoLoading, setSsoLoading] = useState(false)
// Check if already authenticated
useEffect(() => {
if (isAuthenticated()) {
router.push('/portal')
}
}, [router])
// Handle Keycloak SSO callback
useEffect(() => {
const code = searchParams?.get('code')
const state = searchParams?.get('state')
if (code && state) {
// Handle SSO callback - would integrate with actual Keycloak
// For now, redirect to portal
router.push('/portal')
}
}, [searchParams, router])
const handleSignIn = async (e: React.FormEvent) => {
e.preventDefault()
setLoading(true)
setError('')
try {
// TODO: Integrate with actual authentication API
// For now, use GraphQL login mutation
const response = await fetch(
process.env.NEXT_PUBLIC_GRAPHQL_ENDPOINT || 'http://localhost:4000/graphql',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: `
mutation Login($email: String!, $password: String!) {
login(email: $email, password: $password) {
token
user {
id
email
name
role
}
}
}
`,
variables: { email, password },
}),
}
)
const result = await response.json()
if (result.errors) {
setError(result.errors[0].message || 'Invalid email or password')
setLoading(false)
return
}
if (result.data?.login) {
// Store token
if (typeof window !== 'undefined') {
sessionStorage.setItem('auth_token', result.data.login.token)
localStorage.setItem('phoenix_token', result.data.login.token)
}
// Determine portal based on role
const role = result.data.login.user.role.toLowerCase()
const portal = getPortalForRole(role)
router.push(portal)
}
} catch (err) {
setError('Failed to sign in. Please try again.')
console.error('Sign in error:', err)
} finally {
setLoading(false)
}
}
const handleKeycloakSSO = async () => {
setSsoLoading(true)
try {
const keycloakUrl = process.env.NEXT_PUBLIC_KEYCLOAK_URL || 'https://keycloak.sankofa.nexus'
const realm = process.env.NEXT_PUBLIC_KEYCLOAK_REALM || 'sankofa'
const clientId = process.env.NEXT_PUBLIC_KEYCLOAK_CLIENT_ID || 'phoenix-portal'
const redirectUri = `${window.location.origin}/portal/signin`
const ssoUrl = await initiateSSO({
keycloakUrl,
realm,
clientId,
redirectUri,
})
window.location.href = ssoUrl
} catch (err) {
setError('Failed to initiate SSO. Please try again.')
console.error('SSO error:', err)
setSsoLoading(false)
}
}
const isKeycloakConfigured =
typeof window !== 'undefined' &&
(process.env.NEXT_PUBLIC_KEYCLOAK_URL || process.env.NEXT_PUBLIC_KEYCLOAK_CLIENT_ID)
return (
<>
<Header />
<main className="min-h-screen bg-studio-black flex items-center justify-center px-4">
<Card className="w-full max-w-md border-studio-medium">
<CardHeader className="text-center">
<div className="mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-phoenix-fire/20">
<Key className="h-6 w-6 text-phoenix-fire" />
</div>
<CardTitle className="text-2xl">Sign In</CardTitle>
<CardDescription>
Access your Phoenix Nexus portals
</CardDescription>
</CardHeader>
<CardContent>
<form onSubmit={handleSignIn} className="space-y-4">
{error && (
<div className="rounded bg-red-500/10 px-4 py-3 text-sm text-red-500">
{error}
</div>
)}
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input
id="email"
type="email"
placeholder="you@example.com"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
disabled={loading}
/>
</div>
<div className="space-y-2">
<div className="flex items-center justify-between">
<Label htmlFor="password">Password</Label>
<Link
href="/portal/forgot-password"
className="text-sm text-phoenix-fire hover:underline"
>
Forgot password?
</Link>
</div>
<Input
id="password"
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
disabled={loading}
/>
</div>
<Button
type="submit"
variant="phoenix"
className="w-full"
disabled={loading}
>
{loading ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Signing in...
</>
) : (
<>
Sign In
<ArrowRight className="ml-2 h-4 w-4" />
</>
)}
</Button>
<div className="text-center text-sm text-gray-400">
Don't have an account?{' '}
<Link href="/portal/get-started" className="text-phoenix-fire hover:underline">
Get started
</Link>
</div>
</form>
{isKeycloakConfigured && (
<div className="mt-6 border-t border-studio-medium pt-6">
<p className="mb-4 text-center text-sm text-gray-400">
Or continue with
</p>
<div className="space-y-2">
<Button
variant="outline"
className="w-full"
onClick={handleKeycloakSSO}
disabled={ssoLoading || loading}
>
{ssoLoading ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Connecting...
</>
) : (
'Keycloak SSO'
)}
</Button>
</div>
</div>
)}
</CardContent>
</Card>
</main>
</>
)
}

View File

@@ -0,0 +1,254 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { ArrowLeft, Check } from 'lucide-react'
import { notFound } from 'next/navigation'
// Product catalog with details
const products = {
'phoenixcore-compute': {
name: 'PhoenixCore Compute',
category: 'Compute',
description: 'Core compute engine powered by Phoenix fire',
longDescription: 'PhoenixCore Compute delivers high-performance virtual machines and container orchestration with enterprise-grade reliability. Built on our global edge infrastructure, it provides low-latency compute resources across 325+ regions worldwide.',
features: [
'High-performance CPUs (AMD EPYC / Intel Xeon)',
'NVMe storage for ultra-fast I/O',
'Global edge deployment',
'Auto-scaling capabilities',
'99.99% uptime SLA',
'Blockchain-verified resource tracking',
],
pricing: {
base: 0.05, // per vCPU hour
memory: 0.01, // per GB hour
storage: 0.001, // per GB hour
currency: 'USD',
},
tiers: [
{ name: 'Starter', vcpu: 2, memory: 4, price: 50 },
{ name: 'Professional', vcpu: 8, memory: 16, price: 200 },
{ name: 'Enterprise', vcpu: 32, memory: 64, price: 800 },
],
},
'sankofaedge-nodes': {
name: 'SankofaEdge Nodes',
category: 'Compute',
description: 'Edge nodes that remember and return data',
longDescription: 'SankofaEdge Nodes provide low-latency compute at the network edge, bringing your applications closer to users worldwide. With 250+ edge locations, reduce latency and improve user experience.',
features: [
'250+ global edge locations',
'Sub-10ms latency',
'CDN integration',
'Edge caching',
'Regional data residency',
],
pricing: {
base: 0.03,
currency: 'USD',
},
},
'okravault-storage': {
name: 'OkraVault Storage',
category: 'Storage',
description: 'Storage for the soul of your data',
longDescription: 'OkraVault provides secure, scalable object and block storage with enterprise-grade durability. Your data is protected with encryption at rest and in transit, with blockchain-verified integrity.',
features: [
'S3-compatible API',
'99.999999999% durability',
'Encryption at rest and in transit',
'Multi-region replication',
'Versioning and lifecycle policies',
],
pricing: {
storage: 0.023, // per GB/month
egress: 0.09, // per GB
currency: 'USD',
},
},
'firebird-ai-engine': {
name: 'Firebird AI Engine',
category: 'AI & Machine Learning',
description: 'AI that transforms like fire',
longDescription: 'Firebird AI Engine provides scalable machine learning infrastructure with GPU acceleration, model training, and inference capabilities. Built for enterprise AI workloads.',
features: [
'GPU acceleration (NVIDIA A100/H100)',
'Distributed training',
'Model serving',
'Auto-scaling inference',
'MLOps integration',
],
pricing: {
training: 2.50, // per GPU hour
inference: 0.50, // per GPU hour
currency: 'USD',
},
},
}
export async function generateStaticParams() {
return Object.keys(products).map((slug) => ({ slug }))
}
export default function ProductDetailPage({ params }: { params: { slug: string } }) {
const product = products[params.slug as keyof typeof products]
if (!product) {
notFound()
}
return (
<main className="min-h-screen bg-studio-black">
{/* Header */}
<header className="border-b border-studio-medium bg-studio-dark">
<div className="mx-auto flex max-w-7xl items-center justify-between px-4 py-4">
<Link href="/" className="text-2xl font-bold text-white">
<span className="text-sankofa-gold">Sankofa's</span> Phoenix <span className="text-phoenix-fire">Nexus</span> Cloud
</Link>
<nav className="flex gap-4">
<Link href="/" className="text-gray-400 hover:text-white">
Home
</Link>
<Link href="/products" className="text-gray-400 hover:text-white">
Products
</Link>
<Link href="/about" className="text-gray-400 hover:text-white">
About
</Link>
</nav>
</div>
</header>
{/* Breadcrumb */}
<div className="mx-auto max-w-7xl px-4 py-4">
<Link
href="/products"
className="inline-flex items-center gap-2 text-gray-400 hover:text-white"
>
<ArrowLeft className="h-4 w-4" />
Back to Products
</Link>
</div>
{/* Product Detail */}
<section className="mx-auto max-w-7xl px-4 py-12">
<div className="grid gap-8 lg:grid-cols-2">
{/* Product Info */}
<div>
<div className="mb-4">
<span className="rounded-full bg-phoenix-fire/20 px-3 py-1 text-sm text-phoenix-fire">
{product.category}
</span>
</div>
<h1 className="mb-4 text-4xl font-bold text-white">{product.name}</h1>
<p className="mb-6 text-xl text-gray-300">{product.description}</p>
<p className="mb-8 text-gray-400">{product.longDescription}</p>
{/* Features */}
<div className="mb-8">
<h2 className="mb-4 text-2xl font-bold text-white">Features</h2>
<ul className="space-y-2">
{product.features.map((feature, index) => (
<li key={index} className="flex items-start gap-2 text-gray-300">
<Check className="mt-1 h-5 w-5 flex-shrink-0 text-phoenix-fire" />
<span>{feature}</span>
</li>
))}
</ul>
</div>
{/* Pricing */}
{product.pricing && (
<div className="mb-8">
<h2 className="mb-4 text-2xl font-bold text-white">Pricing</h2>
<Card className="border-studio-medium bg-studio-dark">
<CardHeader>
<CardTitle className="text-white">Pay-as-you-go</CardTitle>
</CardHeader>
<CardContent>
{product.pricing.base && (
<p className="text-gray-300">
Base: ${product.pricing.base.toFixed(3)} per hour
</p>
)}
{product.pricing.storage && (
<p className="text-gray-300">
Storage: ${product.pricing.storage.toFixed(3)} per GB/month
</p>
)}
{product.pricing.training && (
<p className="text-gray-300">
Training: ${product.pricing.training.toFixed(2)} per GPU hour
</p>
)}
{product.pricing.inference && (
<p className="text-gray-300">
Inference: ${product.pricing.inference.toFixed(2)} per GPU hour
</p>
)}
</CardContent>
</Card>
</div>
)}
{/* Tiers */}
{product.tiers && (
<div className="mb-8">
<h2 className="mb-4 text-2xl font-bold text-white">Pricing Tiers</h2>
<div className="grid gap-4 md:grid-cols-3">
{product.tiers.map((tier, index) => (
<Card key={index} className="border-studio-medium bg-studio-dark">
<CardHeader>
<CardTitle className="text-white">{tier.name}</CardTitle>
</CardHeader>
<CardContent>
<p className="mb-2 text-3xl font-bold text-phoenix-fire">
${tier.price}
<span className="text-sm text-gray-400">/month</span>
</p>
<p className="text-sm text-gray-400">
{tier.vcpu} vCPU, {tier.memory}GB RAM
</p>
</CardContent>
</Card>
))}
</div>
</div>
)}
{/* CTA */}
<div className="flex gap-4">
<Button variant="phoenix" size="lg">
Get Started
</Button>
<Button variant="outline" size="lg">
Contact Sales
</Button>
</div>
</div>
{/* Sidebar */}
<div>
<Card className="border-studio-medium bg-studio-dark">
<CardHeader>
<CardTitle className="text-white">Ready to Start?</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<p className="text-gray-400">
Start building on Sankofa Phoenix today. No credit card required for free tier.
</p>
<Button variant="phoenix" className="w-full" size="lg">
Create Account
</Button>
<Button variant="outline" className="w-full" size="lg">
Schedule Demo
</Button>
</CardContent>
</Card>
</div>
</div>
</section>
</main>
)
}

View File

@@ -0,0 +1,111 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { PublicLayout } from '@/components/layout/public-layout'
import { Sparkles, Brain, Network } from 'lucide-react'
export default function AIMLPage() {
const products = [
{
name: 'Firebird AI Engine',
icon: Sparkles,
description: 'AI that transforms like fire',
features: [
'Model inference',
'Real-time AI',
'Edge AI deployment',
'GPU acceleration',
],
},
{
name: 'Sankofa Memory Model',
icon: Brain,
description: 'AI models that remember and learn',
features: [
'Recursive learning',
'Memory-augmented AI',
'Context-aware models',
'Continuous improvement',
],
},
{
name: 'Ancestral Neural Fabric',
icon: Network,
description: 'Distributed AI with ancestral patterns',
features: [
'Distributed training',
'Federated learning',
'Knowledge graphs',
'Multi-region deployment',
],
},
]
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black">
<section className="relative flex min-h-[50vh] flex-col items-center justify-center overflow-hidden px-4">
<div className="absolute inset-0 bg-gradient-to-br from-phoenix-fire/20 via-transparent to-sankofa-gold/20" />
<div className="relative z-10 max-w-4xl text-center">
<h1 className="mb-6 text-5xl font-bold tracking-tight text-white md:text-7xl">
AI & Machine Learning
</h1>
<p className="mb-8 text-xl text-gray-300 md:text-2xl">
AI services powered by ancestral wisdom and modern technology
</p>
</div>
</section>
<section className="py-24 px-4">
<div className="mx-auto max-w-7xl">
<div className="grid gap-8 md:grid-cols-3">
{products.map((product) => {
const Icon = product.icon
return (
<Card key={product.name} className="hover:border-phoenix-fire transition-colors">
<CardHeader>
<Icon className="mb-4 h-12 w-12 text-phoenix-fire" />
<CardTitle className="text-xl">{product.name}</CardTitle>
<CardDescription className="text-gray-400">
{product.description}
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300 mb-6">
{product.features.map((feature, idx) => (
<li key={idx} className="flex items-start gap-2">
<span className="text-phoenix-fire mt-1"></span>
<span>{feature}</span>
</li>
))}
</ul>
<Button variant="outline" className="w-full" asChild>
<Link href={`/products/${product.name.toLowerCase().replace(/\s+/g, '-')}`}>
Learn More
</Link>
</Button>
</CardContent>
</Card>
)
})}
</div>
</div>
</section>
<section className="py-24 px-4 bg-studio-dark">
<div className="mx-auto max-w-4xl text-center">
<h2 className="mb-6 text-4xl font-bold text-white">
Ready to Get Started?
</h2>
<Button variant="phoenix" size="lg" asChild>
<Link href="/portal">Get Started</Link>
</Button>
</div>
</section>
</div>
</PublicLayout>
)
}

View File

@@ -0,0 +1,126 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { PublicLayout } from '@/components/layout/public-layout'
import { Server, HardDrive, Network } from 'lucide-react'
export default function CoreInfrastructurePage() {
const products = [
{
name: 'PhoenixCore Compute',
icon: Server,
description: 'Core compute engine powered by Phoenix fire',
features: [
'Virtual machines and containers',
'Serverless functions',
'Auto-scaling capabilities',
'Multi-region deployment',
],
},
{
name: 'OkraVault Storage',
icon: HardDrive,
description: 'Storage for the soul of your data',
features: [
'Object and block storage',
'High-performance NVMe storage',
'Multi-region replication',
'S3-compatible API',
],
},
{
name: 'SankofaGrid Global Mesh',
icon: Network,
description: 'Global network mesh that remembers',
features: [
'325-region global network',
'Low-latency routing',
'Private network connections',
'DDoS protection',
],
},
]
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black">
{/* Hero Section */}
<section className="relative flex min-h-[50vh] flex-col items-center justify-center overflow-hidden px-4">
<div className="absolute inset-0 bg-gradient-to-br from-phoenix-fire/20 via-transparent to-sankofa-gold/20" />
<div className="relative z-10 max-w-4xl text-center">
<h1 className="mb-6 text-5xl font-bold tracking-tight text-white md:text-7xl">
Core Infrastructure
</h1>
<p className="mb-8 text-xl text-gray-300 md:text-2xl">
The foundation of sovereign cloud infrastructure
</p>
<p className="mb-12 text-lg text-gray-400">
Compute, storage, and networking services that power the Phoenix Nexus Cloud
</p>
</div>
</section>
{/* Products Grid */}
<section className="py-24 px-4">
<div className="mx-auto max-w-7xl">
<div className="grid gap-8 md:grid-cols-3">
{products.map((product) => {
const Icon = product.icon
return (
<Card key={product.name} className="hover:border-phoenix-fire transition-colors">
<CardHeader>
<Icon className="mb-4 h-12 w-12 text-phoenix-fire" />
<CardTitle className="text-xl">{product.name}</CardTitle>
<CardDescription className="text-gray-400">
{product.description}
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300 mb-6">
{product.features.map((feature, idx) => (
<li key={idx} className="flex items-start gap-2">
<span className="text-phoenix-fire mt-1"></span>
<span>{feature}</span>
</li>
))}
</ul>
<Button variant="outline" className="w-full" asChild>
<Link href={`/products/${product.name.toLowerCase().replace(/\s+/g, '-')}`}>
Learn More
</Link>
</Button>
</CardContent>
</Card>
)
})}
</div>
</div>
</section>
{/* CTA Section */}
<section className="py-24 px-4 bg-studio-dark">
<div className="mx-auto max-w-4xl text-center">
<h2 className="mb-6 text-4xl font-bold text-white">
Ready to Get Started?
</h2>
<p className="mb-8 text-xl text-gray-400">
Build on sovereign cloud infrastructure
</p>
<div className="flex flex-col gap-4 sm:flex-row sm:justify-center">
<Button variant="phoenix" size="lg" asChild>
<Link href="/portal">Get Started</Link>
</Button>
<Button variant="outline" size="lg" asChild>
<Link href="/docs">View Documentation</Link>
</Button>
</div>
</div>
</section>
</div>
</PublicLayout>
)
}

View File

@@ -0,0 +1,111 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { PublicLayout } from '@/components/layout/public-layout'
import { Database, Layers, Clock } from 'lucide-react'
export default function DataServicesPage() {
const products = [
{
name: 'SankofaGraph Database',
icon: Database,
description: 'Graph database that remembers relationships',
features: [
'Knowledge graphs',
'Relationship mapping',
'Network analysis',
'GraphQL interface',
],
},
{
name: 'PhoenixFire NoSQL',
icon: Layers,
description: 'Fast, powerful NoSQL database',
features: [
'Document stores',
'Key-value stores',
'High-performance queries',
'Auto-scaling',
],
},
{
name: 'Nananom Time Series',
icon: Clock,
description: 'Time-series database for historical data',
features: [
'Metrics storage',
'Monitoring data',
'Historical analysis',
'High-throughput ingestion',
],
},
]
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black">
<section className="relative flex min-h-[50vh] flex-col items-center justify-center overflow-hidden px-4">
<div className="absolute inset-0 bg-gradient-to-br from-phoenix-fire/20 via-transparent to-sankofa-gold/20" />
<div className="relative z-10 max-w-4xl text-center">
<h1 className="mb-6 text-5xl font-bold tracking-tight text-white md:text-7xl">
Data Services
</h1>
<p className="mb-8 text-xl text-gray-300 md:text-2xl">
Databases and data services for modern applications
</p>
</div>
</section>
<section className="py-24 px-4">
<div className="mx-auto max-w-7xl">
<div className="grid gap-8 md:grid-cols-3">
{products.map((product) => {
const Icon = product.icon
return (
<Card key={product.name} className="hover:border-phoenix-fire transition-colors">
<CardHeader>
<Icon className="mb-4 h-12 w-12 text-phoenix-fire" />
<CardTitle className="text-xl">{product.name}</CardTitle>
<CardDescription className="text-gray-400">
{product.description}
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300 mb-6">
{product.features.map((feature, idx) => (
<li key={idx} className="flex items-start gap-2">
<span className="text-phoenix-fire mt-1"></span>
<span>{feature}</span>
</li>
))}
</ul>
<Button variant="outline" className="w-full" asChild>
<Link href={`/products/${product.name.toLowerCase().replace(/\s+/g, '-')}`}>
Learn More
</Link>
</Button>
</CardContent>
</Card>
)
})}
</div>
</div>
</section>
<section className="py-24 px-4 bg-studio-dark">
<div className="mx-auto max-w-4xl text-center">
<h2 className="mb-6 text-4xl font-bold text-white">
Ready to Get Started?
</h2>
<Button variant="phoenix" size="lg" asChild>
<Link href="/portal">Get Started</Link>
</Button>
</div>
</section>
</div>
</PublicLayout>
)
}

View File

@@ -0,0 +1,100 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { PublicLayout } from '@/components/layout/public-layout'
import { Code, Hammer } from 'lucide-react'
export default function DeveloperServicesPage() {
const products = [
{
name: 'SankofaDev Platform',
icon: Code,
description: 'Development that remembers best practices',
features: [
'CI/CD pipelines',
'Developer tools',
'Platform services',
'GitOps workflows',
],
},
{
name: 'PhoenixForge Build Engine',
icon: Hammer,
description: 'Build and deployment services',
features: [
'Build systems',
'Deployment automation',
'Container builds',
'Artifact management',
],
},
]
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black">
<section className="relative flex min-h-[50vh] flex-col items-center justify-center overflow-hidden px-4">
<div className="absolute inset-0 bg-gradient-to-br from-phoenix-fire/20 via-transparent to-sankofa-gold/20" />
<div className="relative z-10 max-w-4xl text-center">
<h1 className="mb-6 text-5xl font-bold tracking-tight text-white md:text-7xl">
Developer Services
</h1>
<p className="mb-8 text-xl text-gray-300 md:text-2xl">
Tools and services for modern development workflows
</p>
</div>
</section>
<section className="py-24 px-4">
<div className="mx-auto max-w-7xl">
<div className="grid gap-8 md:grid-cols-2">
{products.map((product) => {
const Icon = product.icon
return (
<Card key={product.name} className="hover:border-phoenix-fire transition-colors">
<CardHeader>
<Icon className="mb-4 h-12 w-12 text-phoenix-fire" />
<CardTitle className="text-xl">{product.name}</CardTitle>
<CardDescription className="text-gray-400">
{product.description}
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300 mb-6">
{product.features.map((feature, idx) => (
<li key={idx} className="flex items-start gap-2">
<span className="text-phoenix-fire mt-1"></span>
<span>{feature}</span>
</li>
))}
</ul>
<Button variant="outline" className="w-full" asChild>
<Link href={`/products/${product.name.toLowerCase().replace(/\s+/g, '-')}`}>
Learn More
</Link>
</Button>
</CardContent>
</Card>
)
})}
</div>
</div>
</section>
<section className="py-24 px-4 bg-studio-dark">
<div className="mx-auto max-w-4xl text-center">
<h2 className="mb-6 text-4xl font-bold text-white">
Ready to Get Started?
</h2>
<Button variant="phoenix" size="lg" asChild>
<Link href="/portal">Get Started</Link>
</Button>
</div>
</section>
</div>
</PublicLayout>
)
}

View File

@@ -0,0 +1,100 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { PublicLayout } from '@/components/layout/public-layout'
import { User, Key } from 'lucide-react'
export default function IdentityPage() {
const products = [
{
name: 'OkraID',
icon: User,
description: 'Soul-powered identity framework',
features: [
'Self-sovereign identity',
'Decentralized identity',
'User authentication',
'Identity verification',
],
},
{
name: 'AkanAuth Sovereign Identity Plane',
icon: Key,
description: 'Sovereign authentication platform',
features: [
'Multi-factor authentication',
'Single sign-on (SSO)',
'Identity federation',
'Sovereign identity management',
],
},
]
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black">
<section className="relative flex min-h-[50vh] flex-col items-center justify-center overflow-hidden px-4">
<div className="absolute inset-0 bg-gradient-to-br from-phoenix-fire/20 via-transparent to-sankofa-gold/20" />
<div className="relative z-10 max-w-4xl text-center">
<h1 className="mb-6 text-5xl font-bold tracking-tight text-white md:text-7xl">
Identity Services
</h1>
<p className="mb-8 text-xl text-gray-300 md:text-2xl">
Sovereign identity management for the modern web
</p>
</div>
</section>
<section className="py-24 px-4">
<div className="mx-auto max-w-7xl">
<div className="grid gap-8 md:grid-cols-2">
{products.map((product) => {
const Icon = product.icon
return (
<Card key={product.name} className="hover:border-phoenix-fire transition-colors">
<CardHeader>
<Icon className="mb-4 h-12 w-12 text-phoenix-fire" />
<CardTitle className="text-xl">{product.name}</CardTitle>
<CardDescription className="text-gray-400">
{product.description}
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300 mb-6">
{product.features.map((feature, idx) => (
<li key={idx} className="flex items-start gap-2">
<span className="text-phoenix-fire mt-1"></span>
<span>{feature}</span>
</li>
))}
</ul>
<Button variant="outline" className="w-full" asChild>
<Link href={`/products/${product.name.toLowerCase().replace(/\s+/g, '-')}`}>
Learn More
</Link>
</Button>
</CardContent>
</Card>
)
})}
</div>
</div>
</section>
<section className="py-24 px-4 bg-studio-dark">
<div className="mx-auto max-w-4xl text-center">
<h2 className="mb-6 text-4xl font-bold text-white">
Ready to Get Started?
</h2>
<Button variant="phoenix" size="lg" asChild>
<Link href="/portal">Get Started</Link>
</Button>
</div>
</section>
</div>
</PublicLayout>
)
}

View File

@@ -0,0 +1,100 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { PublicLayout } from '@/components/layout/public-layout'
import { Settings, Globe2 } from 'lucide-react'
export default function ManagementPage() {
const products = [
{
name: 'SankofaControl Plane',
icon: Settings,
description: 'Control that remembers and learns',
features: [
'Infrastructure as Code',
'Orchestration',
'Resource management',
'Policy enforcement',
],
},
{
name: 'PhoenixRealm Management',
icon: Globe2,
description: 'Multi-cloud and multi-region management',
features: [
'Multi-cloud management',
'Global orchestration',
'Region management',
'Unified control plane',
],
},
]
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black">
<section className="relative flex min-h-[50vh] flex-col items-center justify-center overflow-hidden px-4">
<div className="absolute inset-0 bg-gradient-to-br from-phoenix-fire/20 via-transparent to-sankofa-gold/20" />
<div className="relative z-10 max-w-4xl text-center">
<h1 className="mb-6 text-5xl font-bold tracking-tight text-white md:text-7xl">
Management Services
</h1>
<p className="mb-8 text-xl text-gray-300 md:text-2xl">
Infrastructure management and orchestration for global deployments
</p>
</div>
</section>
<section className="py-24 px-4">
<div className="mx-auto max-w-7xl">
<div className="grid gap-8 md:grid-cols-2">
{products.map((product) => {
const Icon = product.icon
return (
<Card key={product.name} className="hover:border-phoenix-fire transition-colors">
<CardHeader>
<Icon className="mb-4 h-12 w-12 text-phoenix-fire" />
<CardTitle className="text-xl">{product.name}</CardTitle>
<CardDescription className="text-gray-400">
{product.description}
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300 mb-6">
{product.features.map((feature, idx) => (
<li key={idx} className="flex items-start gap-2">
<span className="text-phoenix-fire mt-1"></span>
<span>{feature}</span>
</li>
))}
</ul>
<Button variant="outline" className="w-full" asChild>
<Link href={`/products/${product.name.toLowerCase().replace(/\s+/g, '-')}`}>
Learn More
</Link>
</Button>
</CardContent>
</Card>
)
})}
</div>
</div>
</section>
<section className="py-24 px-4 bg-studio-dark">
<div className="mx-auto max-w-4xl text-center">
<h2 className="mb-6 text-4xl font-bold text-white">
Ready to Get Started?
</h2>
<Button variant="phoenix" size="lg" asChild>
<Link href="/portal">Get Started</Link>
</Button>
</div>
</section>
</div>
</PublicLayout>
)
}

View File

@@ -0,0 +1,111 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { PublicLayout } from '@/components/layout/public-layout'
import { Network, Globe, Zap } from 'lucide-react'
export default function NetworkingPage() {
const products = [
{
name: 'SankofaGrid Global Mesh',
icon: Network,
description: 'Global network mesh that remembers',
features: [
'325-region global network',
'Low-latency routing',
'Private network connections',
'Multi-region connectivity',
],
},
{
name: 'AkanSphere Edge Routing',
icon: Globe,
description: 'Edge routing with cultural intelligence',
features: [
'Edge routing',
'Traffic management',
'CDN integration',
'Geographic routing',
],
},
{
name: 'PhoenixFlight Network Fabric',
icon: Zap,
description: 'High-performance network fabric',
features: [
'High-bandwidth connections',
'Data center networking',
'Low-latency fabric',
'Network automation',
],
},
]
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black">
<section className="relative flex min-h-[50vh] flex-col items-center justify-center overflow-hidden px-4">
<div className="absolute inset-0 bg-gradient-to-br from-phoenix-fire/20 via-transparent to-sankofa-gold/20" />
<div className="relative z-10 max-w-4xl text-center">
<h1 className="mb-6 text-5xl font-bold tracking-tight text-white md:text-7xl">
Networking Services
</h1>
<p className="mb-8 text-xl text-gray-300 md:text-2xl">
Global networking infrastructure for sovereign cloud
</p>
</div>
</section>
<section className="py-24 px-4">
<div className="mx-auto max-w-7xl">
<div className="grid gap-8 md:grid-cols-3">
{products.map((product) => {
const Icon = product.icon
return (
<Card key={product.name} className="hover:border-phoenix-fire transition-colors">
<CardHeader>
<Icon className="mb-4 h-12 w-12 text-phoenix-fire" />
<CardTitle className="text-xl">{product.name}</CardTitle>
<CardDescription className="text-gray-400">
{product.description}
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300 mb-6">
{product.features.map((feature, idx) => (
<li key={idx} className="flex items-start gap-2">
<span className="text-phoenix-fire mt-1"></span>
<span>{feature}</span>
</li>
))}
</ul>
<Button variant="outline" className="w-full" asChild>
<Link href={`/products/${product.name.toLowerCase().replace(/\s+/g, '-')}`}>
Learn More
</Link>
</Button>
</CardContent>
</Card>
)
})}
</div>
</div>
</section>
<section className="py-24 px-4 bg-studio-dark">
<div className="mx-auto max-w-4xl text-center">
<h2 className="mb-6 text-4xl font-bold text-white">
Ready to Get Started?
</h2>
<Button variant="phoenix" size="lg" asChild>
<Link href="/portal">Get Started</Link>
</Button>
</div>
</section>
</div>
</PublicLayout>
)
}

View File

@@ -59,7 +59,7 @@ export default function ProductsPage() {
<header className="border-b border-studio-medium bg-studio-dark">
<div className="mx-auto flex max-w-7xl items-center justify-between px-4 py-4">
<Link href="/" className="text-2xl font-bold text-white">
Phoenix <span className="text-phoenix-fire">Sankofa</span> Cloud
<span className="text-sankofa-gold">Sankofa's</span> Phoenix <span className="text-phoenix-fire">Nexus</span> Cloud
</Link>
<nav className="flex gap-4">
<Link href="/" className="text-gray-400 hover:text-white">
@@ -96,18 +96,26 @@ export default function ProductsPage() {
{category.category}
</h2>
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
{category.items.map((item) => (
<Card key={item.name}>
<CardHeader>
<CardTitle className="text-lg">{item.name}</CardTitle>
</CardHeader>
<CardContent>
<CardDescription className="text-gray-400">
{item.description}
</CardDescription>
</CardContent>
</Card>
))}
{category.items.map((item) => {
const slug = item.name.toLowerCase().replace(/\s+/g, '-')
return (
<Card key={item.name} className="hover:border-phoenix-fire transition-colors">
<CardHeader>
<CardTitle className="text-lg">{item.name}</CardTitle>
</CardHeader>
<CardContent>
<CardDescription className="text-gray-400 mb-4">
{item.description}
</CardDescription>
<Link href={`/products/${slug}`}>
<Button variant="outline" size="sm" className="w-full">
Learn More
</Button>
</Link>
</CardContent>
</Card>
)
})}
</div>
</div>
))}

View File

@@ -0,0 +1,111 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { PublicLayout } from '@/components/layout/public-layout'
import { Shield, Lock, Eye } from 'lucide-react'
export default function SecurityPage() {
const products = [
{
name: 'Aegis of Akan Shield',
icon: Shield,
description: 'Comprehensive security platform',
features: [
'Threat protection',
'DDoS mitigation',
'Security monitoring',
'Zero Trust networking',
],
},
{
name: 'PhoenixGuard IAM',
icon: Lock,
description: 'Identity and access management',
features: [
'Multi-factor authentication',
'Single sign-on (SSO)',
'Role-based access control',
'Identity federation',
],
},
{
name: 'Nsamankom Sentinel',
icon: Eye,
description: 'Security monitoring with ancestral protection',
features: [
'Security monitoring',
'Threat detection',
'Compliance reporting',
'Incident response',
],
},
]
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black">
<section className="relative flex min-h-[50vh] flex-col items-center justify-center overflow-hidden px-4">
<div className="absolute inset-0 bg-gradient-to-br from-phoenix-fire/20 via-transparent to-sankofa-gold/20" />
<div className="relative z-10 max-w-4xl text-center">
<h1 className="mb-6 text-5xl font-bold tracking-tight text-white md:text-7xl">
Security Services
</h1>
<p className="mb-8 text-xl text-gray-300 md:text-2xl">
Enterprise-grade security for sovereign cloud infrastructure
</p>
</div>
</section>
<section className="py-24 px-4">
<div className="mx-auto max-w-7xl">
<div className="grid gap-8 md:grid-cols-3">
{products.map((product) => {
const Icon = product.icon
return (
<Card key={product.name} className="hover:border-phoenix-fire transition-colors">
<CardHeader>
<Icon className="mb-4 h-12 w-12 text-phoenix-fire" />
<CardTitle className="text-xl">{product.name}</CardTitle>
<CardDescription className="text-gray-400">
{product.description}
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300 mb-6">
{product.features.map((feature, idx) => (
<li key={idx} className="flex items-start gap-2">
<span className="text-phoenix-fire mt-1"></span>
<span>{feature}</span>
</li>
))}
</ul>
<Button variant="outline" className="w-full" asChild>
<Link href={`/products/${product.name.toLowerCase().replace(/\s+/g, '-')}`}>
Learn More
</Link>
</Button>
</CardContent>
</Card>
)
})}
</div>
</div>
</section>
<section className="py-24 px-4 bg-studio-dark">
<div className="mx-auto max-w-4xl text-center">
<h2 className="mb-6 text-4xl font-bold text-white">
Ready to Get Started?
</h2>
<Button variant="phoenix" size="lg" asChild>
<Link href="/portal">Get Started</Link>
</Button>
</div>
</section>
</div>
</PublicLayout>
)
}

View File

@@ -1,9 +1,9 @@
'use client'
import { ApolloProvider } from '@apollo/client'
import { apolloClient } from '@/lib/graphql/client'
import { getApolloClient } from '@/lib/graphql/client'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { useState } from 'react'
import { useState, useMemo } from 'react'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import { Toaster } from '@/components/ui/toaster'
@@ -33,6 +33,9 @@ export function Providers({ children }: { children: React.ReactNode }) {
})
)
// Create Apollo Client only on client side
const apolloClient = useMemo(() => getApolloClient(), [])
return (
<ApolloProvider client={apolloClient}>
<QueryClientProvider client={queryClient}>

View File

@@ -0,0 +1,183 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Header } from '@/components/layout/header'
import { Check, Shield, Globe, Lock, Zap, Users } from 'lucide-react'
export default function EnterprisePage() {
return (
<>
<Header />
<main className="min-h-screen bg-studio-black">
{/* Hero */}
<section className="relative border-b border-studio-medium bg-gradient-to-br from-phoenix-fire/10 via-transparent to-sankofa-gold/10 py-24 px-4">
<div className="mx-auto max-w-4xl text-center">
<h1 className="mb-6 text-5xl font-bold text-white md:text-6xl">
Enterprise Cloud Infrastructure
</h1>
<p className="mb-8 text-xl text-gray-300">
Sovereign cloud infrastructure designed for enterprise scale, security, and compliance
</p>
<div className="flex flex-col gap-4 sm:flex-row sm:justify-center">
<Button variant="phoenix" size="lg" asChild>
<Link href="/portal/get-started">Start Free Trial</Link>
</Button>
<Button variant="outline" size="lg" asChild>
<Link href="/company/trust">View Compliance</Link>
</Button>
</div>
</div>
</section>
{/* Trust & Compliance */}
<section className="py-24 px-4">
<div className="mx-auto max-w-6xl">
<h2 className="mb-12 text-center text-4xl font-bold text-white">
Enterprise-Grade Trust & Compliance
</h2>
<div className="grid gap-8 md:grid-cols-3">
<Card>
<CardHeader>
<Shield className="mb-2 h-10 w-10 text-phoenix-fire" />
<CardTitle>Security First</CardTitle>
<CardDescription>
DoD/MilSpec compliance, zero-trust architecture, and sovereign identity management
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li className="flex items-start gap-2">
<Check className="mt-0.5 h-5 w-5 flex-shrink-0 text-phoenix-fire" />
<span>STIG-compliant infrastructure</span>
</li>
<li className="flex items-start gap-2">
<Check className="mt-0.5 h-5 w-5 flex-shrink-0 text-phoenix-fire" />
<span>Keycloak-based sovereign identity (no Azure dependencies)</span>
</li>
<li className="flex items-start gap-2">
<Check className="mt-0.5 h-5 w-5 flex-shrink-0 text-phoenix-fire" />
<span>End-to-end encryption</span>
</li>
</ul>
</CardContent>
</Card>
<Card>
<CardHeader>
<Lock className="mb-2 h-10 w-10 text-sankofa-gold" />
<CardTitle>Compliance Ready</CardTitle>
<CardDescription>
Built for regulated industries and government requirements
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li className="flex items-start gap-2">
<Check className="mt-0.5 h-5 w-5 flex-shrink-0 text-sankofa-gold" />
<span>RMF authorization ready</span>
</li>
<li className="flex items-start gap-2">
<Check className="mt-0.5 h-5 w-5 flex-shrink-0 text-sankofa-gold" />
<span>Audit logging and compliance reporting</span>
</li>
<li className="flex items-start gap-2">
<Check className="mt-0.5 h-5 w-5 flex-shrink-0 text-sankofa-gold" />
<span>Data sovereignty controls</span>
</li>
</ul>
</CardContent>
</Card>
<Card>
<CardHeader>
<Globe className="mb-2 h-10 w-10 text-neon-cyan" />
<CardTitle>Global Infrastructure</CardTitle>
<CardDescription>
325-region deployment with edge computing and regional data residency
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li className="flex items-start gap-2">
<Check className="mt-0.5 h-5 w-5 flex-shrink-0 text-neon-cyan" />
<span>Multi-region redundancy</span>
</li>
<li className="flex items-start gap-2">
<Check className="mt-0.5 h-5 w-5 flex-shrink-0 text-neon-cyan" />
<span>Edge computing for low latency</span>
</li>
<li className="flex items-start gap-2">
<Check className="mt-0.5 h-5 w-5 flex-shrink-0 text-neon-cyan" />
<span>Data residency controls</span>
</li>
</ul>
</CardContent>
</Card>
</div>
</div>
</section>
{/* Enterprise Features */}
<section className="border-t border-studio-medium bg-studio-dark py-24 px-4">
<div className="mx-auto max-w-6xl">
<h2 className="mb-12 text-center text-4xl font-bold text-white">
Enterprise Capabilities
</h2>
<div className="grid gap-8 md:grid-cols-2">
<div>
<Zap className="mb-4 h-8 w-8 text-phoenix-fire" />
<h3 className="mb-4 text-2xl font-bold text-white">Advanced Multi-Tenancy</h3>
<p className="mb-4 text-gray-300">
Superior tenant isolation, per-second billing granularity, and comprehensive quota management.
Built for enterprises managing multiple business units or customer tenants.
</p>
<ul className="space-y-2 text-sm text-gray-400">
<li> Tenant-level resource isolation</li>
<li> Per-second billing with cost forecasting</li>
<li> Budget management and alerts</li>
<li> Custom quota enforcement</li>
</ul>
</div>
<div>
<Users className="mb-4 h-8 w-8 text-sankofa-gold" />
<h3 className="mb-4 text-2xl font-bold text-white">Role-Based Access Control</h3>
<p className="mb-4 text-gray-300">
Enterprise-grade RBAC with fine-grained permissions, audit trails, and integration
with your existing identity providers.
</p>
<ul className="space-y-2 text-sm text-gray-400">
<li> Custom roles and permissions</li>
<li> SSO integration (SAML, OIDC)</li>
<li> Audit logging for all actions</li>
<li> Multi-factor authentication</li>
</ul>
</div>
</div>
</div>
</section>
{/* CTA */}
<section className="py-24 px-4">
<div className="mx-auto max-w-4xl text-center">
<h2 className="mb-6 text-4xl font-bold text-white">
Ready to Transform Your Infrastructure?
</h2>
<p className="mb-8 text-xl text-gray-400">
Join enterprises leveraging sovereign cloud infrastructure
</p>
<div className="flex flex-col gap-4 sm:flex-row sm:justify-center">
<Button variant="phoenix" size="lg" asChild>
<Link href="/portal/get-started">Contact Sales</Link>
</Button>
<Button variant="outline" size="lg" asChild>
<Link href="/developers">View Documentation</Link>
</Button>
</div>
</div>
</section>
</main>
</>
)
}

View File

@@ -0,0 +1,169 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Header } from '@/components/layout/header'
import { Shield, Lock, FileCheck, Globe, CheckCircle, Building2 } from 'lucide-react'
export default function GovernmentPage() {
return (
<>
<Header />
<main className="min-h-screen bg-studio-black">
{/* Hero */}
<section className="relative border-b border-studio-medium bg-gradient-to-br from-phoenix-fire/10 via-transparent to-sankofa-gold/10 py-24 px-4">
<div className="mx-auto max-w-4xl text-center">
<h1 className="mb-6 text-5xl font-bold text-white md:text-6xl">
Government Cloud Infrastructure
</h1>
<p className="mb-8 text-xl text-gray-300">
Sovereign cloud infrastructure designed for government agencies and public sector organizations
</p>
<div className="flex flex-col gap-4 sm:flex-row sm:justify-center">
<Button variant="phoenix" size="lg" asChild>
<Link href="/portal/get-started">Request Demo</Link>
</Button>
<Button variant="outline" size="lg" asChild>
<Link href="/company/trust">View Compliance</Link>
</Button>
</div>
</div>
</section>
{/* Government Features */}
<section className="py-24 px-4">
<div className="mx-auto max-w-6xl">
<h2 className="mb-12 text-center text-4xl font-bold text-white">
Built for Government Requirements
</h2>
<div className="grid gap-8 md:grid-cols-2">
<Card>
<CardHeader>
<Shield className="mb-2 h-10 w-10 text-phoenix-fire" />
<CardTitle>DoD/MilSpec Compliance</CardTitle>
<CardDescription>
STIG-compliant infrastructure meeting Department of Defense standards
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-5 w-5 flex-shrink-0 text-phoenix-fire" />
<span>Security Technical Implementation Guides (STIG)</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-5 w-5 flex-shrink-0 text-phoenix-fire" />
<span>RMF authorization ready</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-5 w-5 flex-shrink-0 text-phoenix-fire" />
<span>FedRAMP alignment (in progress)</span>
</li>
</ul>
</CardContent>
</Card>
<Card>
<CardHeader>
<Lock className="mb-2 h-10 w-10 text-sankofa-gold" />
<CardTitle>Data Sovereignty</CardTitle>
<CardDescription>
Complete control over data location and access
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-5 w-5 flex-shrink-0 text-sankofa-gold" />
<span>On-premises deployment options</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-5 w-5 flex-shrink-0 text-sankofa-gold" />
<span>Air-gapped configurations</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-5 w-5 flex-shrink-0 text-sankofa-gold" />
<span>Regional data residency controls</span>
</li>
</ul>
</CardContent>
</Card>
<Card>
<CardHeader>
<FileCheck className="mb-2 h-10 w-10 text-neon-cyan" />
<CardTitle>Audit & Compliance</CardTitle>
<CardDescription>
Comprehensive audit logging and compliance reporting
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-5 w-5 flex-shrink-0 text-neon-cyan" />
<span>Immutable audit logs</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-5 w-5 flex-shrink-0 text-neon-cyan" />
<span>Compliance dashboards</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-5 w-5 flex-shrink-0 text-neon-cyan" />
<span>Automated compliance reporting</span>
</li>
</ul>
</CardContent>
</Card>
<Card>
<CardHeader>
<Building2 className="mb-2 h-10 w-10 text-phoenix-fire" />
<CardTitle>Government Partnerships</CardTitle>
<CardDescription>
Dedicated support for government agencies
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-5 w-5 flex-shrink-0 text-phoenix-fire" />
<span>Dedicated government support team</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-5 w-5 flex-shrink-0 text-phoenix-fire" />
<span>GSA schedule (in progress)</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-5 w-5 flex-shrink-0 text-phoenix-fire" />
<span>Custom contract vehicles</span>
</li>
</ul>
</CardContent>
</Card>
</div>
</div>
</section>
{/* CTA */}
<section className="border-t border-studio-medium bg-studio-dark py-24 px-4">
<div className="mx-auto max-w-4xl text-center">
<h2 className="mb-6 text-4xl font-bold text-white">
Ready to Transform Government IT?
</h2>
<p className="mb-8 text-xl text-gray-400">
Contact our government team to learn more
</p>
<div className="flex flex-col gap-4 sm:flex-row sm:justify-center">
<Button variant="phoenix" size="lg" asChild>
<Link href="/support">Contact Government Team</Link>
</Button>
<Button variant="outline" size="lg" asChild>
<Link href="/developers">View Documentation</Link>
</Button>
</div>
</div>
</section>
</main>
</>
)
}

View File

@@ -0,0 +1,183 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Header } from '@/components/layout/header'
import { GraduationCap, Users, Shield, BookOpen, CheckCircle } from 'lucide-react'
export default function InstitutionalPage() {
return (
<>
<Header />
<main className="min-h-screen bg-studio-black">
{/* Hero */}
<section className="relative border-b border-studio-medium bg-gradient-to-br from-phoenix-fire/10 via-transparent to-sankofa-gold/10 py-24 px-4">
<div className="mx-auto max-w-4xl text-center">
<h1 className="mb-6 text-5xl font-bold text-white md:text-6xl">
Institutional Cloud Infrastructure
</h1>
<p className="mb-8 text-xl text-gray-300">
Sovereign cloud infrastructure for educational institutions, research organizations, and non-profits
</p>
<div className="flex flex-col gap-4 sm:flex-row sm:justify-center">
<Button variant="phoenix" size="lg" asChild>
<Link href="/portal/get-started">Get Started</Link>
</Button>
<Button variant="outline" size="lg" asChild>
<Link href="/solutions/institutional/pricing">View Pricing</Link>
</Button>
</div>
</div>
</section>
{/* Institutional Features */}
<section className="py-24 px-4">
<div className="mx-auto max-w-6xl">
<h2 className="mb-12 text-center text-4xl font-bold text-white">
Built for Institutions
</h2>
<div className="grid gap-8 md:grid-cols-3">
<Card>
<CardHeader>
<GraduationCap className="mb-2 h-10 w-10 text-phoenix-fire" />
<CardTitle>Education-Focused</CardTitle>
<CardDescription>
Designed for universities, colleges, and research institutions
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-5 w-5 flex-shrink-0 text-phoenix-fire" />
<span>Student and faculty management</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-5 w-5 flex-shrink-0 text-phoenix-fire" />
<span>Research computing resources</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-5 w-5 flex-shrink-0 text-phoenix-fire" />
<span>Academic pricing and discounts</span>
</li>
</ul>
</CardContent>
</Card>
<Card>
<CardHeader>
<Users className="mb-2 h-10 w-10 text-sankofa-gold" />
<CardTitle>Multi-Tenant Support</CardTitle>
<CardDescription>
Manage multiple departments, schools, or research groups
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-5 w-5 flex-shrink-0 text-sankofa-gold" />
<span>Department-level isolation</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-5 w-5 flex-shrink-0 text-sankofa-gold" />
<span>Budget allocation and tracking</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-5 w-5 flex-shrink-0 text-sankofa-gold" />
<span>Usage reporting by department</span>
</li>
</ul>
</CardContent>
</Card>
<Card>
<CardHeader>
<Shield className="mb-2 h-10 w-10 text-neon-cyan" />
<CardTitle>Privacy & Security</CardTitle>
<CardDescription>
FERPA and HIPAA considerations for educational data
</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-5 w-5 flex-shrink-0 text-neon-cyan" />
<span>Data privacy controls</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-5 w-5 flex-shrink-0 text-neon-cyan" />
<span>Secure research environments</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle className="mt-0.5 h-5 w-5 flex-shrink-0 text-neon-cyan" />
<span>Compliance with educational regulations</span>
</li>
</ul>
</CardContent>
</Card>
</div>
</div>
</section>
{/* Use Cases */}
<section className="border-t border-studio-medium bg-studio-dark py-24 px-4">
<div className="mx-auto max-w-6xl">
<h2 className="mb-12 text-center text-4xl font-bold text-white">
Institutional Use Cases
</h2>
<div className="grid gap-8 md:grid-cols-2">
<div>
<BookOpen className="mb-4 h-8 w-8 text-phoenix-fire" />
<h3 className="mb-4 text-2xl font-bold text-white">Research Computing</h3>
<p className="mb-4 text-gray-300">
High-performance computing resources for research projects,
data analysis, and computational research.
</p>
<ul className="space-y-2 text-sm text-gray-400">
<li> GPU clusters for ML/AI research</li>
<li> Large-scale data processing</li>
<li> Collaborative research environments</li>
<li> Research data management</li>
</ul>
</div>
<div>
<Users className="mb-4 h-8 w-8 text-sankofa-gold" />
<h3 className="mb-4 text-2xl font-bold text-white">Campus IT Infrastructure</h3>
<p className="mb-4 text-gray-300">
Modern cloud infrastructure for campus-wide IT services,
student portals, and administrative systems.
</p>
<ul className="space-y-2 text-sm text-gray-400">
<li> Student information systems</li>
<li> Learning management systems</li>
<li> Campus-wide applications</li>
<li> Administrative computing</li>
</ul>
</div>
</div>
</div>
</section>
{/* CTA */}
<section className="py-24 px-4">
<div className="mx-auto max-w-4xl text-center">
<h2 className="mb-6 text-4xl font-bold text-white">
Ready to Modernize Your Institution?
</h2>
<p className="mb-8 text-xl text-gray-400">
Contact our institutional team to learn more
</p>
<div className="flex flex-col gap-4 sm:flex-row sm:justify-center">
<Button variant="phoenix" size="lg" asChild>
<Link href="/support">Contact Institutional Team</Link>
</Button>
<Button variant="outline" size="lg" asChild>
<Link href="/developers">View Documentation</Link>
</Button>
</div>
</div>
</section>
</main>
</>
)
}

179
src/app/support/page.tsx Normal file
View File

@@ -0,0 +1,179 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Header } from '@/components/layout/header'
import { HelpCircle, Book, MessageSquare, FileText, Search, Headphones } from 'lucide-react'
export default function SupportPage() {
return (
<>
<Header />
<main className="min-h-screen bg-studio-black">
{/* Hero */}
<section className="relative border-b border-studio-medium bg-gradient-to-br from-phoenix-fire/10 via-transparent to-sankofa-gold/10 py-24 px-4">
<div className="mx-auto max-w-4xl text-center">
<h1 className="mb-6 text-5xl font-bold text-white md:text-6xl">
Support Center
</h1>
<p className="mb-8 text-xl text-gray-300">
Get help when you need it
</p>
</div>
</section>
{/* Support Options */}
<section className="py-24 px-4">
<div className="mx-auto max-w-6xl">
<h2 className="mb-12 text-center text-4xl font-bold text-white">
How Can We Help?
</h2>
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
<Card className="hover:border-phoenix-fire transition-colors cursor-pointer" asChild>
<Link href="/developers/docs">
<CardHeader>
<Book className="mb-2 h-10 w-10 text-phoenix-fire" />
<CardTitle>Documentation</CardTitle>
<CardDescription>
Comprehensive guides, API references, and tutorials
</CardDescription>
</CardHeader>
</Link>
</Card>
<Card className="hover:border-phoenix-fire transition-colors cursor-pointer" asChild>
<Link href="/support/kb">
<CardHeader>
<FileText className="mb-2 h-10 w-10 text-sankofa-gold" />
<CardTitle>Knowledge Base</CardTitle>
<CardDescription>
Search articles, FAQs, and troubleshooting guides
</CardDescription>
</CardHeader>
</Link>
</Card>
<Card className="hover:border-phoenix-fire transition-colors cursor-pointer" asChild>
<Link href="/support/contact">
<CardHeader>
<MessageSquare className="mb-2 h-10 w-10 text-neon-cyan" />
<CardTitle>Contact Support</CardTitle>
<CardDescription>
Get in touch with our support team
</CardDescription>
</CardHeader>
</Link>
</Card>
<Card className="hover:border-phoenix-fire transition-colors cursor-pointer" asChild>
<Link href="/support/status">
<CardHeader>
<Search className="mb-2 h-10 w-10 text-phoenix-fire" />
<CardTitle>System Status</CardTitle>
<CardDescription>
Check service status and incident reports
</CardDescription>
</CardHeader>
</Link>
</Card>
<Card className="hover:border-phoenix-fire transition-colors cursor-pointer" asChild>
<Link href="/support/community">
<CardHeader>
<Headphones className="mb-2 h-10 w-10 text-sankofa-gold" />
<CardTitle>Community</CardTitle>
<CardDescription>
Connect with other users and experts
</CardDescription>
</CardHeader>
</Link>
</Card>
<Card className="hover:border-phoenix-fire transition-colors cursor-pointer" asChild>
<Link href="/support/training">
<CardHeader>
<HelpCircle className="mb-2 h-10 w-10 text-neon-cyan" />
<CardTitle>Training</CardTitle>
<CardDescription>
Learn through courses and workshops
</CardDescription>
</CardHeader>
</Link>
</Card>
</div>
</div>
</section>
{/* Support Tiers */}
<section className="border-t border-studio-medium bg-studio-dark py-24 px-4">
<div className="mx-auto max-w-6xl">
<h2 className="mb-12 text-center text-4xl font-bold text-white">
Support Plans
</h2>
<div className="grid gap-8 md:grid-cols-3">
<Card>
<CardHeader>
<CardTitle>Community Support</CardTitle>
<CardDescription>Free</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li> Community forums</li>
<li> Documentation access</li>
<li> Knowledge base</li>
<li> Best effort responses</li>
</ul>
</CardContent>
</Card>
<Card className="border-phoenix-fire">
<CardHeader>
<CardTitle>Standard Support</CardTitle>
<CardDescription>Included with subscription</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li> Email support (24-48h response)</li>
<li> Priority documentation access</li>
<li> System status notifications</li>
<li> Business hours support</li>
</ul>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>Enterprise Support</CardTitle>
<CardDescription>Premium</CardDescription>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li> 24/7 phone and email support</li>
<li> Dedicated support engineer</li>
<li> SLA guarantees</li>
<li> On-site support available</li>
</ul>
</CardContent>
</Card>
</div>
</div>
</section>
{/* CTA */}
<section className="py-24 px-4">
<div className="mx-auto max-w-4xl text-center">
<h2 className="mb-6 text-4xl font-bold text-white">
Need Immediate Help?
</h2>
<p className="mb-8 text-xl text-gray-400">
Contact our support team
</p>
<Button variant="phoenix" size="lg" asChild>
<Link href="/support/contact">Contact Support</Link>
</Button>
</div>
</section>
</main>
</>
)
}

View File

@@ -0,0 +1,107 @@
import { PublicLayout } from '@/components/layout/public-layout'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import { Palette, Globe, Shield, CheckCircle } from 'lucide-react'
export default function WhiteLabelPage() {
return (
<PublicLayout>
<div className="min-h-screen bg-studio-black py-24 px-4">
<div className="mx-auto max-w-7xl">
<div className="mb-12 text-center">
<h1 className="mb-4 text-5xl font-bold text-white">White-Label Solution</h1>
<p className="text-xl text-gray-400">
Customize Phoenix with your brand for enterprise deployments
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-12">
<Card>
<CardHeader>
<Palette className="h-8 w-8 text-phoenix-fire mb-2" />
<CardTitle className="text-white">Custom Branding</CardTitle>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-400" />
<span>Custom logo and colors</span>
</li>
<li className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-400" />
<span>Custom domain</span>
</li>
<li className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-400" />
<span>Branded email templates</span>
</li>
</ul>
</CardContent>
</Card>
<Card>
<CardHeader>
<Globe className="h-8 w-8 text-sankofa-gold mb-2" />
<CardTitle className="text-white">Multi-Tenant</CardTitle>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-400" />
<span>Isolated tenant environments</span>
</li>
<li className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-400" />
<span>Custom subdomains</span>
</li>
<li className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-400" />
<span>Tenant-specific branding</span>
</li>
</ul>
</CardContent>
</Card>
<Card>
<CardHeader>
<Shield className="h-8 w-8 text-neon-cyan mb-2" />
<CardTitle className="text-white">Enterprise Features</CardTitle>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-gray-300">
<li className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-400" />
<span>SLA guarantees</span>
</li>
<li className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-400" />
<span>Dedicated support</span>
</li>
<li className="flex items-center gap-2">
<CheckCircle className="h-4 w-4 text-green-400" />
<span>Custom integrations</span>
</li>
</ul>
</CardContent>
</Card>
</div>
<Card className="bg-studio-dark border-studio-medium">
<CardHeader>
<CardTitle className="text-white">Get Started with White-Label</CardTitle>
</CardHeader>
<CardContent>
<p className="text-gray-300 mb-6">
Contact our enterprise sales team to discuss white-label options for your organization.
</p>
<Button variant="phoenix" size="lg" asChild>
<a href="/enterprise">Contact Sales</a>
</Button>
</CardContent>
</Card>
</div>
</div>
</PublicLayout>
)
}