feat: fix
Pablo Murad pblmrd@gmail.com
Thu, 06 Aug 2026 15:04:10 -0300
4 files changed,
5 insertions(+),
148 deletions(-)
D
.forgejo/scripts/check_links.py
@@ -1,99 +0,0 @@
-#!/usr/bin/env python3 - -import concurrent.futures -import re -import socket -import urllib.error -import urllib.request - -README = "README.md" -MARKER = " **(link no longer exists)**" - -# Match a list entry and capture its primary URL: "- [Name](https://...) - ..." -# Table rows ("|...") and Table-of-Contents anchors ("#...") never match. -ENTRY_RE = re.compile(r"^- \[[^\]]+\]\((https?://[^)]+)\)") - -UA = ( - "Mozilla/5.0 (compatible; awesome-indieweb-linkcheck/1.0; " - "+https://source.tube/pmurad/awesome-indieweb)" -) -TIMEOUT = 20 - - -def is_dead(url): - """Return True only on a definitive dead signal (404/410/NXDOMAIN).""" - req = urllib.request.Request(url, method="GET", headers={"User-Agent": UA}) - try: - urllib.request.urlopen(req, timeout=TIMEOUT) - return False - except urllib.error.HTTPError as e: - return e.code in (404, 410) - except urllib.error.URLError as e: - # DNS resolution failure means the domain itself is gone. - return isinstance(e.reason, socket.gaierror) - except Exception: - # Anything else is inconclusive; never flag on uncertainty. - return False - - -def strip_marker(line): - """Remove a trailing marker (if present), preserving the newline.""" - body = line.rstrip("\n") - if body.endswith(MARKER): - nl = "\n" if line.endswith("\n") else "" - return body[: -len(MARKER)] + nl - return line - - -def main(): - with open(README, encoding="utf-8") as f: - lines = f.readlines() - - # (line index, url) for every entry, ignoring any existing marker. - targets = [] - for i, line in enumerate(lines): - m = ENTRY_RE.match(strip_marker(line)) - if m: - targets.append((i, m.group(1))) - - urls = {url for _, url in targets} - dead = {} - with concurrent.futures.ThreadPoolExecutor(max_workers=16) as ex: - futures = {ex.submit(is_dead, u): u for u in urls} - for fut in concurrent.futures.as_completed(futures): - url = futures[fut] - try: - dead[url] = fut.result() - except Exception: - dead[url] = False - - changed, newly_dead, recovered = 0, [], [] - for i, url in targets: - base = strip_marker(lines[i]) - was_marked = lines[i] != base - if dead.get(url): - nl = "\n" if base.endswith("\n") else "" - updated = base.rstrip("\n") + MARKER + nl - if updated != lines[i]: - lines[i], changed = updated, changed + 1 - newly_dead.append(url) - elif was_marked: - lines[i], changed = base, changed + 1 - recovered.append(url) - - if changed: - with open(README, "w", encoding="utf-8", newline="") as f: - f.writelines(lines) - - print(f"Checked {len(urls)} unique links across {len(targets)} entries.") - print(f"Newly marked dead: {len(newly_dead)}") - for u in newly_dead: - print(f" DEAD {u}") - print(f"Recovered (marker removed): {len(recovered)}") - for u in recovered: - print(f" ALIVE {u}") - print(f"Lines changed: {changed}") - - -if __name__ == "__main__": - main()
D
.forgejo/workflows/link-check.yml
@@ -1,40 +0,0 @@
-name: Link check - -on: - schedule: - - cron: "0 0 1 * *" # 00:00 UTC on the 1st of every month - workflow_dispatch: # allow manual runs from the Actions tab - -jobs: - check: - runs-on: docker - # python:3 ships both python3 and git, so the job needs no Node-based - # actions (checkout/setup-python). Every step below is a plain shell step. - container: - image: python:3 - steps: - - name: Check out the repository - env: - # Prefer a write-enabled access token stored as the PUSH_TOKEN secret; - # fall back to the automatic per-run token when it is not set. - PUSH_TOKEN: ${{ secrets.PUSH_TOKEN }} - RUN_TOKEN: ${{ github.token }} - run: | - git config --global --add safe.directory '*' - token="${PUSH_TOKEN:-$RUN_TOKEN}" - host="${GITHUB_SERVER_URL#https://}" - git clone --depth 1 --branch "$GITHUB_REF_NAME" \ - "https://x-access-token:${token}@${host}/${GITHUB_REPOSITORY}.git" . - - - name: Check links and annotate dead entries - run: python3 .forgejo/scripts/check_links.py - - - name: Commit changes if any - run: | - if [ -n "$(git status --porcelain README.md)" ]; then - git add README.md - git -c user.name="Link Checker" -c user.email="" commit -m "chore: flag dead links (automated monthly check)" - git push origin "HEAD:${GITHUB_REF_NAME}" - else - echo "No dead-link changes to commit." - fi
M
.gitignore
→
.gitignore
@@ -1,3 +1,2 @@
# files from my obsidian -.recursos/ -__pycache__/ +.recursos/
M
README.md
→
README.md
@@ -21,9 +21,6 @@
This list spans both resources **native to the IndieWeb** (standards and building blocks) and **adjacent** tools that solve important parts of the problem well. Statuses change fast, confirm recent releases, docs, and export procedures before adopting a critical component. **Contributions are welcome.** Pull requests are accepted only on the main repository at [source.tube](https://source.tube/pmurad/awesome-indieweb): open a [pull request](https://source.tube/pmurad/awesome-indieweb/pulls) or file an [issue](https://source.tube/pmurad/awesome-indieweb/issues/new/choose) there. GitHub users can request an inclusion by emailing runawaydevil@pm.me. Please read the [contribution guidelines](CONTRIBUTING.md) first. - -Links are checked automatically on the first of each month. Entries found permanently unreachable are flagged **(link no longer exists)** next to them. Please open a PR to fix or remove any you spot. - ## Contents - [Directories and Awesome Lists](#directories-and-awesome-lists)@@ -396,7 +393,7 @@ - [indielib](https://github.com/hacdias/indielib) - Go IndieWeb toolkit bundling IndieAuth client/server, Micropub, and discovery helpers.
- [benjifs/micropub](https://github.com/benjifs/micropub) - Serverless Micropub and media endpoint that publishes posts to a Git-backed static site. - [kirby-micropub](https://github.com/sebsel/kirby-micropub) - Micropub server endpoint for the Kirby CMS. - [selfauth](https://github.com/Inklings-io/selfauth) - Minimal single-user PHP IndieAuth authorization endpoint so you can be your own identity provider. -- [Indigenous for Android](https://indigenous.realize.be/) - Native Android app acting as a Micropub posting client and Microsub reader. **(link no longer exists)** +- [Indigenous for Android](https://indigenous.realize.be/) - Native Android app acting as a Micropub posting client and Microsub reader. - [Post Kinds](https://wordpress.org/plugins/indieweb-post-kinds/) - WordPress plugin adding reply/like/bookmark/RSVP post types with proper microformats2 markup and reply-context. - [Syndication Links](https://wordpress.org/plugins/syndication-links/) - WordPress plugin that displays and manages POSSE syndication URLs for cross-posted content. - [Semantic Linkbacks](https://wordpress.org/plugins/semantic-linkbacks/) - WordPress plugin enriching incoming Webmentions/pingbacks into semantic comments (likes, reposts, replies).@@ -451,7 +448,7 @@ - [Sharkey](https://joinsharkey.org/) - Actively maintained Misskey fork with quote posts and improved moderation.
- [Iceshrimp](https://iceshrimp.dev/) - Lean, rewritten Misskey-family server focused on performance and standards compliance. - [Firefish](https://joinfirefish.org/) - A Misskey fork (formerly Calckey) whose development has largely stalled. - [snac2](https://codeberg.org/grunfink/snac2) - Tiny C-based single/multi-user ActivityPub server with minimal dependencies. -- [Honk](https://humungus.tedunangst.com/r/honk) - Minimalist single-user ActivityPub server with no JavaScript. **(link no longer exists)** +- [Honk](https://humungus.tedunangst.com/r/honk) - Minimalist single-user ActivityPub server with no JavaScript. - [Epicyon](https://libreserver.org/epicyon/) - AGPL, low-resource ActivityPub server designed for small self-hosted communities. - [Hometown](https://github.com/hometown-fork/hometown) - Mastodon fork adding local-only posting and full-text formatting. - [Friendica](https://friendi.ca/) - Decentralized social server federating across ActivityPub, Diaspora, and more.@@ -667,7 +664,7 @@ - [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/) - Canonical color-contrast checker for meeting WCAG requirements.
- [Sa11y](https://sa11y.netlify.app/) - In-page accessibility QA assistant that flags content issues visually for authors. - [Colorable](https://colorable.jxnblk.com/) - Interactive tool to test text/background color combinations against contrast ratios. - [HTMLHint](https://htmlhint.com/) - Configurable static linter for HTML to keep markup clean and valid. -- [SVGO](https://github.com/svg/svgo) - Node tool to optimize and shrink SVG files, reducing page weight. **(link no longer exists)** +- [SVGO](https://github.com/svg/svgo) - Node tool to optimize and shrink SVG files, reducing page weight. - [Sharp](https://sharp.pixelplumbing.com/) - High-performance Node image-processing library for resizing and compressing images. - [oxipng](https://github.com/oxipng/oxipng) - Fast multithreaded lossless PNG optimizer. - [pngquant](https://pngquant.org/) - Lossy PNG compressor that greatly reduces size with minimal quality loss.@@ -717,7 +714,7 @@ - [The Black Cat](https://theblack.cat/) - Small, invite-only community hosting tiny handmade personal websites, with a browser-based editor and no JavaScript, trackers, or algorithms. ⭐ *Curator's pick*
- [HTML Energy](https://html.energy/) - Community and movement celebrating hand-written HTML and personal websites, with events and jams. - [MelonLand Forum](https://forum.melonland.net/) - Active forum and wiki for the old/personal-web revival, webrings, and Neocities-style building. - [SadGrl.online](https://sadgrl.online/) - Hub of webmastering guides, a layout generator, and resources encouraging indie sites. -- [Blaugust](https://blaugust.net/) - Annual month-long event encouraging people to (re)start personal blogging, with mentors and a Discord. **(link no longer exists)** +- [Blaugust](https://blaugust.net/) - Annual month-long event encouraging people to (re)start personal blogging, with mentors and a Discord. - [Recurring Creative Challenges](https://challenges.stefanbohacek.com/) - Directory of recurring indie-web and creative challenges that drive personal-site activity. - [Yesterweb](https://yesterweb.org/) - Influential anti-corporate "reclaim the web" community and webzine. - [omg.lol](https://omg.lol/) - Community of personal websites built around your own domain, with profile pages carrying h-card and rel=me, a weblog, statuslog and now pages, and the social.lol Mastodon instance. ⭐ *Curator's pick*