diff --git a/.github/workflows/deploy-website.yml b/.github/workflows/deploy-website.yml index aa0fcc37..2e4380d3 100644 --- a/.github/workflows/deploy-website.yml +++ b/.github/workflows/deploy-website.yml @@ -27,16 +27,26 @@ jobs: steps: - name: Checkout uses: actions/checkout@v6 - + + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + + - name: Install dependencies + run: bun install --frozen-lockfile + working-directory: website + + - name: Build website + run: bun run build + working-directory: website + - name: Setup Pages uses: actions/configure-pages@v5 - + - name: Upload artifact uses: actions/upload-pages-artifact@v4 with: - # Upload the website directory - path: './website' - + path: './website/dist' + - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 \ No newline at end of file diff --git a/.github/workflows/publish-website-artifacts.yml b/.github/workflows/publish-website-artifacts.yml index c417d210..5127aeb3 100644 --- a/.github/workflows/publish-website-artifacts.yml +++ b/.github/workflows/publish-website-artifacts.yml @@ -41,40 +41,117 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Copy artifacts to website folder + - name: Copy artifacts to website public folder run: | - mkdir -p website + mkdir -p website/public # Copy macOS DMG DMG_FILE=$(find /tmp/artifacts -name "*.dmg" | head -1) if [ -n "$DMG_FILE" ]; then - cp "$DMG_FILE" website/astro-editor-latest.dmg + cp "$DMG_FILE" website/public/astro-editor-latest.dmg echo "Copied DMG: $DMG_FILE" fi # Copy Windows MSI MSI_FILE=$(find /tmp/artifacts -name "*.msi" | head -1) if [ -n "$MSI_FILE" ]; then - cp "$MSI_FILE" website/astro-editor-latest.msi + cp "$MSI_FILE" website/public/astro-editor-latest.msi echo "Copied MSI: $MSI_FILE" fi # Copy Linux AppImage APPIMAGE_FILE=$(find /tmp/artifacts -name "*.AppImage" | head -1) if [ -n "$APPIMAGE_FILE" ]; then - cp "$APPIMAGE_FILE" website/astro-editor-latest.AppImage + cp "$APPIMAGE_FILE" website/public/astro-editor-latest.AppImage echo "Copied AppImage: $APPIMAGE_FILE" fi - echo "Website folder contents:" - ls -la website/*.dmg website/*.msi website/*.AppImage 2>/dev/null || true + echo "Website public folder contents:" + ls -la website/public/*.dmg website/public/*.msi website/public/*.AppImage 2>/dev/null || true - - name: Commit website artifacts + - name: Generate release page + run: | + RELEASE_BODY=$(gh release view "$RELEASE_TAG" --json body -q .body) + VERSION="${RELEASE_TAG#v}" + DATE=$(gh release view "$RELEASE_TAG" --json publishedAt -q .publishedAt | cut -dT -f1) + + # Sanitise body for MDX: + # - Strip leading H2 title + # - Strip "Installation Instructions" section and everything after + # - Strip "Full Changelog" links + # - Escape curly braces outside code spans/blocks + # + # NOTE: This logic is duplicated in website/scripts/generate-release-pages.ts + # (sanitiseBody, escapeCurlyBraces, localiseImages). If you change this, + # update that script too (and vice versa). + CLEAN_BODY=$(printf '%s\n' "$RELEASE_BODY" | \ + sed '/^## *\(π *\)\{0,1\}Astro Editor v[0-9]/d' | \ + sed '/^### Installation Instructions/,$d' | \ + sed '/^\*\*Full Changelog\*\*/d' | \ + awk ' + /^```/ { in_code = !in_code } + in_code { print; next } + { + line = "" + n = split($0, chars, "") + in_tick = 0 + for (i = 1; i <= n; i++) { + if (chars[i] == "`") in_tick = !in_tick + if (!in_tick && chars[i] == "{") { line = line "" "{"; continue } + if (!in_tick && chars[i] == "}") { line = line "" "}"; continue } + line = line chars[i] + } + print line + } + ' | \ + sed -e :a -e '/^[[:space:]]*$/{ $d; N; ba; }') + + # Download GitHub attachment images to local repo + IMAGES_DIR="website/public/releases" + mkdir -p "$IMAGES_DIR" + IMAGE_URLS=$(printf '%s\n' "$CLEAN_BODY" | grep -oE 'https://github\.com/user-attachments/assets/[a-f0-9-]+' | sort -u || true) + IMG_INDEX=0 + for URL in $IMAGE_URLS; do + IMG_INDEX=$((IMG_INDEX + 1)) + LOCAL_NAME="${VERSION}-${IMG_INDEX}.png" + curl -sL -o "${IMAGES_DIR}/${LOCAL_NAME}" "$URL" + CLEAN_BODY=$(printf '%s' "$CLEAN_BODY" | sed "s|${URL}|/releases/${LOCAL_NAME}|g") + echo "Downloaded image: ${LOCAL_NAME}" + done + + # Generate MDX file + RELEASES_DIR="website/src/content/docs/releases" + mkdir -p "$RELEASES_DIR" + OUTPUT_FILE="$RELEASES_DIR/${VERSION}.mdx" + + { + printf '%s\n' "---" + printf '%s\n' "title: 'v${VERSION}'" + printf '%s\n' "description: 'Astro Editor v${VERSION}'" + printf '%s\n' "date: ${DATE}" + printf '%s\n' "slug: 'releases/v${VERSION}'" + printf '%s\n' "---" + + if [ -n "$CLEAN_BODY" ]; then + printf '\n%s\n\n%s\n' "$CLEAN_BODY" "---" + fi + + printf '\n%s\n' "[View on GitHub](https://github.com/dannysmith/astro-editor/releases/tag/${RELEASE_TAG})" + } > "$OUTPUT_FILE" + + echo "Generated release page: $OUTPUT_FILE" + cat "$OUTPUT_FILE" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Commit website artifacts and release page run: | git config --local user.email "action@github.com" git config --local user.name "GitHub Action" - git add website/astro-editor-latest.dmg website/astro-editor-latest.msi website/astro-editor-latest.AppImage 2>/dev/null || true - git commit -m "chore: update installers for $RELEASE_TAG" || echo "No changes to commit" + git add website/public/astro-editor-latest.dmg website/public/astro-editor-latest.msi website/public/astro-editor-latest.AppImage 2>/dev/null || true + git add website/public/releases/*.png 2>/dev/null || true + git add website/src/content/docs/releases/*.mdx 2>/dev/null || true + git commit -m "chore: update installers and add release page for $RELEASE_TAG" || echo "No changes to commit" git pull --rebase origin main git push origin main diff --git a/.gitignore b/.gitignore index 62fb74ff..95ba3643 100644 --- a/.gitignore +++ b/.gitignore @@ -37,5 +37,9 @@ temp-dummy-astro-project/ # Code quality reports jscpd-report/ -.claude/worktrees/ +# Website build artifacts +website/dist/ website/.astro/ +website/node_modules/ + +.claude/worktrees/ diff --git a/.vscode/settings.json b/.vscode/settings.json index 6d4da956..956d4d66 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,6 +6,7 @@ "css": "css" }, "files.associations": { - "*.css": "tailwindcss" + "*.css": "tailwindcss", + "*.mdx": "markdown" } } diff --git a/AGENTS.md b/AGENTS.md index 5c210d79..cc5fd036 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -22,6 +22,8 @@ - Comprehensive keyboard shortcuts and menu integration - Toast notifications throughout the app +**Note:** The `website/` directory is an independent project that uses **bun** (not pnpm). It is not part of the pnpm workspace. See `website/AGENTS.md` for its own instructions. + ## Core Rules ### New Sessions diff --git a/docs/tasks-done/task-2026-02-17-rework-website.md b/docs/tasks-done/task-2026-02-17-rework-website.md new file mode 100644 index 00000000..c332c606 --- /dev/null +++ b/docs/tasks-done/task-2026-02-17-rework-website.md @@ -0,0 +1,548 @@ +# Task: Replace Static Website with Starlight Documentation Site + +Replace the current static `index.html` in `website/` with an Astro + Starlight documentation site, modelled on the Taskdn project's website (`~/dev/taskdn/website/`). The homepage content stays essentially the same for now (Task 3 will redesign it). Documentation content is stub-only (Task 2 will write it). + +## Context + +- **Current state**: `website/` contains a static `index.html` (Tailwind CDN, dark theme, marketing page with feature sections, YouTube embed, download buttons), favicon assets, screenshot PNGs, and three installer binaries (`astro-editor-latest.{dmg,msi,AppImage}`). +- **Deployment**: Two GitHub Actions workflows: + - `deploy-website.yml` β deploys `website/` to GitHub Pages on push to `main` when `website/**` changes + - `publish-website-artifacts.yml` β on release publish, downloads binaries from the GH release, copies them as `astro-editor-latest.*` into `website/`, commits to `main`, triggers deploy +- **Domain**: `astroeditor.danny.is` (CNAME on GitHub Pages) +- **Analytics**: Simple Analytics (privacy-first, no cookies) +- **Reference**: Taskdn website at `~/dev/taskdn/website/` β same stack but multi-product (has `product` enum in schema, multiple sidebar sections). Astro Editor is single-product so simpler. +- **33 historical releases** on GitHub (v0.1.1 through v1.0.10). Release bodies range from minimal ("No user-facing changes") to rich markdown with images. Post-1.0.0 releases should all get changelog pages; pre-1.0.0 are case-by-case. + +## Follow-up Tasks + +- **Task 2** β Write actual documentation content (by hand with AI help, new screenshots) +- **Task 3** β Complete homepage redesign (rebuild `index.astro` from scratch with proper Astro features) + +--- + +## Phase 0: Repo Setup + +- [ ] Backup current website: `mv website/ website-old/` (git-tracked, recoverable) +- [ ] Add website build artifacts to root `.gitignore`: `website/dist/`, `website/.astro/`, `website/node_modules/` + +No GH Actions changes yet β they'll be broken on this branch which is fine. + +--- + +## Phase 1: Build Out Starlight Site [β DONE] + +Core scaffolding, config, and all structural pages. + +### 1.1 Scaffold & Dependencies + +- [ ] Scaffold Starlight project in `website/` using the CLI to get latest configs: + ```bash + npm create astro@latest -- --template starlight website + ``` + (`website/` won't exist after Phase 0 backup, so this should work directly) +- [ ] Ensure `package.json` has `"type": "module"` and standard scripts: + ```json + { + "scripts": { + "dev": "astro dev", + "start": "astro dev", + "build": "astro build", + "preview": "astro preview", + "astro": "astro", + "check": "astro check && tsc --noEmit && bun run lint && bun run format:check", + "lint": "eslint .", + "lint:fix": "eslint . --fix", + "format": "prettier --write .", + "format:check": "prettier --check ." + } + } + ``` +- [ ] Install runtime deps: `@astrojs/starlight`, `astro`, `sharp`, `starlight-theme-flexoki`, `starlight-llms-txt`, `starlight-kbd` +- [ ] Install dev deps: `@astrojs/check`, `typescript`, `eslint`, `@eslint/js`, `typescript-eslint`, `eslint-plugin-astro`, `prettier`, `prettier-plugin-astro` + +### 1.2 Configuration Files + +- [ ] `astro.config.mjs` β Starlight with: + - Site: `https://astroeditor.danny.is` + - Plugins: Flexoki theme (blue accent), llms.txt, kbd (macOS default + Windows) + - Title: `Astro Editor` + - Description: `Schema-aware markdown editor for Astro content collections` + - Footer component override + - Logo from `src/assets/` + - Favicon: `/favicon.png` + - Social: GitHub (`https://github.com/dannysmith/astro-editor`) + - Head: OG meta, Twitter card, Simple Analytics script + - Sidebar: Getting Started link + Releases link (expand in Phase 4) +- [ ] `tsconfig.json` β extends `astro/tsconfigs/strict`, path aliases (`@components`, `@layouts`, `@assets`) +- [ ] `eslint.config.js` β JS recommended + TS recommended + Astro recommended, ignoring `dist/`, `.astro/`, `node_modules/` +- [ ] `prettier.config.js` β no semi, single quotes, tab width 2, trailing comma es5, astro plugin +- [ ] `.prettierignore` β `dist/`, `.astro/`, `node_modules/`, `bun.lock`, `*.md`, `*.mdx` +- [ ] `website/.gitignore` β `dist/`, `.astro/`, `node_modules/`, `npm-debug.log*`, `.env`, `.env.production`, `.DS_Store` +- [ ] `website/AGENTS.md` β Starlight/Astro-specific AI instructions (build up over time). Include: Astro/Starlight version, key patterns, content conventions +- [ ] `website/CLAUDE.md` β just `@AGENTS.md` (same pattern as root project) + +### 1.3 Content Collection & Components + +- [ ] `src/content.config.ts` β docs collection with `date` field extension (no `product` field) +- [ ] `src/components/Footer.astro` β wraps Starlight default footer, adds copyright ("Danny Smith") + privacy policy link +- [ ] `src/layouts/Layout.astro` β standalone layout for non-Starlight pages (homepage). Flexoki palette, full meta tags, Simple Analytics. See reference implementation appendix below. + +### 1.4 Homepage + +- [ ] `src/pages/index.astro` β port current `index.html` content into Astro component using standalone `Layout.astro` + - Keep Tailwind CDN for now (Task 3 will handle properly) + - **Gotcha**: Inline ` + +
+