diff --git a/MIGRATION_PARITY.md b/MIGRATION_PARITY.md new file mode 100644 index 0000000..db23a52 --- /dev/null +++ b/MIGRATION_PARITY.md @@ -0,0 +1,66 @@ +# Astro Migration Parity Contract + +This document defines the "must match" behaviors and routes to keep the Astro +migration safe and low-risk. Changes outside this list are deferred until after +cutover. + +## Must Match + +### Routes (trailing slash preserved) +- `/` (home) +- `/about/` +- `/faq/` +- `/projects/` +- `/projects/gazette-protocol/` (draft content; see Draft Handling) +- `/projects/the-truth-post/` +- `/projects/prove-me-wrong/` (draft content; see Draft Handling) +- `/404/` (404 page) + +### Markdown Source + Frontmatter +Source files live in `src/pages/**/*.md` with frontmatter: +- `slug` (string, required) +- `draft` (boolean, optional) +- `toc` (boolean, optional) + +### Draft Handling +Current Gatsby behavior hides drafts in all environments because `process.env.ENV` +is undefined. For parity-first, drafts should remain hidden in production and +preview unless we explicitly opt-in to show them. + +### TOC Behavior +If `toc: true`, insert a list of `h2` headings immediately after the first `h1`. +Each entry links to the heading id (slugged). + +### SEO + Metadata +- Canonical/OG/Twitter tags match the current `Seo` component. +- `og:url` and canonical should use the deployment base URL. + - Production base: `https://proveuswrong.io/` + - Preview base: `CF_PAGES_URL` (Cloudflare Pages) +- `og:image` defaults to the site icon (`src/images/icon.png`). + +### Sitemap/Robots +- `sitemap.xml` available at `/sitemap.xml` +- `robots.txt` allows all (`User-agent: *`, `Allow: /`) + +### Assets + Paths +- Static files in `static/` are served from the site root: + - `/pressKit.zip` + - `/link.svg` + - `/linkRed.svg` +- Image assets in `src/images/` are used by layout and About page. + +### Styling +- SCSS modules and global styles must retain current visual output. + +## Open Decisions (post-parity) +- PWA manifest/offline support (currently in Gatsby, can be reintroduced later). +- Whether drafts should be visible in preview builds. +- Whether to keep React components or rewrite to native Astro. + +## Parity Check Results (Astro build) +- Routes rendered in `astro/dist`: `/`, `/about/`, `/faq/`, `/projects/`, `/projects/the-truth-post/`, `/404/`. +- Draft routes excluded from build output as expected (`/projects/gazette-protocol/`, `/projects/prove-me-wrong/`). +- TOC insertion verified on `/faq/` (list of `h2` links placed after first `h1`). +- SEO tags present on sampled pages (title, description, OG/Twitter, `og:url` uses `https://proveuswrong.io/`). +- Static assets verified in output root and `/images/` (press kit + icons + portraits). +- `sitemap.xml` now served as an index pointing to `/sitemap-0.xml` (fixes robots.txt parity). diff --git a/astro/.gitignore b/astro/.gitignore new file mode 100644 index 0000000..16d54bb --- /dev/null +++ b/astro/.gitignore @@ -0,0 +1,24 @@ +# build output +dist/ +# generated types +.astro/ + +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + + +# environment variables +.env +.env.production + +# macOS-specific files +.DS_Store + +# jetbrains setting folder +.idea/ diff --git a/astro/.vscode/extensions.json b/astro/.vscode/extensions.json new file mode 100644 index 0000000..22a1505 --- /dev/null +++ b/astro/.vscode/extensions.json @@ -0,0 +1,4 @@ +{ + "recommendations": ["astro-build.astro-vscode"], + "unwantedRecommendations": [] +} diff --git a/astro/.vscode/launch.json b/astro/.vscode/launch.json new file mode 100644 index 0000000..d642209 --- /dev/null +++ b/astro/.vscode/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "command": "./node_modules/.bin/astro dev", + "name": "Development server", + "request": "launch", + "type": "node-terminal" + } + ] +} diff --git a/astro/README.md b/astro/README.md new file mode 100644 index 0000000..7264f40 --- /dev/null +++ b/astro/README.md @@ -0,0 +1,43 @@ +# Astro Starter Kit: Minimal + +```sh +yarn create astro@latest -- --template minimal +``` + +> πŸ§‘β€πŸš€ **Seasoned astronaut?** Delete this file. Have fun! + +## πŸš€ Project Structure + +Inside of your Astro project, you'll see the following folders and files: + +```text +/ +β”œβ”€β”€ public/ +β”œβ”€β”€ src/ +β”‚ └── pages/ +β”‚ └── index.astro +└── package.json +``` + +Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name. + +There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components. + +Any static assets, like images, can be placed in the `public/` directory. + +## 🧞 Commands + +All commands are run from the root of the project, from a terminal: + +| Command | Action | +| :------------------------ | :----------------------------------------------- | +| `yarn install` | Installs dependencies | +| `yarn dev` | Starts local dev server at `localhost:4321` | +| `yarn build` | Build your production site to `./dist/` | +| `yarn preview` | Preview your build locally, before deploying | +| `yarn astro ...` | Run CLI commands like `astro add`, `astro check` | +| `yarn astro -- --help` | Get help using the Astro CLI | + +## πŸ‘€ Want to learn more? + +Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat). diff --git a/astro/astro.config.mjs b/astro/astro.config.mjs new file mode 100644 index 0000000..b1e394a --- /dev/null +++ b/astro/astro.config.mjs @@ -0,0 +1,31 @@ +// @ts-check +import { defineConfig } from "astro/config"; +import cloudflare from "@astrojs/cloudflare"; +import react from "@astrojs/react"; +import sitemap from "@astrojs/sitemap"; +import remarkTocAfterH1 from "./src/lib/remark-toc-after-h1.js"; + +const isProd = + process.env.CF_PAGES_ENVIRONMENT === "production" || + process.env.NODE_ENV === "production"; +const site = + process.env.SITE_URL || + (isProd + ? "https://proveuswrong.io" + : process.env.CF_PAGES_URL || "http://localhost:4321"); + +// https://astro.build/config +export default defineConfig({ + build: { + format: "directory", + }, + trailingSlash: "always", + site, + integrations: [react(), sitemap()], + adapter: cloudflare({ + mode: "static", + }), + markdown: { + remarkPlugins: [remarkTocAfterH1], + }, +}); diff --git a/astro/package.json b/astro/package.json new file mode 100644 index 0000000..dbe7e99 --- /dev/null +++ b/astro/package.json @@ -0,0 +1,26 @@ +{ + "name": "astro", + "type": "module", + "version": "0.0.1", + "scripts": { + "dev": "astro dev", + "build": "astro build", + "preview": "astro preview", + "astro": "astro" + }, + "dependencies": { + "@astrojs/cloudflare": "^12.6.12", + "@astrojs/react": "^4.4.2", + "@astrojs/sitemap": "^3.6.0", + "astro": "^5.16.6", + "github-slugger": "^2.0.0", + "react": "^19.2.3", + "react-dom": "^19.2.3", + "sass": "^1.97.1", + "unist-util-visit": "^5.0.0" + }, + "devDependencies": { + "@types/react": "^19", + "@types/react-dom": "^19" + } +} diff --git a/astro/src/components/Footer.jsx b/astro/src/components/Footer.jsx new file mode 100644 index 0000000..e8dfcf7 --- /dev/null +++ b/astro/src/components/Footer.jsx @@ -0,0 +1,99 @@ +import * as React from "react"; +import * as styles from "./footer.module.scss"; +import githubIcon from "../icons/github.svg?raw"; +import twitterIcon from "../icons/twitter.svg?raw"; +import emailIcon from "../icons/email.svg?raw"; +import angelIcon from "../icons/angel.svg?raw"; +import discordIcon from "../icons/discord.svg?raw"; +import linkedInIcon from "../icons/linkedin.svg?raw"; +import pressKitIcon from "../icons/pressKit.svg?raw"; + +const InlineSvg = ({ svg, id }) => ( +