---
import '../styles/global.css';
import Sidebar from '../components/Sidebar.astro';
interface Props {
title?: string;
description?: string;
}
const {
title = 'Prax ORM - Type-Safe Database ORM for Rust',
description = 'Prax is a next-generation, type-safe ORM for Rust inspired by Prisma. Build robust database applications with async support, beautiful schema language, and multi-database compatibility.',
} = Astro.props;
const currentPath = Astro.url.pathname;
---
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>{title}</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content={description} />
<meta name="keywords" content="rust, orm, database, prisma, postgresql, mysql, sqlite, async, type-safe" />
<meta name="author" content="Pegasus Heavy Industries" />
<meta property="og:title" content={title} />
<meta
property="og:description"
content="A next-generation, type-safe ORM for Rust with beautiful schema language and async support."
/>
<meta property="og:type" content="website" />
<meta property="og:url" content={new URL(currentPath, Astro.site)} />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={title} />
<meta
name="twitter:description"
content="A next-generation, type-safe ORM for Rust with beautiful schema language and async support."
/>
<link
rel="icon"
type="image/svg+xml"
href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><rect fill='%23f97316' rx='20' width='100' height='100'/><text x='50' y='70' text-anchor='middle' fill='white' font-size='60' font-weight='bold'>P</text></svg>"
/>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap"
rel="stylesheet"
/>
<meta name="theme-color" content="#1a1a1a" />
</head>
<body class="bg-background text-foreground antialiased">
<div class="min-h-screen bg-background text-foreground flex">
<aside
class="hidden lg:flex lg:flex-col w-72 border-r border-border bg-surface fixed h-full z-40"
>
<Sidebar currentPath={currentPath} />
</aside>
<header
class="lg:hidden fixed top-0 left-0 right-0 h-16 bg-surface border-b border-border z-50 flex items-center px-4"
>
<button
type="button"
id="mobile-menu-button"
class="p-2 hover:bg-surface-elevated rounded-lg"
aria-label="Open menu"
>
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M4 6h16M4 12h16M4 18h16"></path>
</svg>
</button>
<div class="flex items-center gap-2 ml-4">
<div
class="w-8 h-8 bg-gradient-to-br from-primary-500 to-primary-700 rounded-lg flex items-center justify-center"
>
<span class="text-white font-bold">P</span>
</div>
<span class="font-bold">Prax</span>
</div>
</header>
<main class="flex-1 lg:ml-72">
<div class="pt-16 lg:pt-0">
<slot />
</div>
</main>
</div>
<div id="mobile-menu" class="lg:hidden fixed inset-0 z-50 hidden">
<div class="absolute inset-0 bg-black/50" data-close-menu></div>
<aside
class="absolute left-0 top-0 bottom-0 w-72 bg-surface border-r border-border overflow-y-auto flex flex-col"
>
<Sidebar currentPath={currentPath} />
</aside>
</div>
<script>
const menu = document.getElementById('mobile-menu');
const openButton = document.getElementById('mobile-menu-button');
openButton?.addEventListener('click', () => {
menu?.classList.toggle('hidden');
});
menu?.querySelector('[data-close-menu]')?.addEventListener('click', () => {
menu.classList.add('hidden');
});
menu?.querySelectorAll('a').forEach((link) => {
link.addEventListener('click', () => menu.classList.add('hidden'));
});
</script>
</body>
</html>