{"id":51475352,"url":"https://github.com/asmuelle/asmuelle.github.io","last_synced_at":"2026-07-06T20:30:32.491Z","repository":{"id":365863645,"uuid":"1272733566","full_name":"asmuelle/asmuelle.github.io","owner":"asmuelle","description":"Personal landing page — selected projects, live at asmuelle.github.io","archived":false,"fork":false,"pushed_at":"2026-06-30T07:37:51.000Z","size":299,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-30T09:23:59.090Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://asmuelle.github.io/","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/asmuelle.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-17T22:18:10.000Z","updated_at":"2026-06-30T07:37:55.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/asmuelle/asmuelle.github.io","commit_stats":null,"previous_names":["asmuelle/asmuelle.github.io"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/asmuelle/asmuelle.github.io","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asmuelle%2Fasmuelle.github.io","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asmuelle%2Fasmuelle.github.io/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asmuelle%2Fasmuelle.github.io/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asmuelle%2Fasmuelle.github.io/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/asmuelle","download_url":"https://codeload.github.com/asmuelle/asmuelle.github.io/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asmuelle%2Fasmuelle.github.io/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35205739,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-06T02:00:07.184Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-06T20:30:31.728Z","updated_at":"2026-07-06T20:30:32.474Z","avatar_url":"https://github.com/asmuelle.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# asmuelle.github.io\n\nMy personal landing page — selected work plus a live grid of recent projects,\nserved at **https://asmuelle.github.io/** in 10 languages.\n\n📊 **[Repository status board → STATUS.md](./STATUS.md)** — live CI/check, commit,\nand open-issue badges for every public repository.\n\n## Generated, not hand-edited\n\nThe HTML pages are **built** from a single translation source, so do not edit\n`index.html` (or the `de/`, `fr/`, … pages) by hand — your changes will be\noverwritten on the next build.\n\n- `scripts/i18n.mjs` — **single source of truth** for all copy, in 10 languages\n  (English, German, French, Spanish, Portuguese, Norwegian, Swedish, Danish,\n  Russian, Simplified Chinese). The build fails loudly if any language is missing\n  a key.\n- `scripts/build-site.mjs` — generator. Emits one fully-translated, statically\n  rendered page per language (`index.html` = English at the root, `de/index.html`,\n  `fr/index.html`, …) plus `sitemap.xml`, `robots.txt`, `llms.txt` and `.nojekyll`.\n\nBuild:\n\n```bash\nnode scripts/build-site.mjs\n```\n\nWhy statically rendered per language: search engines index one language per URL,\nand most AI/answer-engine crawlers (GPTBot, PerplexityBot, ClaudeBot …) don't run\nJavaScript — so the localized content has to be in the served HTML, not swapped in\nby JS. Each page carries `hreflang` alternates, a self-referencing canonical,\nlocalized `\u003ctitle\u003e`/meta/OpenGraph, and structured data.\n\n## SEO / GEO\n\n- **`hreflang`** — every page links all 10 locales + `x-default` (English root).\n- **`sitemap.xml`** — all 10 URLs with reciprocal `hreflang` alternates.\n- **`robots.txt`** — explicitly allows AI/answer-engine crawlers (being cited is\n  the goal) and points to the sitemap.\n- **`llms.txt`** — plain-markdown profile/projects summary for AI engines.\n- **JSON-LD** — `ProfilePage` + `Person` (with `knowsLanguage`, `sameAs`,\n  `email`) + `SoftwareApplication`/`SoftwareSourceCode` per flagship project +\n  `FAQPage`.\n- **`sitemap-index.xml`** — a root-domain **sitemap index** that aggregates this\n  site's own `sitemap.xml` with every project Pages site's sitemap\n  (`asmuelle.github.io/\u003cslug\u003e/sitemap.xml`). `robots.txt` points crawlers here, so\n  one entry discovers the whole portfolio. A sitemap index served from the host\n  root may reference URLs anywhere on the host, which is what makes per-repo\n  project sitemaps discoverable from a single place.\n- **Language selector** — a styled `\u003cselect\u003e` that navigates to the localized URL\n  (real navigation, not client-side text swapping), with a `\u003cnoscript\u003e` link list.\n\n## Other files\n\n- `repos.json` — curated data for the *Also on GitHub* grid. Generated, not\n  hand-edited (see below).\n- `og.png` / `og.svg` — 1200×630 social-share card referenced by the OpenGraph\n  and Twitter `summary_large_image` meta tags. Edit `og.svg`, then re-render\n  (`inkscape og.svg --export-type=png --export-filename=og.png -w 1200 -h 630`).\n- `scripts/build-repos.sh` + `scripts/repos-filter.jq` — regenerate `repos.json`\n  from the GitHub API (non-forks, with a description, not already featured,\n  newest 6 by push date).\n- `pages-projects.json` — source of truth for the sitemap index: the project Pages\n  sites whose `sitemap.xml` should be aggregated. Generated, not hand-edited.\n- `scripts/build-sitemap-index.mjs` — renders `sitemap-index.xml` from\n  `pages-projects.json` (offline/deterministic; also called by `build-site.mjs`).\n- `STATUS.md` — central repository status board (live CI/check, commit-freshness,\n  and open-issue badges for every public repo, with live links for Pages sites).\n  Generated, not hand-edited.\n- `scripts/build-status.mjs` — regenerates `STATUS.md` from the GitHub API\n  (badges are dynamic, so only the repo list needs rebuilding). Requires `gh`\n  authenticated.\n- `scripts/build-pages-projects.sh` — refreshes `pages-projects.json` from the\n  GitHub API: every owner repo with Pages enabled whose site actually **serves a\n  `sitemap.xml`** (probed live, so the index never points at a 404). Additive — a\n  listed project is kept even if a probe fails mid-rollout. Requires `gh`\n  authenticated.\n- `.github/workflows/refresh-repos.yml` — runs the repos build **and** the\n  pages-projects/sitemap-index refresh daily (and on demand) with the\n  authenticated `GITHUB_TOKEN`, committing `repos.json`, `pages-projects.json`, and\n  `sitemap-index.xml` when they change. This keeps the grid static (no\n  unauthenticated rate limits) and the sitemap index current as projects ship.\n\n## Grid data flow\n\nThe *Also on GitHub* grid loads at runtime in three tiers, degrading gracefully\n(and localized via strings injected into each page at build time):\n\n1. **`repos.json`** — fast, static, Action-generated. Preferred.\n2. **Live GitHub API** — fallback if `repos.json` is missing/empty.\n3. **A plain \"browse on GitHub\" link** — fallback if the API fails.\n\n## Changing content\n\n- **Copy / translations** → edit `scripts/i18n.mjs`, then `node scripts/build-site.mjs`.\n- **Featured projects, services, FAQ structure** → edit the data arrays near the\n  top of `scripts/build-site.mjs`, then rebuild. Keep featured repo names in the\n  `FEATURED` arrays (in `build-site.mjs` and `scripts/build-repos.sh`) so they\n  stay out of the live grid.\n- **Grid data** → `bash scripts/build-repos.sh` (requires `gh` authenticated).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasmuelle%2Fasmuelle.github.io","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fasmuelle%2Fasmuelle.github.io","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasmuelle%2Fasmuelle.github.io/lists"}