20.0.0-alpha.1
A role-playing games community platform built with modern web technologies. Pelilauta provides a space for RPG enthusiasts to create sites, share content, engage in discussions, and build gaming communities.
Monorepo layout for code organization and LLM/agent context engineering. Packages are linked via Vite aliases, not pnpm workspace protocol — no monorepo build tooling required.
pelilauta-20/
├── app/
│ ├── pelilauta/ # Main Astro application (SSR + Svelte 5)
│ └── cyan-ds/ # Design system documentation/playground
├── packages/
│ ├── cyan/ # Cyan design system (tokens, components, styles)
│ └── ... # Additional shared libraries
└── package.json
app/pelilauta — The main platform. Astro with SSR, Svelte 5 (Runes mode) for interactivity, Firebase backend.app/cyan-ds — Design system documentation, component playground, and visual testing.packages/cyan — The Cyan design system: tokens, base styles, and shared UI components. Pure CSS/Svelte.Packages are resolved at build time via Vite/Astro aliases, not workspace dependencies:
// vite.config / astro.config — alias example
resolve: {
alias: {
'@cyan': path.resolve(__dirname, '../../packages/cyan/src'),
}
}
This keeps each directory self-contained for LLM context while avoiding monorepo tooling complexity.
packages/cyan)*.test.ts files)e2e/ directories)pnpm install
pnpm dev # Start pelilauta app (dev mode)
pnpm dev:ds # Start cyan-ds app (dev mode)
pnpm build # Build both apps for production
pnpm test # Run unit tests (Vitest, all packages + apps)
pnpm test:e2e # Run e2e tests (Playwright, both apps)
pnpm check # Lint and format (Biome)
Create a .env in app/pelilauta/ with Firebase configuration:
PUBLIC_apiKey=your_firebase_api_key
PUBLIC_authDomain=your_project.firebaseapp.com
PUBLIC_databaseURL=https://your_project.firebaseio.com
PUBLIC_projectId=your_firebase_project_id
PUBLIC_storageBucket=your_project.appspot.com
PUBLIC_messagingSenderId=your_messaging_sender_id
PUBLIC_appId=your_firebase_app_id
PUBLIC_measurementId=your_measurement_id
PUBLIC_APP_NAME=Pelilauta 20
FIREBASE_ADMIN_KEY=your_firebase_admin_service_account_json
<script lang="ts">
interface Props {
title: string;
active?: boolean;
}
const { title, active = false }: Props = $props();
const isVisible = $state(false);
const buttonText = $derived(isVisible ? 'Hide' : 'Show');
</script>
// Client-side (dynamic imports)
const { doc, getDoc } = await import('firebase/firestore');
const { db } = await import('@firebase/client');
// Server-side (static imports)
import { serverDB } from '@firebase/server';
@cyan/tokens)MIT