Skip to content

Commit d506e8b

Browse files
feat: add static hero landing site at site/ (#12)
A small static landing page that mirrors the app's dark / amber aesthetic and explains the local-first loop without needing the backend. Aimed at people who haven't installed anything yet. - site/index.html: hero with headline + lede, useful/private/credible rows, four-step local loop (Write Python -> Run locally -> Get feedback -> Offline practice), simplified UI mockup with code lab + tutor chat, six-screenshot tour, and the two-command quick start. - site/style.css: design tokens mirror frontend/base.css. - SEO/Open Graph/Twitter meta; reuses the existing 1200x630 OG image and the frontend favicon. - Pure static, no build step. Preview with: cd site && python3 -m http.server 8080 - scripts/check_site.sh: asset existence, required meta/section anchors, no hard-coded localhost, balanced <main>. Wired into CI (frontend job). - README.md: new "Hero website" section with preview instructions. Co-authored-by: Claude Code <claude-code@anthropic.com>
1 parent a60aae5 commit d506e8b

14 files changed

Lines changed: 1025 additions & 0 deletions

.github/workflows/ci.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,15 @@ jobs:
7575
sys.exit(1 if errors else 0)
7676
"
7777
78+
- name: Check hero landing site
79+
run: |
80+
if [ -f scripts/check_site.sh ]; then
81+
chmod +x scripts/check_site.sh
82+
./scripts/check_site.sh
83+
else
84+
echo "scripts/check_site.sh missing; skipping"
85+
fi
86+
7887
scripts:
7988
name: Shell script lint + smoke
8089
runs-on: ubuntu-latest

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,24 @@ laptop.
4141

4242
---
4343

44+
## Hero website
45+
46+
A small static landing page lives at [`site/`](site/) — dark / amber
47+
aesthetic, the local-first loop in four steps, a simplified product
48+
mockup, and links straight to the two-command install. Useful for
49+
sharing the project without asking people to clone the repo first.
50+
51+
```bash
52+
cd site
53+
python3 -m http.server 8080
54+
# open http://localhost:8080/
55+
```
56+
57+
It's pure static HTML + CSS, no build step. See
58+
[`site/README.md`](site/README.md) for what's in it and the asset layout.
59+
60+
---
61+
4462
## A quick look
4563

4664
A 30-second tour of the UI, lab, and tutor. Click any image to enlarge.

scripts/check_site.sh

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#!/usr/bin/env bash
2+
# check_site.sh — light validity / asset checks for the hero landing page.
3+
#
4+
# Runs from repo root. Exits non-zero on the first failure, with a clear
5+
# message and an exit code that's safe for CI.
6+
7+
set -euo pipefail
8+
9+
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
10+
SITE="$ROOT/site"
11+
HTML="$SITE/index.html"
12+
CSS="$SITE/style.css"
13+
14+
fail() { echo "$*" >&2; exit 1; }
15+
ok() { echo "$*"; }
16+
17+
[ -f "$HTML" ] || fail "site/index.html missing"
18+
[ -f "$CSS" ] || fail "site/style.css missing"
19+
ok "site/index.html and site/style.css present"
20+
21+
# Required meta tags / sections — grep for substrings.
22+
need() {
23+
grep -q -- "$1" "$HTML" || fail "site/index.html missing: $1"
24+
}
25+
need "<title>Python Tutor"
26+
need 'property="og:title"'
27+
need 'property="og:image"'
28+
need 'name="twitter:card"'
29+
need 'id="why"'
30+
need 'id="loop"'
31+
need 'id="screens"'
32+
need 'id="start"'
33+
ok "required <head> and section anchors present"
34+
35+
# Every local href/src under site/ must resolve to a real file.
36+
# (We only check ./relative paths — external URLs are skipped.)
37+
python3 - "$HTML" "$SITE" <<'PY'
38+
import re, sys, os
39+
html_path, site_dir = sys.argv[1], sys.argv[2]
40+
src = open(html_path, encoding="utf-8").read()
41+
refs = re.findall(r'(?:href|src)\s*=\s*"(\./[^"]+)"', src)
42+
missing = []
43+
for r in refs:
44+
rel = r[2:] # drop "./"
45+
rel = rel.split("#", 1)[0].split("?", 1)[0]
46+
p = os.path.join(site_dir, rel)
47+
if not os.path.exists(p):
48+
missing.append(r)
49+
if missing:
50+
print("✗ missing local assets:", file=sys.stderr)
51+
for m in missing:
52+
print(" " + m, file=sys.stderr)
53+
sys.exit(1)
54+
print(f"✓ all {len(refs)} local references resolve")
55+
PY
56+
57+
# Should NOT contain hard-coded localhost links (would break in prod).
58+
if grep -nE 'href="http://localhost' "$HTML" >/dev/null; then
59+
fail "site/index.html contains hard-coded http://localhost hrefs"
60+
fi
61+
ok "no hard-coded localhost hrefs"
62+
63+
# Cheap structural sanity check: balanced <main> tag.
64+
opens=$(grep -c '<main' "$HTML" || true)
65+
closes=$(grep -c '</main>' "$HTML" || true)
66+
[ "$opens" = "$closes" ] || fail "unbalanced <main> tags ($opens open, $closes close)"
67+
ok "<main> tags balanced"
68+
69+
echo "site checks passed"

site/README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Hero website
2+
3+
A small static landing page for Python Tutor. It mirrors the app's
4+
dark / amber aesthetic and explains the local-first loop without
5+
needing to launch the backend.
6+
7+
## Files
8+
9+
```
10+
site/
11+
├── index.html # the landing page
12+
├── style.css # design tokens mirror frontend/base.css
13+
└── assets/
14+
├── favicon.svg
15+
├── og-image.png # 1200×630 social card (reused from frontend)
16+
└── screenshots/ # six UI screenshots, lazy-loaded
17+
```
18+
19+
## Preview locally
20+
21+
The page is pure static HTML + CSS — no build step.
22+
23+
```bash
24+
cd site
25+
python3 -m http.server 8080
26+
# open http://localhost:8080/
27+
```
28+
29+
Or open `site/index.html` directly in a browser (file://) — all asset
30+
paths are relative.
31+
32+
## Why a separate landing
33+
34+
The app at `frontend/` is a PWA: lesson browser, code lab, tutor chat.
35+
It assumes the FastAPI backend on `:8001`. The landing page is for
36+
**people who haven't installed anything yet** — a credible 30-second
37+
overview that points them at the repo and the two-command install.
38+
39+
## Checks
40+
41+
`scripts/check_site.sh` runs from the repo root and verifies:
42+
43+
- referenced screenshots and OG image exist on disk
44+
- `<title>` and Open Graph tags are present
45+
- no `localhost:` URLs are baked into hrefs/srcs
46+
- key sections (`#why`, `#loop`, `#screens`, `#start`) are wired up
47+
48+
CI invokes the same script.

site/assets/favicon.svg

Lines changed: 7 additions & 0 deletions
Loading

site/assets/og-image.png

122 KB
Loading
409 KB
Loading
351 KB
Loading
454 KB
Loading
314 KB
Loading

0 commit comments

Comments
 (0)