Skip to content

Commit 219f200

Browse files
committed
Add Astro parity migration scaffold
1 parent 2a63dcd commit 219f200

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+7723
-0
lines changed

MIGRATION_PARITY.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Astro Migration Parity Contract
2+
3+
This document defines the "must match" behaviors and routes to keep the Astro
4+
migration safe and low-risk. Changes outside this list are deferred until after
5+
cutover.
6+
7+
## Must Match
8+
9+
### Routes (trailing slash preserved)
10+
- `/` (home)
11+
- `/about/`
12+
- `/faq/`
13+
- `/projects/`
14+
- `/projects/gazette-protocol/` (draft content; see Draft Handling)
15+
- `/projects/the-truth-post/`
16+
- `/projects/prove-me-wrong/` (draft content; see Draft Handling)
17+
- `/404/` (404 page)
18+
19+
### Markdown Source + Frontmatter
20+
Source files live in `src/pages/**/*.md` with frontmatter:
21+
- `slug` (string, required)
22+
- `draft` (boolean, optional)
23+
- `toc` (boolean, optional)
24+
25+
### Draft Handling
26+
Current Gatsby behavior hides drafts in all environments because `process.env.ENV`
27+
is undefined. For parity-first, drafts should remain hidden in production and
28+
preview unless we explicitly opt-in to show them.
29+
30+
### TOC Behavior
31+
If `toc: true`, insert a list of `h2` headings immediately after the first `h1`.
32+
Each entry links to the heading id (slugged).
33+
34+
### SEO + Metadata
35+
- Canonical/OG/Twitter tags match the current `Seo` component.
36+
- `og:url` and canonical should use the deployment base URL.
37+
- Production base: `https://proveuswrong.io/`
38+
- Preview base: `CF_PAGES_URL` (Cloudflare Pages)
39+
- `og:image` defaults to the site icon (`src/images/icon.png`).
40+
41+
### Sitemap/Robots
42+
- `sitemap.xml` available at `/sitemap.xml`
43+
- `robots.txt` allows all (`User-agent: *`, `Allow: /`)
44+
45+
### Assets + Paths
46+
- Static files in `static/` are served from the site root:
47+
- `/pressKit.zip`
48+
- `/link.svg`
49+
- `/linkRed.svg`
50+
- Image assets in `src/images/` are used by layout and About page.
51+
52+
### Styling
53+
- SCSS modules and global styles must retain current visual output.
54+
55+
## Open Decisions (post-parity)
56+
- PWA manifest/offline support (currently in Gatsby, can be reintroduced later).
57+
- Whether drafts should be visible in preview builds.
58+
- Whether to keep React components or rewrite to native Astro.
59+
60+
## Parity Check Results (Astro build)
61+
- Routes rendered in `astro/dist`: `/`, `/about/`, `/faq/`, `/projects/`, `/projects/the-truth-post/`, `/404/`.
62+
- Draft routes excluded from build output as expected (`/projects/gazette-protocol/`, `/projects/prove-me-wrong/`).
63+
- TOC insertion verified on `/faq/` (list of `h2` links placed after first `h1`).
64+
- SEO tags present on sampled pages (title, description, OG/Twitter, `og:url` uses `https://proveuswrong.io/`).
65+
- Static assets verified in output root and `/images/` (press kit + icons + portraits).
66+
- `sitemap.xml` now served as an index pointing to `/sitemap-0.xml` (fixes robots.txt parity).

astro/.gitignore

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# build output
2+
dist/
3+
# generated types
4+
.astro/
5+
6+
# dependencies
7+
node_modules/
8+
9+
# logs
10+
npm-debug.log*
11+
yarn-debug.log*
12+
yarn-error.log*
13+
pnpm-debug.log*
14+
15+
16+
# environment variables
17+
.env
18+
.env.production
19+
20+
# macOS-specific files
21+
.DS_Store
22+
23+
# jetbrains setting folder
24+
.idea/

astro/.vscode/extensions.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"recommendations": ["astro-build.astro-vscode"],
3+
"unwantedRecommendations": []
4+
}

astro/.vscode/launch.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"version": "0.2.0",
3+
"configurations": [
4+
{
5+
"command": "./node_modules/.bin/astro dev",
6+
"name": "Development server",
7+
"request": "launch",
8+
"type": "node-terminal"
9+
}
10+
]
11+
}

astro/README.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Astro Starter Kit: Minimal
2+
3+
```sh
4+
yarn create astro@latest -- --template minimal
5+
```
6+
7+
> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun!
8+
9+
## 🚀 Project Structure
10+
11+
Inside of your Astro project, you'll see the following folders and files:
12+
13+
```text
14+
/
15+
├── public/
16+
├── src/
17+
│ └── pages/
18+
│ └── index.astro
19+
└── package.json
20+
```
21+
22+
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
23+
24+
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
25+
26+
Any static assets, like images, can be placed in the `public/` directory.
27+
28+
## 🧞 Commands
29+
30+
All commands are run from the root of the project, from a terminal:
31+
32+
| Command | Action |
33+
| :------------------------ | :----------------------------------------------- |
34+
| `yarn install` | Installs dependencies |
35+
| `yarn dev` | Starts local dev server at `localhost:4321` |
36+
| `yarn build` | Build your production site to `./dist/` |
37+
| `yarn preview` | Preview your build locally, before deploying |
38+
| `yarn astro ...` | Run CLI commands like `astro add`, `astro check` |
39+
| `yarn astro -- --help` | Get help using the Astro CLI |
40+
41+
## 👀 Want to learn more?
42+
43+
Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).

astro/astro.config.mjs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// @ts-check
2+
import { defineConfig } from "astro/config";
3+
import cloudflare from "@astrojs/cloudflare";
4+
import react from "@astrojs/react";
5+
import sitemap from "@astrojs/sitemap";
6+
import remarkTocAfterH1 from "./src/lib/remark-toc-after-h1.js";
7+
8+
const isProd =
9+
process.env.CF_PAGES_ENVIRONMENT === "production" ||
10+
process.env.NODE_ENV === "production";
11+
const site =
12+
process.env.SITE_URL ||
13+
(isProd
14+
? "https://proveuswrong.io"
15+
: process.env.CF_PAGES_URL || "http://localhost:4321");
16+
17+
// https://astro.build/config
18+
export default defineConfig({
19+
build: {
20+
format: "directory",
21+
},
22+
trailingSlash: "always",
23+
site,
24+
integrations: [react(), sitemap()],
25+
adapter: cloudflare({
26+
mode: "static",
27+
}),
28+
markdown: {
29+
remarkPlugins: [remarkTocAfterH1],
30+
},
31+
});

astro/package.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"name": "astro",
3+
"type": "module",
4+
"version": "0.0.1",
5+
"scripts": {
6+
"dev": "astro dev",
7+
"build": "astro build",
8+
"preview": "astro preview",
9+
"astro": "astro"
10+
},
11+
"dependencies": {
12+
"@astrojs/cloudflare": "^12.6.12",
13+
"@astrojs/react": "^4.4.2",
14+
"@astrojs/sitemap": "^3.6.0",
15+
"astro": "^5.16.6",
16+
"github-slugger": "^2.0.0",
17+
"react": "^19.2.3",
18+
"react-dom": "^19.2.3",
19+
"sass": "^1.97.1",
20+
"unist-util-visit": "^5.0.0"
21+
},
22+
"devDependencies": {
23+
"@types/react": "^19",
24+
"@types/react-dom": "^19"
25+
}
26+
}

astro/src/components/Footer.jsx

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import * as React from "react";
2+
import * as styles from "./footer.module.scss";
3+
import githubIcon from "../icons/github.svg?raw";
4+
import twitterIcon from "../icons/twitter.svg?raw";
5+
import emailIcon from "../icons/email.svg?raw";
6+
import angelIcon from "../icons/angel.svg?raw";
7+
import discordIcon from "../icons/discord.svg?raw";
8+
import linkedInIcon from "../icons/linkedin.svg?raw";
9+
import pressKitIcon from "../icons/pressKit.svg?raw";
10+
11+
const InlineSvg = ({ svg, id }) => (
12+
<span
13+
aria-hidden="true"
14+
id={id}
15+
dangerouslySetInnerHTML={{ __html: svg }}
16+
/>
17+
);
18+
19+
const Footer = () => (
20+
<footer>
21+
<div className={styles.container}>
22+
<div className={styles.social}>
23+
<a
24+
href="https://www.linkedin.com/company/prove-us-wrong/"
25+
target="_blank"
26+
rel="noopener noreferrer"
27+
title='LinkedIn Company Page'
28+
>
29+
<span style={{ display: "none" }}>Link to LinkedIn profile</span>
30+
<InlineSvg svg={linkedInIcon} id="linkedin" />
31+
</a>
32+
<a
33+
href="https://angel.co/company/prove-us-wrong"
34+
target="_blank"
35+
rel="noopener noreferrer"
36+
title='AngelList Page'
37+
>
38+
<span style={{ display: "none" }}>Link to AngelList profile</span>
39+
<InlineSvg svg={angelIcon} id="angel" />
40+
</a>
41+
42+
<a
43+
href="https://twitter.com/ProveUsWrongIO"
44+
target="_blank"
45+
rel="noopener noreferrer"
46+
title='Twitter Page'
47+
>
48+
<span style={{ display: "none" }}>Link to Twitter profile</span>
49+
<InlineSvg svg={twitterIcon} id="twitter" />
50+
</a>
51+
52+
53+
<a
54+
href="https://discord.gg/FvDrdDtYAV"
55+
target="_blank"
56+
rel="noopener noreferrer"
57+
title='Discord Community'
58+
>
59+
<span style={{ display: "none" }}>Link to Discord community</span>
60+
<InlineSvg svg={discordIcon} id="discord" />
61+
</a>
62+
<a
63+
href="https://github.com/proveuswrong"
64+
target="_blank"
65+
rel="noopener noreferrer"
66+
title='GitHub Organization'
67+
>
68+
<span style={{ display: "none" }}>Link to GitHub profile</span>
69+
<InlineSvg svg={githubIcon} id="github" />
70+
</a>
71+
72+
<a
73+
href="mailto:inbox@proveuswrong.io"
74+
target="_blank"
75+
rel="noopener noreferrer"
76+
title='E-mail Address'
77+
>
78+
<span style={{ display: "none" }}>Link to e-mail address</span>
79+
<InlineSvg svg={emailIcon} id="email" />
80+
</a>
81+
<a
82+
href="/pressKit.zip"
83+
target="_blank"
84+
rel="noopener noreferrer"
85+
title='Press Kit'
86+
>
87+
<span style={{ display: "none" }}>Press Kit</span>
88+
<InlineSvg svg={pressKitIcon} id="pressKit" />
89+
</a>
90+
</div>
91+
92+
<small>Copyright {new Date().getFullYear()} Prove Us Wrong</small>
93+
<small>This site is powered by <a target="_blank" rel="noopener noreferrer" href="https://pages.cloudflare.com/">Cloudflare Pages</a></small>
94+
95+
</div>
96+
</footer>
97+
);
98+
99+
export default Footer;

astro/src/components/Hamburger.jsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import * as React from "react";
2+
3+
import * as styles from "./hamburger.module.scss";
4+
5+
const handleHamburgerClick = (e) => {
6+
document.getElementById("toggle").classList.toggle(styles.active);
7+
8+
document.getElementById("overlay").classList.toggle("open");
9+
};
10+
11+
const Hamburger = () => {
12+
return (
13+
<div
14+
className={styles.button_container}
15+
id="toggle"
16+
onClick={handleHamburgerClick}
17+
onKeyDown={handleHamburgerClick}
18+
role="button"
19+
>
20+
<span className={styles.top}></span>
21+
<span className={styles.middle}></span>
22+
<span className={styles.bottom}></span>
23+
</div>
24+
);
25+
};
26+
27+
export default Hamburger;

0 commit comments

Comments
 (0)