Ryan Malloy b892189f21 Add SEO infrastructure: sitemap, OG meta, JSON-LD, custom 404
- Integrate @astrojs/sitemap for automatic sitemap generation
- Add robots.txt with sitemap reference
- Add Open Graph and Twitter Card meta tags to Layout
- Add canonical URL and structured data slot to Layout
- Add JSON-LD schema (WebSite, CollectionPage, Book, BreadcrumbList)
- Create custom 404 page with navigation links
- Create default OG image (SVG with graph-paper theme)
- Wire SITE_URL through Docker build args for production builds
- Update Caddyfile for proper 404 handling instead of SPA fallback
2026-02-13 07:32:57 -07:00

92 lines
4.2 KiB
Plaintext

---
import Layout from '@/layouts/Layout.astro';
import FilterableBookGrid from '@/components/FilterableBookGrid';
import { getCollection } from 'astro:content';
import { serializeBook } from '@/lib/types';
import type { WithContext, CollectionPage } from 'schema-dts';
const allBooks = await getCollection('books');
const uglysBooks = allBooks
.filter(book => book.data.collection === 'uglys')
.sort((a, b) => a.data.sortOrder - b.data.sortOrder);
// Get unique topics for filtering
const allTopics = [...new Set(uglysBooks.flatMap(book => book.data.topics))].sort();
const serializedBooks = uglysBooks.map(serializeBook);
const siteUrl = import.meta.env.SITE || 'https://forrest.warehack.ing';
const jsonLd: WithContext<CollectionPage> = {
'@context': 'https://schema.org',
'@type': 'CollectionPage',
name: "Ugly's Electrical References",
description: 'The essential pocket reference for electricians - tables, formulas, and NEC code references',
url: `${siteUrl}/uglys`,
numberOfItems: uglysBooks.length,
};
---
<Layout
title="Ugly's Electrical References"
description="The essential pocket reference for electricians - packed with tables, formulas, and NEC code references"
>
<Fragment slot="structured-data">
<script type="application/ld+json" set:html={JSON.stringify(jsonLd)} />
</Fragment>
<div class="space-y-8">
<!-- Header -->
<div class="space-y-4">
<div class="flex items-center gap-2 text-sm text-muted-foreground">
<a href="/" class="hover:text-foreground transition-colors">Home</a>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="9 18 15 12 9 6"/>
</svg>
<span>Ugly's Collection</span>
</div>
<div class="flex flex-col md:flex-row md:items-end justify-between gap-4">
<div>
<h1 class="text-3xl md:text-4xl font-bold title-accent">
Ugly's Electrical References
</h1>
<p class="text-muted-foreground mt-2 max-w-2xl">
The pocket-sized bible for electricians. Packed with tables, formulas, wiring diagrams,
NEC code references, and quick calculations for electrical work. An essential field reference.
</p>
</div>
<div class="flex items-center gap-2 text-sm text-muted-foreground">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/>
<path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/>
</svg>
<span>{uglysBooks.length} reference{uglysBooks.length !== 1 ? 's' : ''}</span>
</div>
</div>
</div>
<!-- Filterable grid with topic tags -->
<FilterableBookGrid books={serializedBooks} allTopics={allTopics} collectionSlug="uglys" client:load />
<!-- Info box -->
<div class="mt-12 p-6 rounded-lg bg-card border border-border">
<div class="flex items-start gap-4">
<div class="w-10 h-10 rounded-lg bg-chart-2/20 flex items-center justify-center shrink-0">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-chart-2">
<path d="M13 2 3 14h9l-1 8 10-12h-9l1-8z"/>
</svg>
</div>
<div>
<h3 class="font-semibold text-foreground">About This Collection</h3>
<p class="text-sm text-muted-foreground mt-1">
Ugly's Electrical References has been the go-to pocket reference for electricians since 1970.
This spiral-bound guide fits in your back pocket and contains everything you need on the
job site - wire ampacities, conduit fill tables, motor calculations, NEC code references,
and much more. Like the Mims notebooks, this is practical, no-nonsense reference material
that gets the job done.
</p>
</div>
</div>
</div>
</div>
</Layout>