Example Site

A fully-working game guide site — every file, ready to copy. This is "Dungeon Delver Guide", a fictional example that uses all the core @guides/ui components. See the New Site Guide for scaffold instructions.

📁 dungeon-delver-guide/
dungeon-delver-guide/
├── astro.config.mjs
├── package.json
├── tsconfig.json
├── wrangler.toml
├── src/
│   ├── layouts/
│   │   └── Layout.astro          ← site branding lives here
│   └── pages/
│       ├── index.astro            ← main page (hero, features, FAQ, download…)
│       ├── contact.astro
│       ├── thank-you.astro
│       └── privacy.astro
├── public/
│   ├── styles/global.css          ← CSS variables (colours)
│   └── images/                    ← your screenshot PNGs go here
│       ├── screen-1.png
│       └── …
└── functions/
    └── api/
        └── contact.ts             ← Cloudflare Pages Function
📄 package.json
{
  "name": "dungeon-delver-guide",
  "type": "module",
  "version": "0.0.1",
  "scripts": {
    "dev": "astro dev",
    "build": "astro build",
    "preview": "astro preview"
  },
  "dependencies": {
    "@guides/ui": "workspace:*",
    "@guides/workers": "workspace:*",
    "astro": "^5.7.0"
  },
  "devDependencies": {
    "@cloudflare/workers-types": "^4.20240529.0"
  }
}
⚙️ astro.config.mjs
import { defineConfig } from 'astro/config';
import { createSitemap } from '@guides/ui/sitemap';

export default defineConfig({
  output: 'static',
  site: 'https://dungeon-delver-guide.pages.dev',
  integrations: [createSitemap()],
  vite: {
    ssr: { noExternal: ['@guides/ui'] },
  },
});
🔧 tsconfig.json
{
  "extends": "astro/tsconfigs/base",
  "compilerOptions": {
    "types": ["@cloudflare/workers-types"]
  }
}
☁️ wrangler.toml
name = "dungeon-delver-guide"
pages_build_output_dir = "dist"
compatibility_date = "2024-09-23"
🎨 public/styles/global.css

Define your colour palette here. Every @guides/ui component reads these variables — changing --primary re-themes the whole site.

:root {
    --primary:       #b91c1c;   /* deep red — brand colour */
    --primary-dark:  #991b1b;
    --primary-light: #dc2626;
    --accent:        #f59e0b;   /* amber highlight */
    --accent-dark:   #d97706;
    --accent-light:  #fcd34d;
    --dark:          #1c0a0a;   /* hero / nav background */
    --dark-mid:      #2d1515;
    --text:          #1f2328;
    --text-muted:    #5a6270;
    --surface:       #f9f5f5;
    --border:        #e8dede;
    --white:         #ffffff;
}
🏗️ src/layouts/Layout.astro

The single source of truth for site-wide branding. The SiteConfig object flows through to the nav, footer, OG tags, and theme-color meta tag.

---
import SiteLayout from '@guides/ui/SiteLayout.astro';
import type { SiteConfig } from '@guides/ui/SiteLayout.astro';

const config: SiteConfig = {
  themeColor: '#b91c1c',
  ogSiteName: 'Dungeon Delver Guide',
  emoji: '⚔️',
  brandName: 'Dungeon Delver Guide',
  navCtaLabel: 'Get the app',
  navCtaHref: '/app/',
  footerTagline: 'Maps, bosses, loot, and every secret — all in one place.',
  footerResources: [
    { label: 'Official Game Site', href: 'https://dungeondelver.example.com' },
    { label: 'Community Discord', href: 'https://discord.gg/example' },
    { label: 'Privacy Policy', href: '/privacy' },
  ],
  copyright: '© 2026 Dungeon Delver Guide.',
};

interface Props {
  title: string;
  description: string;
  canonical?: string;
  keywords?: string;
  noindex?: boolean;
  variant?: 'default' | 'contact' | 'thanks';
}

const { title, description, canonical, keywords, noindex, variant = 'default' } = Astro.props;
---
<SiteLayout {config} {title} {description} {canonical} {keywords} {noindex} {variant}>
  <slot name="head" slot="head" />
  <slot />
</SiteLayout>
🏠 src/pages/index.astro

The main page. Uses HeroSection, DownloadSection, Screenshots, and ContactForm. Add or remove sections as needed for your site.

---
import Layout from '../layouts/Layout.astro';
import HeroSection from '@guides/ui/HeroSection.astro';
import DownloadSection from '@guides/ui/DownloadSection.astro';
import Screenshots from '@guides/ui/Screenshots.astro';
import ContactForm from '@guides/ui/ContactForm.astro';
---
<Layout
  title="Dungeon Delver Guide – Floors, Loot &amp; Secrets"
  description="The complete companion for Dungeon Delver. Maps, boss strategies, loot tables, and secret rooms."
  canonical="https://dungeon-delver-guide.pages.dev/"
  keywords="dungeon delver guide, dungeon delver tips, boss guide, loot tables"
>
  <main>

    <HeroSection
      title="Dungeon Delver Guide"
      subtitle="Your Complete Companion"
      description="Maps, boss strategies, loot tables, and every secret room — all in one place."
    >
      <a href="/app/" class="cta-button">Open the App</a>
    </HeroSection>

    <section id="about" class="features">
      <div class="container">
        <h2>Everything you need</h2>
        <div class="features-grid">
          <div class="feature-card">
            <span class="feature-icon">🗺️</span>
            <h3>Interactive Maps</h3>
            <p>Every floor mapped in detail. Mark rooms you've cleared and track your progress.</p>
          </div>
          <div class="feature-card">
            <span class="feature-icon">⚔️</span>
            <h3>Boss Strategies</h3>
            <p>Step-by-step guides for every encounter — phases, weak points, and recommended gear.</p>
          </div>
          <div class="feature-card">
            <span class="feature-icon">💎</span>
            <h3>Loot Tables</h3>
            <p>Drop rates, locations, and crafting recipes for every item in the game.</p>
          </div>
          <div class="feature-card">
            <span class="feature-icon">🔍</span>
            <h3>Secret Rooms</h3>
            <p>All hidden rooms and their unlock conditions, including missable one-time rewards.</p>
          </div>
        </div>
      </div>
    </section>

    <DownloadSection
      heading="Get the Android App"
      description="The full guide in your pocket, no internet required."
      downloadUrl="https://github.com/you/dungeon-delver-guide/releases"
      downloadAriaLabel="Download Dungeon Delver Guide APK"
      downloadAlt="Download APK"
    />

    <section id="faq" class="faq-section">
      <div class="container">
        <h2>Frequently asked questions</h2>
        <div class="faq-grid">
          <div class="faq-item">
            <h3>Is the guide free?</h3>
            <p>Yes — the website and Android app are completely free, with no ads or sign-ups required.</p>
          </div>
          <div class="faq-item">
            <h3>How often is it updated?</h3>
            <p>The guide is updated whenever the game receives new content or balance patches.</p>
          </div>
          <div class="faq-item">
            <h3>Does the app work offline?</h3>
            <p>Yes — once installed, the Android app works entirely offline. No internet needed.</p>
          </div>
          <div class="faq-item">
            <h3>Can I contribute?</h3>
            <p>Absolutely. Open a GitHub issue or use the contact form below to suggest corrections or additions.</p>
          </div>
        </div>
      </div>
    </section>

    <Screenshots
      title="Screenshots"
      screenshots={[
        { src: '/images/screen-1.png', alt: 'Floor map view',   caption: 'Interactive floor maps'     },
        { src: '/images/screen-2.png', alt: 'Boss guide',       caption: 'Detailed boss strategies'  },
        { src: '/images/screen-3.png', alt: 'Loot table',       caption: 'Full loot tables'           },
        { src: '/images/screen-4.png', alt: 'Secret room list', caption: 'All secret rooms catalogued'},
      ]}
    />

    <ContactForm webPageName="Dungeon Delver Guide" />

  </main>
</Layout>
✉️ src/pages/contact.astro

The variant="contact" prop on Layout renders ContactPage automatically. No extra imports needed.

---
import Layout from '../layouts/Layout.astro';
---
<Layout
  title="Contact – Dungeon Delver Guide"
  description="Get in touch with the Dungeon Delver Guide team."
  variant="contact"
/>
🙏 src/pages/thank-you.astro
---
import Layout from '../layouts/Layout.astro';
---
<Layout
  title="Message Sent – Dungeon Delver Guide"
  description="Your message has been received."
  variant="thanks"
/>
🔒 src/pages/privacy.astro

Update siteName, lastUpdated, and localStorageDescription to match your site. The rest of the policy text is pre-written and GDPR-friendly.

---
import Layout from '../layouts/Layout.astro';
import PrivacyPage from '@guides/ui/PrivacyPage.astro';
---
<Layout
  title="Privacy Policy – Dungeon Delver Guide"
  description="Privacy policy for Dungeon Delver Guide."
  noindex={true}
>
  <PrivacyPage
    siteName="Dungeon Delver Guide"
    lastUpdated="May 2026"
    localStorageDescription="The app saves your progress (cleared rooms, bookmarks) locally on your device using the browser's local storage. This data never leaves your device."
    thirdPartyLinks={[]}
  />
</Layout>
⚡ functions/api/contact.ts

Cloudflare Pages Function that handles the contact form. The second argument to handleContactForm is a label used to identify the form source in email notifications.

import type { EventContext } from '@cloudflare/workers-types';
import { handleContactForm } from '@guides/workers/contact';

export const onRequestPost = (
  context: EventContext<Record<string, unknown>, string, Record<string, unknown>>
) => handleContactForm(context.request, 'dungeon-delver-guide');

Ready to build? Follow the New Site Guide to scaffold the directory, register in the workspace, and deploy to Cloudflare Pages.

Browse the component library →