Skip to content

Commit 473ebb8

Browse files
committed
feat(site): SEO/agent-readiness, author footer, custom domain + Pages deploy
Emit per-page discovery metadata (canonical, robots, OpenGraph, Twitter cards, JSON-LD WebSite/Person/Book and TechArticle/BreadcrumbList), favicons and app icons, web manifest, robots.txt, sitemap.xml, llms.txt/llms-full.txt and a 404 page from site/generate.py so they survive rebuilds. Regenerate the cover without the gh-aw version line and derive a 1200x630 og-image.png. Switch the canonical origin to https://aw.isainative.dev (CNAME + README). Replace the footer with author credit (Maxim Salnikov) and remove the 'built by a fleet' references (delete orchestration.html). Add a GitHub Actions workflow to build and deploy site/ to GitHub Pages.
1 parent afb4482 commit 473ebb8

37 files changed

Lines changed: 1275 additions & 537 deletions

.github/workflows/deploy-pages.yml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
name: Deploy book to GitHub Pages
2+
3+
# Builds the static site from content/ with site/generate.py and publishes site/
4+
# to GitHub Pages. The committed images (cover, og-image, icons) are shipped as-is;
5+
# generate.py refreshes the HTML, sitemap, robots, manifest and llms files.
6+
7+
on:
8+
push:
9+
branches: [main]
10+
paths:
11+
- "site/**"
12+
- "content/**"
13+
- "assets/**"
14+
- "scripts/**"
15+
- ".github/workflows/deploy-pages.yml"
16+
workflow_dispatch:
17+
18+
# Least-privilege token; Pages deployment needs pages:write + id-token:write.
19+
permissions:
20+
contents: read
21+
pages: write
22+
id-token: write
23+
24+
# Allow one concurrent deployment; let in-progress production deploys finish.
25+
concurrency:
26+
group: pages
27+
cancel-in-progress: false
28+
29+
jobs:
30+
build:
31+
runs-on: ubuntu-latest
32+
steps:
33+
- name: Checkout
34+
uses: actions/checkout@v4
35+
36+
- name: Set up Python
37+
uses: actions/setup-python@v5
38+
with:
39+
python-version: "3.12"
40+
41+
- name: Regenerate site from content
42+
run: |
43+
python -m pip install --upgrade pip
44+
python -m pip install pyyaml
45+
python site/generate.py
46+
47+
- name: Configure Pages
48+
uses: actions/configure-pages@v5
49+
with:
50+
enablement: true
51+
52+
- name: Upload site artifact
53+
uses: actions/upload-pages-artifact@v3
54+
with:
55+
path: site
56+
57+
deploy:
58+
needs: build
59+
runs-on: ubuntu-latest
60+
environment:
61+
name: github-pages
62+
url: ${{ steps.deployment.outputs.page_url }}
63+
steps:
64+
- name: Deploy to GitHub Pages
65+
id: deployment
66+
uses: actions/deploy-pages@v4

README.md

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<p align="center">
2-
<a href="https://webmaxru.github.io/github-agentic-workflows-book/">
2+
<a href="https://aw.isainative.dev/">
33
<img src="assets/cover.png" alt="GitHub Agentic Workflows: An Interactive Book — Continuous AI for the repository's outer loop, written by the agentic fleet it teaches" width="100%">
44
</a>
55
</p>
66

77
<p align="center">
8-
<a href="https://webmaxru.github.io/github-agentic-workflows-book/"><strong>Read the book →</strong></a>
8+
<a href="https://aw.isainative.dev/"><strong>Read the book →</strong></a>
99
</p>
1010

1111
# GitHub Agentic Workflows — An Interactive Book
@@ -24,11 +24,7 @@ prompt) that collaborate under an orchestrator in a wave-based pipeline.
2424
> 🧬 **Built on the foundation of [`microsoft-agent-framework-playbook-fleets-generated` by Valentina Alto](https://github.com/Valentina-Alto/microsoft-agent-framework-playbook-fleets-generated)** — this project adapts that repository's fleet-of-primitives methodology and site tooling from the **Microsoft Agent Framework** to **GitHub Agentic Workflows**.
2525
2626
> 🛠️ **Build & preview locally:** the site is generated from `content/toc.yml` by `site/generate.py`
27-
> and served from `site/` (see [Run the book locally](#run-the-book-locally)). A published URL is TBD.
28-
29-
> 🤖 **See the fleet in action:** an **interactive orchestration wireframe** at
30-
> [`site/orchestration.html`](site/orchestration.html) animates the exact pipeline
31-
> (design → research → author → verify → review) that produces this book.
27+
> and served from `site/` (see [Run the book locally](#run-the-book-locally)). Published at <https://aw.isainative.dev/>.
3228
3329
---
3430

@@ -169,7 +165,6 @@ site/
169165
index.html # generated
170166
chapters/*.html # generated: one page per chapter in toc.yml
171167
assets/ # style.css + app.js
172-
orchestration.html # animated fleet wireframe
173168
scripts/
174169
run-fleet.ps1 # convenience launcher
175170
```

assets/cover.png

22.8 KB
Loading

assets/cover.svg

Lines changed: 2 additions & 3 deletions
Loading

scripts/generate-icons.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#!/usr/bin/env python3
2+
"""Generate favicons and app icons for the gh-aw book site from the brand mark.
3+
4+
Brand mark: a rounded square with a diagonal blue->green gradient and a dark "aw",
5+
matching the badge on assets/cover.svg and site/favicon.svg.
6+
7+
Outputs (into site/):
8+
favicon.ico 16/32/48 rounded badge (transparent corners), legacy fallback
9+
icon-192.png 192x192 rounded badge, transparent (PWA "any")
10+
icon-512.png 512x512 rounded badge, transparent (PWA "any")
11+
apple-touch-icon.png 180x180 full-bleed gradient, opaque (iOS masks the corners)
12+
icon-maskable-512.png 512x512 full-bleed gradient, opaque, safe padding (PWA maskable)
13+
14+
favicon.svg is authored by hand (scalable) and committed alongside these rasters.
15+
Reproducible: `python scripts/generate-icons.py` (requires Pillow). Commit the output.
16+
"""
17+
from __future__ import annotations
18+
19+
from pathlib import Path
20+
21+
from PIL import Image, ImageDraw, ImageFont
22+
23+
ROOT = Path(__file__).resolve().parents[1]
24+
SITE = ROOT / "site"
25+
26+
BLUE = (0x78, 0xA6, 0xFF)
27+
GREEN = (0x4A, 0xDE, 0x80)
28+
INK = (0x0B, 0x10, 0x20)
29+
SS = 4 # supersample factor for crisp edges + text
30+
31+
32+
def _font(px: int) -> ImageFont.FreeTypeFont:
33+
candidates = (
34+
"consolab.ttf", "arialbd.ttf", "seguisb.ttf",
35+
r"C:\Windows\Fonts\consolab.ttf", r"C:\Windows\Fonts\arialbd.ttf",
36+
)
37+
for name in candidates:
38+
try:
39+
return ImageFont.truetype(name, px)
40+
except OSError:
41+
continue
42+
return ImageFont.load_default()
43+
44+
45+
def _gradient(size: int) -> Image.Image:
46+
"""Diagonal blue->green gradient at `size`x`size` (built small, scaled up)."""
47+
base = 128
48+
grad = Image.new("RGB", (base, base))
49+
px = grad.load()
50+
maxd = 2 * (base - 1) or 1
51+
for y in range(base):
52+
for x in range(base):
53+
t = (x + y) / maxd
54+
px[x, y] = (
55+
round(BLUE[0] + (GREEN[0] - BLUE[0]) * t),
56+
round(BLUE[1] + (GREEN[1] - BLUE[1]) * t),
57+
round(BLUE[2] + (GREEN[2] - BLUE[2]) * t),
58+
)
59+
return grad.resize((size, size), Image.BILINEAR)
60+
61+
62+
def _draw_aw(img: Image.Image, frac: float) -> None:
63+
draw = ImageDraw.Draw(img)
64+
size = img.width
65+
font = _font(round(size * frac))
66+
bbox = draw.textbbox((0, 0), "aw", font=font)
67+
w, h = bbox[2] - bbox[0], bbox[3] - bbox[1]
68+
draw.text(((size - w) / 2 - bbox[0], (size - h) / 2 - bbox[1]), "aw", font=font, fill=INK)
69+
70+
71+
def badge(size: int) -> Image.Image:
72+
"""Rounded-square gradient badge with transparent corners (RGBA)."""
73+
s = size * SS
74+
grad = _gradient(s).convert("RGBA")
75+
mask = Image.new("L", (s, s), 0)
76+
ImageDraw.Draw(mask).rounded_rectangle([0, 0, s - 1, s - 1], radius=round(s * 0.22), fill=255)
77+
out = Image.new("RGBA", (s, s), (0, 0, 0, 0))
78+
out.paste(grad, (0, 0), mask)
79+
_draw_aw(out, 0.5)
80+
return out.resize((size, size), Image.LANCZOS)
81+
82+
83+
def fullbleed(size: int, aw_frac: float) -> Image.Image:
84+
"""Full-bleed opaque gradient square with a centered 'aw' (RGB)."""
85+
s = size * SS
86+
img = _gradient(s).convert("RGBA")
87+
_draw_aw(img, aw_frac)
88+
return img.resize((size, size), Image.LANCZOS).convert("RGB")
89+
90+
91+
def main() -> None:
92+
SITE.mkdir(parents=True, exist_ok=True)
93+
badge(512).save(SITE / "icon-512.png")
94+
badge(192).save(SITE / "icon-192.png")
95+
badge(64).save(SITE / "favicon.ico", sizes=[(16, 16), (32, 32), (48, 48)])
96+
fullbleed(180, 0.50).save(SITE / "apple-touch-icon.png")
97+
fullbleed(512, 0.42).save(SITE / "icon-maskable-512.png")
98+
print(f"Wrote favicon.ico, icon-192/512, apple-touch-icon, icon-maskable-512 to {SITE}")
99+
100+
101+
if __name__ == "__main__":
102+
main()

site/.nojekyll

Whitespace-only changes.

site/404.html

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
6+
<title>Page not found | GitHub Agentic Workflows: An Interactive Book</title>
7+
<meta name="robots" content="noindex, follow">
8+
<meta name="color-scheme" content="light dark">
9+
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#e9edf4">
10+
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#0d1220">
11+
<link rel="icon" href="/favicon.ico" sizes="32x32">
12+
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
13+
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
14+
<link rel="stylesheet" href="/assets/style.css">
15+
</head>
16+
<body class="home">
17+
<main id="main-content" style="max-width:44rem;margin:0 auto;padding:16vh 1.5rem 10rem;text-align:center">
18+
<p style="font-family:var(--font-mono);color:var(--muted);letter-spacing:.08em">404</p>
19+
<h1 style="font-size:clamp(2rem,6vw,3rem);line-height:1.1;margin:.4em 0">This page wandered off the outer loop</h1>
20+
<p style="color:var(--muted);font-size:1.1rem">The page you asked for doesn't exist or has moved. Head back to the book and pick up where you left off.</p>
21+
<p style="margin-top:2rem"><a class="btn btn-primary" href="/">Back to the book</a></p>
22+
</main>
23+
</body>
24+
</html>

site/CNAME

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
aw.isainative.dev

site/apple-touch-icon.png

11 KB
Loading

site/chapters/anatomy-and-compile-model.html

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,36 @@
33
<head>
44
<meta charset="utf-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
6+
<title>Anatomy &amp; the Compile Model | GitHub Agentic Workflows: An Interactive Book</title>
67
<meta name="description" content="Read any workflow&#x27;s frontmatter + Markdown, run the compile-and-iterate loop, and understand what the generated .lock.yml contains.">
8+
<meta name="author" content="Maxim Salnikov">
9+
<link rel="canonical" href="https://aw.isainative.dev/chapters/anatomy-and-compile-model.html">
10+
<meta name="robots" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1">
11+
<meta name="googlebot" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1">
712
<meta name="color-scheme" content="light dark">
8-
<title>Anatomy &amp; the Compile Model | GitHub Agentic Workflows: An Interactive Book</title>
13+
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#e9edf4">
14+
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#0d1220">
915
<script>(function(){try{var t=localStorage.getItem('aw-theme');if(t&&t!=='system'){document.documentElement.setAttribute('data-theme',t);}}catch(e){}})();</script>
10-
<link rel="icon" href="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2032%2032'%3E%3Crect%20width='32'%20height='32'%20rx='7'%20fill='%234f46e5'/%3E%3Ctext%20x='16'%20y='22'%20font-family='monospace'%20font-size='16'%20font-weight='bold'%20text-anchor='middle'%20fill='white'%3Eaw%3C/text%3E%3C/svg%3E">
16+
<link rel="icon" href="/favicon.ico" sizes="32x32">
17+
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
18+
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
19+
<link rel="manifest" href="/site.webmanifest">
20+
<meta property="og:type" content="article">
21+
<meta property="og:site_name" content="GitHub Agentic Workflows: An Interactive Book">
22+
<meta property="og:locale" content="en_US">
23+
<meta property="og:title" content="Anatomy &amp; the Compile Model">
24+
<meta property="og:description" content="Read any workflow&#x27;s frontmatter + Markdown, run the compile-and-iterate loop, and understand what the generated .lock.yml contains.">
25+
<meta property="og:url" content="https://aw.isainative.dev/chapters/anatomy-and-compile-model.html">
26+
<meta property="og:image" content="https://aw.isainative.dev/og-image.png">
27+
<meta property="og:image:type" content="image/png">
28+
<meta property="og:image:width" content="1200">
29+
<meta property="og:image:height" content="630">
30+
<meta property="og:image:alt" content="GitHub Agentic Workflows — An Interactive Book by Maxim Salnikov">
31+
<meta name="twitter:card" content="summary_large_image">
32+
<meta name="twitter:title" content="Anatomy &amp; the Compile Model">
33+
<meta name="twitter:description" content="Read any workflow&#x27;s frontmatter + Markdown, run the compile-and-iterate loop, and understand what the generated .lock.yml contains.">
34+
<meta name="twitter:image" content="https://aw.isainative.dev/og-image.png">
35+
<meta name="twitter:image:alt" content="GitHub Agentic Workflows — An Interactive Book by Maxim Salnikov">
1136
<link rel="preconnect" href="https://fonts.googleapis.com">
1237
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
1338
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;700&family=Literata:ital,opsz,wght@0,7..72,400;0,7..72,500;0,7..72,600;0,7..72,700;1,7..72,400&display=swap">
@@ -16,6 +41,7 @@
1641
<link rel="stylesheet" href="../assets/style.css">
1742
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
1843
<script defer src="../assets/app.js"></script>
44+
<script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"TechArticle","@id":"https://aw.isainative.dev/chapters/anatomy-and-compile-model.html#article","headline":"Anatomy \u0026 the Compile Model","name":"Anatomy \u0026 the Compile Model","description":"Read any workflow's frontmatter + Markdown, run the compile-and-iterate loop, and understand what the generated .lock.yml contains.","url":"https://aw.isainative.dev/chapters/anatomy-and-compile-model.html","inLanguage":"en","author":{"@id":"https://aw.isainative.dev/#author"},"publisher":{"@id":"https://aw.isainative.dev/#author"},"isPartOf":{"@id":"https://aw.isainative.dev/#book"},"image":"https://aw.isainative.dev/og-image.png","articleSection":"The Individual (one workflow)","keywords":"workflow file format (frontmatter + Markdown), gh aw compile, .lock.yml artifact, gh aw status, the authoring loop"},{"@type":"Person","@id":"https://aw.isainative.dev/#author","name":"Maxim Salnikov","url":"https://www.linkedin.com/in/webmax/","sameAs":["https://www.linkedin.com/in/webmax/","https://github.com/webmaxru"],"worksFor":{"@type":"Organization","name":"Microsoft"}},{"@type":"BreadcrumbList","@id":"https://aw.isainative.dev/chapters/anatomy-and-compile-model.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://aw.isainative.dev/"},{"@type":"ListItem","position":2,"name":"The Individual (one workflow)","item":"https://aw.isainative.dev/#contents"},{"@type":"ListItem","position":3,"name":"Anatomy \u0026 the Compile Model","item":"https://aw.isainative.dev/chapters/anatomy-and-compile-model.html"}]}]}</script>
1945
</head>
2046
<body class="chapter-page">
2147
<a class="skip-link" href="#main-content">Skip to main content</a>
@@ -250,7 +276,7 @@ <h2 id="recap-and-what-s-next"><a class="anchor-link" href="#recap-and-what-s-ne
250276
</main>
251277

252278
<footer class="site-footer chapter-footer">
253-
<p>Presentation generated by <code>site/generate.py</code>. Prose is injected from <code>content/chapters/anatomy-and-compile-model.html</code>.</p>
279+
<p>By <strong>Maxim Salnikov</strong> · Microsoft · <a href="https://www.linkedin.com/in/webmax/" target="_blank" rel="noopener">LinkedIn</a> · <a href="https://github.com/webmaxru/github-agentic-workflows-book" target="_blank" rel="noopener">Book repository on GitHub ↗</a></p>
254280
</footer>
255281
</div>
256282
</div>

0 commit comments

Comments
 (0)