Skip to content

Commit a85b067

Browse files
StewAlexander-comClaude Agent
andauthored
feat(site): make site/ the start page and publish via GitHub Pages (#14)
Reworks site/ into a proper start page for the repo & software and adds a GitHub Actions workflow that deploys it to GitHub Pages on every push to main that touches site/. - index.html: replace the two-command Start section with three numbered steps (Clone / Install / Run), each with its own copy-to-clipboard button. The clone block uses the HTTPS URL so visitors don't need the GitHub CLI installed. Added prominent links to the repo, README, and issues. Canonical and og:url now point at the Pages URL. - style.css: numbered step cards, copy button styling, a <details> disclosure for common variations, and a links row beneath the steps. - .github/workflows/pages.yml: new workflow using actions/configure-pages, actions/upload-pages-artifact, and actions/deploy-pages. Path-filtered to site/ and the workflow itself so it doesn't fight the existing CI workflow. Uses pages/id-token permissions and a non-cancelling pages concurrency group. - README.md: top-of-file pointer to the Pages start page and an updated "Hero website / start page" section explaining how deployment works. - site/README.md: notes the published URL and which workflow deploys it. - scripts/check_site.sh: validates the new install content (clone / install / run commands, repo/README/issues links, copy buttons) and that the Pages workflow exists and references the official actions. Co-authored-by: Claude Agent <claude-agent@anthropic.com>
1 parent c7d3439 commit a85b067

6 files changed

Lines changed: 329 additions & 33 deletions

File tree

.github/workflows/pages.yml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: Deploy site to GitHub Pages
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- "site/**"
8+
- ".github/workflows/pages.yml"
9+
workflow_dispatch:
10+
11+
permissions:
12+
contents: read
13+
pages: write
14+
id-token: write
15+
16+
concurrency:
17+
group: pages
18+
cancel-in-progress: false
19+
20+
jobs:
21+
build:
22+
name: Build Pages artifact
23+
runs-on: ubuntu-latest
24+
steps:
25+
- uses: actions/checkout@v4
26+
27+
- name: Configure Pages
28+
uses: actions/configure-pages@v5
29+
30+
- name: Upload site/ as Pages artifact
31+
uses: actions/upload-pages-artifact@v3
32+
with:
33+
path: site
34+
35+
deploy:
36+
name: Deploy to GitHub Pages
37+
needs: build
38+
runs-on: ubuntu-latest
39+
environment:
40+
name: github-pages
41+
url: ${{ steps.deployment.outputs.page_url }}
42+
steps:
43+
- name: Deploy to GitHub Pages
44+
id: deployment
45+
uses: actions/deploy-pages@v4

README.md

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ Lessons, an interactive code lab, and an AI mentor — powered by a local LLM
77
Python, write code, get feedback. Your code and your questions never leave the
88
laptop.
99

10+
> **Start here:** <https://stewalexander-com.github.io/python-tutor/> — the
11+
> project's GitHub Pages start page with the three-command install and a
12+
> 30-second visual tour. Source for the page lives in [`site/`](site/).
13+
1014
```
1115
┌─────────────────────────────────────────────────────────┐
1216
│ Read a lesson → Run code in the lab → Ask tutor │
@@ -41,21 +45,30 @@ laptop.
4145

4246
---
4347

44-
## Hero website
48+
## Hero website / start page
49+
50+
The project's **start page** is published on GitHub Pages:
51+
52+
**<https://stewalexander-com.github.io/python-tutor/>**
53+
54+
It's the link to share with anyone who hasn't cloned the repo yet: dark /
55+
amber aesthetic, the local-first loop in four steps, the three-command
56+
install with copy buttons, and links to the repo, README, and issues.
57+
58+
Source lives in [`site/`](site/) and is deployed by
59+
[`.github/workflows/pages.yml`](.github/workflows/pages.yml) on every push
60+
to `main` that touches `site/`. The Pages workflow runs independently of
61+
the regular CI workflow.
4562

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.
63+
To preview locally (pure static HTML + CSS, no build step):
5064

5165
```bash
5266
cd site
5367
python3 -m http.server 8080
5468
# open http://localhost:8080/
5569
```
5670

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.
71+
See [`site/README.md`](site/README.md) for what's in it and the asset layout.
5972

6073
---
6174

scripts/check_site.sh

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,27 @@ need 'id="screens"'
3232
need 'id="start"'
3333
ok "required <head> and section anchors present"
3434

35+
# Start-page install content must be visible — this page is the entry point
36+
# to the repo, so the clone/install/run commands have to be there literally.
37+
need "git clone https://github.com/StewAlexander-com/python-tutor.git"
38+
need "cd python-tutor"
39+
need "./install.sh"
40+
need "./run.sh --open-browser"
41+
ok "clone / install / run commands present in start section"
42+
43+
# Quick links to repo, README, and issues from the start page.
44+
need 'href="https://github.com/StewAlexander-com/python-tutor"'
45+
need 'href="https://github.com/StewAlexander-com/python-tutor#readme"'
46+
need 'href="https://github.com/StewAlexander-com/python-tutor/issues"'
47+
ok "repo / README / issues links present"
48+
49+
# Copy-to-clipboard buttons should be wired to the command blocks.
50+
need 'class="copy-btn"'
51+
need 'data-copy-target="cmd-clone"'
52+
need 'data-copy-target="cmd-install"'
53+
need 'data-copy-target="cmd-run"'
54+
ok "copy-to-clipboard buttons wired up"
55+
3556
# Every local href/src under site/ must resolve to a real file.
3657
# (We only check ./relative paths — external URLs are skipped.)
3758
python3 - "$HTML" "$SITE" <<'PY'
@@ -66,4 +87,13 @@ closes=$(grep -c '</main>' "$HTML" || true)
6687
[ "$opens" = "$closes" ] || fail "unbalanced <main> tags ($opens open, $closes close)"
6788
ok "<main> tags balanced"
6889

90+
# GitHub Pages deploy workflow must exist and reference the official actions.
91+
PAGES_WF="$ROOT/.github/workflows/pages.yml"
92+
[ -f "$PAGES_WF" ] || fail ".github/workflows/pages.yml missing (GitHub Pages deploy)"
93+
grep -q "actions/configure-pages" "$PAGES_WF" || fail "pages.yml missing actions/configure-pages"
94+
grep -q "actions/upload-pages-artifact" "$PAGES_WF" || fail "pages.yml missing actions/upload-pages-artifact"
95+
grep -q "actions/deploy-pages" "$PAGES_WF" || fail "pages.yml missing actions/deploy-pages"
96+
grep -q "path: site" "$PAGES_WF" || fail "pages.yml does not upload the site/ folder"
97+
ok "GitHub Pages workflow present and references official actions"
98+
6999
echo "site checks passed"

site/README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1-
# Hero website
1+
# Hero website / start page
22

33
A small static landing page for Python Tutor. It mirrors the app's
44
dark / amber aesthetic and explains the local-first loop without
55
needing to launch the backend.
66

7+
**Published at:** <https://stewalexander-com.github.io/python-tutor/>
8+
9+
Deployed automatically by [`.github/workflows/pages.yml`](../.github/workflows/pages.yml)
10+
on every push to `main` that touches `site/`.
11+
712
## Files
813

914
```

site/index.html

Lines changed: 123 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
<meta charset="utf-8" />
55
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover" />
66
<title>Python Tutor — Private Python practice with a local AI tutor</title>
7-
<meta name="description" content="A private, offline Python tutor that runs entirely on your own machine. Lessons, an interactive code lab, and a local AI mentor — no accounts, no cloud, no telemetry." />
7+
<meta name="description" content="A private, offline Python tutor that runs entirely on your own machine. Lessons, an interactive code lab, and a local AI mentor — no accounts, no cloud, no telemetry. Clone the repo and run two commands to start." />
88
<meta name="theme-color" content="#0c0c0d" />
99
<link rel="icon" type="image/svg+xml" href="./assets/favicon.svg" />
10-
<link rel="canonical" href="https://github.com/StewAlexander-com/python-tutor" />
10+
<link rel="canonical" href="https://stewalexander-com.github.io/python-tutor/" />
1111

1212
<!-- Open Graph -->
1313
<meta property="og:type" content="website" />
@@ -16,7 +16,7 @@
1616
<meta property="og:image" content="./assets/og-image.png" />
1717
<meta property="og:image:width" content="1200" />
1818
<meta property="og:image:height" content="630" />
19-
<meta property="og:url" content="https://github.com/StewAlexander-com/python-tutor" />
19+
<meta property="og:url" content="https://stewalexander-com.github.io/python-tutor/" />
2020

2121
<!-- Twitter / X -->
2222
<meta name="twitter:card" content="summary_large_image" />
@@ -43,7 +43,7 @@
4343
<a class="topbar__link" href="#why">Why</a>
4444
<a class="topbar__link" href="#loop">How it works</a>
4545
<a class="topbar__link" href="#screens">See it</a>
46-
<a class="topbar__link" href="#start">Start</a>
46+
<a class="topbar__link" href="#start">Install</a>
4747
</nav>
4848
<a class="btn btn--ghost topbar__cta" href="https://github.com/StewAlexander-com/python-tutor" rel="noopener">
4949
<svg width="16" height="16" viewBox="0 0 24 24" aria-hidden="true" fill="currentColor"><path d="M12 .5C5.65.5.5 5.65.5 12c0 5.08 3.29 9.39 7.86 10.91.58.11.79-.25.79-.56v-2c-3.2.7-3.88-1.37-3.88-1.37-.52-1.32-1.27-1.67-1.27-1.67-1.04-.71.08-.7.08-.7 1.15.08 1.76 1.18 1.76 1.18 1.02 1.75 2.68 1.25 3.34.96.1-.74.4-1.25.72-1.54-2.55-.29-5.24-1.28-5.24-5.69 0-1.26.45-2.29 1.18-3.1-.12-.29-.51-1.45.11-3.03 0 0 .97-.31 3.18 1.18a11.04 11.04 0 0 1 5.8 0c2.21-1.49 3.18-1.18 3.18-1.18.62 1.58.23 2.74.11 3.03.73.81 1.18 1.84 1.18 3.1 0 4.42-2.7 5.39-5.27 5.68.41.36.78 1.05.78 2.12v3.14c0 .31.21.68.8.56A11.5 11.5 0 0 0 23.5 12C23.5 5.65 18.35.5 12 .5z"/></svg>
@@ -71,8 +71,8 @@ <h1 class="hero__title">
7171
<strong>never leave your laptop</strong>.
7272
</p>
7373
<div class="hero__cta">
74-
<a class="btn btn--primary" href="https://github.com/StewAlexander-com/python-tutor#quick-start" rel="noopener">
75-
<span>Get started</span>
74+
<a class="btn btn--primary" href="#start">
75+
<span>Install in 3 commands</span>
7676
<svg width="14" height="14" viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M13 5l7 7-7 7"/></svg>
7777
</a>
7878
<a class="btn btn--ghost" href="https://github.com/StewAlexander-com/python-tutor" rel="noopener">View on GitHub</a>
@@ -243,29 +243,86 @@ <h2 class="section__title">See it.</h2>
243243
</div>
244244
</section>
245245

246-
<!-- ============ TWO-COMMAND START ============ -->
246+
<!-- ============ START (clone + install + run) ============ -->
247247
<section id="start" class="start">
248248
<div class="start__inner">
249-
<h2 class="section__title">Two commands.</h2>
250-
<p class="section__lede">macOS or Linux. Python 3.10+.</p>
251-
<div class="start__code">
252-
<pre><code><span class="t-com"># 1 — clone</span>
253-
gh repo clone StewAlexander-com/python-tutor
254-
<span class="t-kw">cd</span> python-tutor
255-
256-
<span class="t-com"># 2 — set up &amp; serve (any host step is opt-in y/N)</span>
257-
./install.sh
258-
./run.sh <span class="t-com"># → http://localhost:8001/</span></code></pre>
259-
</div>
260-
<p class="start__note">
261-
<code>install.sh</code> only touches the repo on its own. Installing
262-
Ollama, starting the daemon, pulling the model, or launching the app
263-
are <strong>opt-in y/N prompts</strong> — press Enter and nothing
264-
changes on your host.
249+
<h2 class="section__title">Clone, install, run.</h2>
250+
<p class="section__lede">
251+
This page is the start page for the repo &amp; software. Three short
252+
commands and you're at <code>http://localhost:8001/</code>.
253+
macOS or Linux. Python 3.10+.
265254
</p>
266-
<div class="start__cta">
255+
256+
<ol class="start__steps">
257+
<li class="start__step">
258+
<div class="start__step-head">
259+
<span class="start__step-num">1</span>
260+
<h3 class="start__step-title">Clone the repo</h3>
261+
</div>
262+
<p class="start__step-sub">HTTPS works without a GitHub login. <code>gh repo clone</code> works too if you use the GitHub CLI.</p>
263+
<div class="start__code start__code--with-copy">
264+
<pre><code id="cmd-clone">git clone https://github.com/StewAlexander-com/python-tutor.git
265+
cd python-tutor</code></pre>
266+
<button class="copy-btn" type="button" data-copy-target="cmd-clone" aria-label="Copy clone commands">Copy</button>
267+
</div>
268+
</li>
269+
270+
<li class="start__step">
271+
<div class="start__step-head">
272+
<span class="start__step-num">2</span>
273+
<h3 class="start__step-title">Install</h3>
274+
</div>
275+
<p class="start__step-sub">
276+
Sets up a Python venv and dependencies. Any host-level step
277+
(Ollama install, daemon start, model pull, app launch) is an
278+
<strong>opt-in y/N prompt</strong> — press Enter and nothing
279+
changes on your host.
280+
</p>
281+
<div class="start__code start__code--with-copy">
282+
<pre><code id="cmd-install">./install.sh</code></pre>
283+
<button class="copy-btn" type="button" data-copy-target="cmd-install" aria-label="Copy install command">Copy</button>
284+
</div>
285+
</li>
286+
287+
<li class="start__step">
288+
<div class="start__step-head">
289+
<span class="start__step-num">3</span>
290+
<h3 class="start__step-title">Run &amp; open in your browser</h3>
291+
</div>
292+
<p class="start__step-sub"><code>--open-browser</code> pops the tab once <code>/api/health</code> is green.</p>
293+
<div class="start__code start__code--with-copy">
294+
<pre><code id="cmd-run">./run.sh --open-browser</code></pre>
295+
<button class="copy-btn" type="button" data-copy-target="cmd-run" aria-label="Copy run command">Copy</button>
296+
</div>
297+
<p class="start__step-sub start__step-sub--muted">
298+
Or just <code>./run.sh</code> and open <code>http://localhost:8001/</code> yourself.
299+
</p>
300+
</li>
301+
</ol>
302+
303+
<details class="start__more">
304+
<summary>Common variations</summary>
305+
<div class="start__code start__code--with-copy">
306+
<pre><code id="cmd-more"><span class="t-com"># trusted host: install Ollama, pull model, launch — no prompts</span>
307+
./install.sh --yes
308+
309+
<span class="t-com"># CI / air-gapped: never prompt, default everything to "no"</span>
310+
./install.sh --noninteractive
311+
312+
<span class="t-com"># Python-only setup (skip every Ollama probe)</span>
313+
./install.sh --skip-ollama
314+
315+
<span class="t-com"># pick a different model or port</span>
316+
./install.sh --model llama3.1:8b
317+
./run.sh --port 8042</code></pre>
318+
<button class="copy-btn" type="button" data-copy-target="cmd-more" aria-label="Copy variation commands">Copy</button>
319+
</div>
320+
</details>
321+
322+
<div class="start__links">
267323
<a class="btn btn--primary" href="https://github.com/StewAlexander-com/python-tutor" rel="noopener">Open the repo</a>
268-
<a class="btn btn--ghost" href="https://github.com/StewAlexander-com/python-tutor#quick-start" rel="noopener">Full quick start →</a>
324+
<a class="btn btn--ghost" href="https://github.com/StewAlexander-com/python-tutor#readme" rel="noopener">Read the README</a>
325+
<a class="btn btn--ghost" href="https://github.com/StewAlexander-com/python-tutor/issues" rel="noopener">File an issue</a>
269326
</div>
270327
</div>
271328
</section>
@@ -290,5 +347,46 @@ <h2 class="section__title">Two commands.</h2>
290347
<p class="foot__note">MIT-licensed. Frontend adapted from <a href="https://github.com/StewAlexander-com/Python-Power-User" rel="noopener">Python Power User</a>.</p>
291348
</div>
292349
</footer>
350+
351+
<script>
352+
(function () {
353+
var buttons = document.querySelectorAll('.copy-btn[data-copy-target]');
354+
buttons.forEach(function (btn) {
355+
btn.addEventListener('click', function () {
356+
var id = btn.getAttribute('data-copy-target');
357+
var node = document.getElementById(id);
358+
if (!node) return;
359+
var text = node.innerText.replace(/ /g, ' ');
360+
var done = function () {
361+
var original = btn.textContent;
362+
btn.textContent = 'Copied';
363+
btn.classList.add('is-copied');
364+
setTimeout(function () {
365+
btn.textContent = original;
366+
btn.classList.remove('is-copied');
367+
}, 1400);
368+
};
369+
if (navigator.clipboard && navigator.clipboard.writeText) {
370+
navigator.clipboard.writeText(text).then(done, function () {
371+
fallbackCopy(text); done();
372+
});
373+
} else {
374+
fallbackCopy(text); done();
375+
}
376+
});
377+
});
378+
function fallbackCopy(text) {
379+
var ta = document.createElement('textarea');
380+
ta.value = text;
381+
ta.setAttribute('readonly', '');
382+
ta.style.position = 'absolute';
383+
ta.style.left = '-9999px';
384+
document.body.appendChild(ta);
385+
ta.select();
386+
try { document.execCommand('copy'); } catch (e) {}
387+
document.body.removeChild(ta);
388+
}
389+
})();
390+
</script>
293391
</body>
294392
</html>

0 commit comments

Comments
 (0)