Skip to content

Commit 1340fba

Browse files
bholmesdevoz-agent
andcommitted
feat(www): SEO & AEO audit — structured data, meta tags, robots.txt
- Add site URL to astro.config.mjs for sitemap generation and canonical URLs - Add robots.txt with sitemap reference - Add JSON-LD structured data via custom Head component override: - WebSite + Organization schema on all pages - SoftwareSourceCode schema on active package pages (store, scope, query) - BreadcrumbList schema on all non-home pages - Add Open Graph and Twitter Card meta tags to all active pages - Improve meta descriptions for better SERP click-through rates - Add noindex to deprecated pages (stream, form/*) - Clean up emoji from titles for consistent SERP display - Rewrite homepage intro for AEO (answer-first content structure) Co-Authored-By: Oz <oz-agent@warp.dev>
1 parent 70cb101 commit 1340fba

11 files changed

Lines changed: 232 additions & 20 deletions

File tree

www/astro.config.mjs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@ import starlight from "@astrojs/starlight";
22
import { defineConfig } from "astro/config";
33

44
export default defineConfig({
5+
site: "https://simplestack.dev",
56
integrations: [
67
starlight({
7-
title: "Simple Stack 🌱",
8+
title: "Simple Stack",
9+
components: {
10+
Head: "./src/components/Head.astro",
11+
},
812
social: [
913
{
1014
icon: "github",

www/public/robots.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
User-agent: *
2+
Allow: /
3+
4+
Sitemap: https://simplestack.dev/sitemap-index.xml

www/src/components/Head.astro

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
---
2+
import Default from "@astrojs/starlight/components/Head.astro";
3+
4+
const route = Astro.locals.starlightRoute;
5+
const title = route?.entry?.data?.title ?? "";
6+
const description = route?.entry?.data?.description ?? "";
7+
const siteUrl = "https://simplestack.dev";
8+
const canonicalUrl = new URL(Astro.url.pathname, siteUrl).href;
9+
10+
// WebSite + Organization schema (all pages)
11+
const websiteSchema = {
12+
"@context": "https://schema.org",
13+
"@type": "WebSite",
14+
name: "Simple Stack",
15+
url: siteUrl,
16+
description:
17+
"A collection of lightweight, focused tools for Astro and Vite — including a reactive store, scoped IDs, and DOM query utilities.",
18+
publisher: {
19+
"@type": "Organization",
20+
name: "Simple Stack",
21+
url: siteUrl,
22+
sameAs: [
23+
"https://github.com/bholmesdev/simple-stack",
24+
"https://wtw.dev/chat",
25+
],
26+
},
27+
};
28+
29+
// Determine page type from URL pathname
30+
const pathname = Astro.url.pathname.replace(/^\/|\/$|index\.html$/g, "");
31+
const isPackagePage =
32+
pathname === "store" || pathname === "scope" || pathname === "query";
33+
const isHomePage = pathname === "";
34+
35+
// SoftwareSourceCode schema for active package pages
36+
const packageMeta: Record<string, { repo: string; npm: string }> = {
37+
store: {
38+
repo: "https://github.com/bholmesdev/simplestack-store",
39+
npm: "https://www.npmjs.com/package/@simplestack/store",
40+
},
41+
scope: {
42+
repo: "https://github.com/bholmesdev/simplestack-scope",
43+
npm: "https://www.npmjs.com/package/vite-plugin-simple-scope",
44+
},
45+
query: {
46+
repo: "https://github.com/bholmesdev/simplestack-query",
47+
npm: "https://www.npmjs.com/package/@simplestack/query",
48+
},
49+
};
50+
51+
const softwareSchema = isPackagePage
52+
? {
53+
"@context": "https://schema.org",
54+
"@type": "SoftwareSourceCode",
55+
name: title,
56+
description: description,
57+
url: canonicalUrl,
58+
codeRepository: packageMeta[pathname]?.repo,
59+
programmingLanguage: ["TypeScript", "JavaScript"],
60+
runtimePlatform: "Node.js",
61+
author: {
62+
"@type": "Person",
63+
name: "Ben Holmes",
64+
url: "https://bholmes.dev",
65+
},
66+
}
67+
: null;
68+
69+
// BreadcrumbList schema for non-home pages
70+
const breadcrumbSchema = !isHomePage
71+
? {
72+
"@context": "https://schema.org",
73+
"@type": "BreadcrumbList",
74+
itemListElement: [
75+
{
76+
"@type": "ListItem",
77+
position: 1,
78+
name: "Home",
79+
item: siteUrl,
80+
},
81+
{
82+
"@type": "ListItem",
83+
position: 2,
84+
name: title,
85+
item: canonicalUrl,
86+
},
87+
],
88+
}
89+
: null;
90+
91+
const schemas = [websiteSchema, softwareSchema, breadcrumbSchema].filter(
92+
Boolean,
93+
);
94+
---
95+
96+
<Default {...Astro.props} />
97+
{
98+
schemas.map((schema) => (
99+
<script type="application/ld+json" set:html={JSON.stringify(schema)} />
100+
))
101+
}

www/src/content/docs/form/client.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
---
2-
title: Add client validation
3-
description: Add client validation to your forms
2+
title: Add Client Validation (Deprecated)
3+
description: "Add client-side form validation using the reward-early, punish-late pattern. This package is deprecated — use Astro Form Actions instead."
44
sidebar:
55
order: 3
6+
head:
7+
- tag: meta
8+
attrs:
9+
name: robots
10+
content: noindex, nofollow
611
---
712

813
:::caution

www/src/content/docs/form/index.mdx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
---
2-
title: Simple form
3-
description: The simple way to validate forms in your fullstack app.
2+
title: Simple Form (Deprecated)
3+
description: "Server and client form validation for Astro with Zod schemas. This package is deprecated — use Astro Form Actions instead."
44
sidebar:
55
label: Get started
66
order: 1
7+
head:
8+
- tag: meta
9+
attrs:
10+
name: robots
11+
content: noindex, nofollow
712
---
813

914
import { Tabs, TabItem } from '@astrojs/starlight/components';

www/src/content/docs/form/parse.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
---
2-
title: Parse form requests
3-
description: Validate forms server-side
2+
title: Parse Form Requests (Deprecated)
3+
description: "Server-side form validation and parsing with Zod schemas in Astro. This package is deprecated — use Astro Form Actions instead."
44
sidebar:
55
order: 2
6+
head:
7+
- tag: meta
8+
attrs:
9+
name: robots
10+
content: noindex, nofollow
611
---
712

813
:::caution

www/src/content/docs/index.mdx

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,35 @@
11
---
2-
title: Simple stack 🌱
3-
description: A suite of tools built for Astro to simplify your workflow.
2+
title: Simple Stack
3+
description: Simple Stack is a collection of lightweight, focused tools for Astro and Vite — including a reactive store, scoped IDs, and DOM query utilities.
44
tableOfContents: false
55
head:
66
- tag: title
7-
content: Simple stack 🌱
7+
content: Simple Stack — Lightweight Tools for Astro & Vite
8+
- tag: meta
9+
attrs:
10+
property: og:title
11+
content: Simple Stack — Lightweight Tools for Astro & Vite
12+
- tag: meta
13+
attrs:
14+
property: og:description
15+
content: A collection of lightweight, focused tools for Astro and Vite — including a reactive store, scoped IDs, and DOM query utilities.
16+
- tag: meta
17+
attrs:
18+
property: og:type
19+
content: website
20+
- tag: meta
21+
attrs:
22+
property: og:url
23+
content: https://simplestack.dev/
24+
- tag: meta
25+
attrs:
26+
name: twitter:card
27+
content: summary
828
---
929

10-
A collection of tools I've built to **make web development simpler.**
30+
**Simple Stack** is a collection of lightweight, open-source JavaScript tools for [Astro](https://astro.build) and [Vite](https://vite.dev) projects. Each package solves one focused use case without unnecessary complexity — a reactive store with selector support, build-time scoped IDs, and a DOM query library for Astro components.
1131

12-
To be honest, there isn't a "story" connecting these packages together (I'm no TanStack). But they follow a common theme: solve a simple use case without too many features.
32+
All packages are written in TypeScript, work with popular frameworks like React and Next.js, and are designed to ship minimal client-side JavaScript.
1333

1434
import { CardGrid, Card, LinkCard } from '@astrojs/starlight/components';
1535

www/src/content/docs/query.mdx

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,27 @@
11
---
2-
title: 💰 Simple Query
3-
description: A simple library to query the DOM from your Astro components.
2+
title: Simple Query
3+
description: "A lightweight DOM query library for Astro components with scoped selectors, signal-based state, and server data passing. No framework overhead."
4+
head:
5+
- tag: meta
6+
attrs:
7+
property: og:title
8+
content: Simple Query — Lightweight DOM Queries for Astro
9+
- tag: meta
10+
attrs:
11+
property: og:description
12+
content: A lightweight DOM query library for Astro components with scoped selectors, signal-based state, and server data passing.
13+
- tag: meta
14+
attrs:
15+
property: og:type
16+
content: article
17+
- tag: meta
18+
attrs:
19+
property: og:url
20+
content: https://simplestack.dev/query/
21+
- tag: meta
22+
attrs:
23+
name: twitter:card
24+
content: summary
425
---
526

627
import { Tabs, TabItem, LinkCard } from '@astrojs/starlight/components';

www/src/content/docs/scope.mdx

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,27 @@
11
---
2-
title: 🔎 Simple scope
3-
description: Get a scoped ID for whatever file you're in. Resolved at build-time with zero client JS.
2+
title: Simple Scope
3+
description: "A Vite plugin that generates scoped IDs for any file at build-time with zero client JavaScript. Perfect for form labels, query selectors, and hydration-safe IDs."
4+
head:
5+
- tag: meta
6+
attrs:
7+
property: og:title
8+
content: Simple Scope — Build-Time Scoped IDs for Vite
9+
- tag: meta
10+
attrs:
11+
property: og:description
12+
content: A Vite plugin that generates scoped IDs for any file at build-time with zero client JavaScript. Perfect for form labels and query selectors.
13+
- tag: meta
14+
attrs:
15+
property: og:type
16+
content: article
17+
- tag: meta
18+
attrs:
19+
property: og:url
20+
content: https://simplestack.dev/scope/
21+
- tag: meta
22+
attrs:
23+
name: twitter:card
24+
content: summary
425
---
526

627
import { LinkCard } from '@astrojs/starlight/components';

www/src/content/docs/store.mdx

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,30 @@
11
---
2-
title: 💾 Simple store
3-
description: A reactive store that combines the simplicity of signals with the power of "selectors" you'd find in Zustand or Redux.
2+
title: Simple Store
3+
description: "A reactive store for JavaScript that combines the simplicity of signals with Zustand-style selectors. Works with React, Vite, and Next.js."
44
sidebar:
55
label: Get started
66
order: 1
7+
head:
8+
- tag: meta
9+
attrs:
10+
property: og:title
11+
content: Simple Store — Reactive State with Signals & Selectors
12+
- tag: meta
13+
attrs:
14+
property: og:description
15+
content: A reactive store for JavaScript that combines the simplicity of signals with Zustand-style selectors. Works with React, Vite, and Next.js.
16+
- tag: meta
17+
attrs:
18+
property: og:type
19+
content: article
20+
- tag: meta
21+
attrs:
22+
property: og:url
23+
content: https://simplestack.dev/store/
24+
- tag: meta
25+
attrs:
26+
name: twitter:card
27+
content: summary
728
---
829

930
import { LinkCard, Tabs, TabItem } from '@astrojs/starlight/components';

0 commit comments

Comments
 (0)