尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證GitHub page for stharrold, "Data Science Demos", with source code (`src_*` branches).
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗Source for Data Science Demos, a blog built with Pelican and deployed to GitHub Pages by GitHub Actions.
Requirements: uv (Python 3.12+). All dependencies are pinned in pyproject.toml and uv.lock.
uv sync # install Pelican, plugins, Pagefind, dev tools
uv run pre-commit install # once: ruff and file checks on commit
uv run pelican --settings pelicanconf.py # build the dev site into output/ (drafts included, no analytics)
uv run python -m pagefind --site output # build the search index (rerun after each build)
uv run pelican --listen # serve output/ at http://localhost:8000
uv run pytest # build the publish site in a temp dir and check it
uv run pelican --settings pelicanconf.py --autoreload --listen rebuilds on every change, but each rebuild deletes
output/pagefind/, so search only works after rerunning Pagefind. Stop it with Ctrl-C; killing only the parent
process leaves its file watcher running.
| Branch | Purpose |
|---|---|
src_master | Production source. Every push builds, tests, and deploys the site (.github/workflows/pages.yml). |
src_develop | Integration branch; pushes run the same checks without deploying. |
src_feature_* | Feature branches off src_develop (git-flow); merged with --no-ff. |
(tag) legacy-ghp-import-master | The former master branch, which held the built site (via ghp-import) until 2026-10-06. |
To release: merge src_feature_* into src_develop, then src_develop into src_master, and push. The workflow runs
ruff, pytest, pelican --settings publishconf.py --fatal warnings, and Pagefind, then deploys output/.
GitHub Pages must be set to Settings > Pages > Source: GitHub Actions. output/ is generated and not tracked.
To verify a deploy, wait for the run (gh run watch <id>; find it with
gh run list --workflow pages.yml --json databaseId,headSha), then check the live site with a cache-busting query,
e.g. curl -s "https://stharrold.github.io/?v=$(date +%s)". For visual changes, compare before/after screenshots of a
local dev build served with python3 -m http.server before merging to src_master.
Automation:
.github/workflows/links.yml logs internal and external link status every Monday (and on manual dispatch) against
a fresh build: a job summary plus a link-report JSON artifact kept 90 days. It is report-only (never fails, files
no issues); alerting belongs to whatever reads the log. Dead links in the frozen 2015-2016 posts are left as is.
GitHub disables scheduled workflows in public repos after 60 days without repository activity, so the log can
stop silently on a quiet blog; re-enable with gh workflow enable links.yml (see #67)..github/dependabot.yml) opens weekly grouped PRs for GitHub Actions and Python packages against
src_develop; security fixes target src_master, so review them as deploys. Actions are pinned to commit SHAs.themes/README.md.pelicanconf.py holds the site settings; publishconf.py extends it for production (absolute URLs, feeds, GA4,
no drafts).
Posts are Markdown files in content/ with a metadata header (Title, Date, Modified, Category, Tags,
Slug, Summary, optional Related_posts and Alias for old URLs). Pages go in content/pages/. Notebooks,
notebook HTML exports, and images go in content/static/<slug>/ and are linked with {static}/static/<slug>/....
Status: draft renders only in dev builds (output/drafts/). Static files are copied regardless of
status, so add a draft's static/<slug> folder to STATIC_EXCLUDES in publishconf.py, and remove it when the
post is published.$...$ inline and $$...$$ display (as its own paragraph); rendered by MathJax 4.
Prices such as $20 are left alone.OUTDATED_AFTER_YEARS).uv run pytest. Deploys stop on any Pelican warning (for example a broken
{filename}/{static} link) or failed test. The tests derive what to expect from content/, so new and newly
published posts need no test changes; publishing a draft that has a STATIC_EXCLUDES entry fails with a message
saying which entry to remove.themes/datasciencedemos/, Bootstrap 5 with Bootswatch Flatly, forked from pelican-bootstrap3;
see themes/README.md.output/ after Pelican; runs in the browser.data/archived-comments/<slug>.html.G-K4PX9089RZ, publish builds only, Google signals off), exported daily to
BigQuery project stharrold-github-io (dataset analytics_393124094). Universal Analytics history recovered from
the GA monthly snapshot emails (2017-11 to 2019-10) is in stharrold-github-io.ua_history.monthly_snapshots.scripts/analytics_archive.py copies every BigQuery table to Parquet in the private Google
Drive folder My_Drive/Data/stharrold.github.io/ (ga4/events_YYYYMMDD.parquet, ua_history/), reads each file
back, and records rows, BigQuery's last-modified time, a sha256 and the writing commit in manifest.json; each run
also writes a README.md there linking back to this repository at that commit. A day is archived once it is
3 days old (GA4 adds late events for 72 hours); a table that changes later is archived again with the old file
kept in superseded/; nothing is deleted. It warns if the newest export is over 7 days old, if an archived table
has left BigQuery, or if billing is off. A launchd job runs it at 09:00 and 21:00 from a copy outside ~/Documents:
install or update with bash scripts/install_analytics_launchd.sh (re-run after changing either script), start a
run with --run-now, log in ~/Library/Logs/stharrold-analytics.log. uv run --script scripts/analytics_archive.py --dry-run shows what is due. The read-back checks the write, not Drive's upload. The files include visitor
pseudonymous IDs, so they never go in git./analytics skill (.claude/skills/analytics/SKILL.md): checks the archive is healthy, reports readership with
uv run --script scripts/analytics_report.py --save (DuckDB over the archive plus the days still only in BigQuery;
totals saved to on Drive; pages ranked only once one has 30 engaged visitors), then proposes
the next post. Engaged visitors (GA4 or engagement time) screen out most crawlers. The owner's own
visits are kept out three ways: a GA4 internal-traffic rule for the home IP with the Internal Traffic filter active
(from 2026-10-29; re-enter the IP if it changes), the Google Analytics opt-out add-on in the owner's browsers, and
on Drive (browser IDs from the cookie, which the report drops from all past data).
How it was built: .Open work is tracked as GitHub issues grouped in milestones: one per post ("post about predicting income", "post about agentic development", ...) plus Site maintenance for build, theme, and tooling upkeep. Planned posts, in order: a pre-registered causal study on CMS Medicare Shared Savings Program data (#73, pinned), an evaluation harness for a retrieval-augmented QA agent (#74), and an interactive household-income demo built from ACS PUMS data (#68). Published 2015-2016 posts are frozen as written.
Code: MIT. Content: CC BY 4.0, except where indicated
otherwise. Vendored theme assets keep their own licenses (themes/datasciencedemos/licenses/).
reports/YYYY-MM-DD.mdsession_engagedexcluded_visitors.txt_gaanalysis/site-analytics/BUILD-NOTES.mdhttps://stharrold.github.io/ (URL prefix, verified through the GA4 tag, so removing
the tag unverifies it), linked to GA4 and bulk-exporting daily to BigQuery dataset searchconsole since 2026-10-29
(the export's service account has BigQuery Job User and Data Editor on the project). The archive copies its tables
one data_date partition per file (searchconsole/<table>/YYYYMMDD.parquet). Search Console keeps only 16 months
and the export does not backfill, so the earlier history is saved once with uv run --script scripts/analytics_archive.py searchconsole-backfill into searchconsole_backfill/<stamp>/; it needs a
webmasters.readonly login kept in its own gcloud configuration, so the default credentials stay untouched:
CLOUDSDK_CONFIG=$HOME/.config/gcloud-searchconsole gcloud auth application-default login --scopes=openid,https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/webmasters.readonly.assets/youtube/ (outside content/, so not published), made by uv run --no-sync python scripts/youtube_art.py
in the site's colours and Lato; its README records what was uploaded. Video files stay on Google Drive, not in git.
How it was set up: analysis/youtube-channel/BUILD-NOTES.md.content/pages/privacy.md lists every third-party service the site loads; update it when adding one.related_posts, tag_cloud, sitemap (from PyPI), and plugins/pelican_alias.py
(Python 3 port of pelican-alias) for Alias: redirects.