# Astro Project Setup

## Prerequisites

- `cms` jail running at 192.168.100.3 with Node.js 24
- Strapi running in cms jail (or plan to set up later)
- nginx serving `/usr/local/www/clawdie/` on host

## Step 1: Create project (inside cms jail)

```sh
sudo jexec cms su - clawdie -c "cd /home/clawdie && npm create astro@latest clawdie-site -- --template minimal --no-install"
sudo jexec cms su - clawdie -c "cd /home/clawdie/clawdie-site && npm install"
```

## Step 2: Install integrations

```sh
npm install @astrojs/mdx
npm install gray-matter    # for parsing SKILL.md frontmatter
npm install marked          # for rendering markdown
```

## Step 3: Configure Astro

Edit `astro.config.mjs`:

```js
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';

export default defineConfig({
  site: 'https://clawdie.si',
  output: 'static',
  integrations: [mdx()],
  build: {
    assets: 'assets',
  },
});
```

## Step 4: Create base layout

Create `src/layouts/Base.astro` with:

- Google Fonts imports (Cormorant Garamond, DM Mono)
- CSS variables from current design system
- Hex background pattern SVG
- Top nav component
- Footer component

Port directly from the current `/usr/local/www/clawdie/index.html` styles.

## Step 5: Create Strapi fetch utility

Create `src/lib/strapi.ts`:

```ts
const STRAPI_URL = import.meta.env.STRAPI_URL || 'http://localhost:1337';

export async function fetchAPI(path: string) {
  const res = await fetch(`${STRAPI_URL}/api${path}`);
  if (!res.ok) {
    console.error(`Strapi fetch failed: ${path} (${res.status})`);
    return null;
  }
  const json = await res.json();
  return json.data;
}

export async function getPage(slug: string) {
  return fetchAPI(`/pages?filters[slug][$eq]=${slug}&populate=*`);
}

export async function getGuides() {
  return fetchAPI('/guides?sort=order:asc&populate=*');
}

export async function getGuide(slug: string) {
  return fetchAPI(`/guides?filters[slug][$eq]=${slug}&populate=*`);
}
```

## Step 6: Create skill loader

Create `src/lib/skills.ts`:

```ts
import fs from 'node:fs';
import path from 'node:path';
import matter from 'gray-matter';
import { marked } from 'marked';

// nullfs-mounted from host into cms jail
const SKILLS_DIR = '/mnt/skills';

export interface Skill {
  name: string;
  slug: string;
  description: string;
  content: string;
  html: string;
}

export function getAllSkills(): Skill[] {
  const dirs = fs.readdirSync(SKILLS_DIR);
  return dirs
    .filter(d => fs.existsSync(path.join(SKILLS_DIR, d, 'SKILL.md')))
    .map(d => {
      const raw = fs.readFileSync(path.join(SKILLS_DIR, d, 'SKILL.md'), 'utf-8');
      const { data, content } = matter(raw);
      return {
        name: data.name || d,
        slug: d,
        description: data.description || '',
        content,
        html: marked(content) as string,
      };
    })
    .sort((a, b) => a.name.localeCompare(b.name));
}

export function getSkill(slug: string): Skill | undefined {
  return getAllSkills().find(s => s.slug === slug);
}
```

## Step 7: Create deploy script

Add to `package.json`:

```json
{
  "scripts": {
    "deploy": "npm run build && rsync -av --delete dist/ /usr/local/www/clawdie/"
  }
}
```

## Step 8: Environment file

Create `.env` inside cms jail:

```
STRAPI_URL=http://localhost:1337
SITE_URL=https://clawdie.si
NODE_OPTIONS=--max-old-space-size=512
```

## Step 9: Test build

```sh
npm run build
ls dist/
```

Verify output contains `index.html` and expected pages.

## Step 10: First deploy

```sh
# snapshot before deploy
sudo zfs snapshot -nv zroot/ROOT/default@pre-astro-deploy
sudo zfs snapshot zroot/ROOT/default@pre-astro-deploy

# backup current site
cp -r /usr/local/www/clawdie /usr/local/www/clawdie.bak

# deploy
npm run deploy

# verify
curl -sI https://clawdie.si | head -5
```
