CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

What this is

OpenSourceFeed (https://www.opensourcefeed.org): a Jekyll site that showcases free operating systems and desktop environments, with release news posts and a monthly popularity index. There is no test suite or linter.

Commands

bundle exec jekyll serve          # local dev server at http://127.0.0.1:4000
bundle exec jekyll build          # build into _site/

ruby scripts/generate_galleries.rb          # re-index screenshots/ into _data/galleries.json
ruby scripts/generate_image_dimensions.rb   # re-measure logo/preview images into _data/image_dimensions.json

cd assets/pageview && ./pagerank.sh         # rebuild _data/rank.yaml from Google Analytics (needs credentials.json and .env venv)

Re-run the two Ruby generators after adding screenshots, logos or preview images. Layouts read their output to render galleries and to emit width/height attributes that prevent layout shift.

Deployment constraint: GitHub Pages classic

The site is built by GitHub Pages’ classic builder; there is no workflow file. Production therefore uses the github-pages gem’s Jekyll 3.x and libsass, even though the local Gemfile pins Jekyll 4. Avoid anything that only works locally:

  • No Dart-Sass-only features: @use, math.div, or Sass-evaluated min()/clamp(). Use @import and plain division.
  • Only the plugins listed in _config.yml (all are on the GitHub Pages allowlist).

Content model

Content pages link to each other through front matter, not through code:

  • Distribution pages (distribution-*.md, layout: distribution, Category: Distribution) and desktop pages (desktop-*.md, layout: desktop, Category: Desktop) each have a uid.
  • Posts (_posts/, layout: post) list categories. A category equal to a page’s uid makes the post appear in that page’s stories (site.categories[page.uid]), and the post header renders that category as a link to the page.
  • A distribution’s desktops: [...] lists desktop uids; the desktop layout uses it to show distributions that ship that desktop.
  • A distribution’s base: [...] lists parent uids; distro-group pages (distro-groups/, layout: distro-group, group:) and the “based on” lists use it.
  • releases: maps release names to post URLs or external links.
  • redirect_from aliases exist on many pages; the rank script merges hits on aliases into the canonical page.

Posts use the :title/ permalink. .post-template is the starter front matter for screenshot posts, which include image-gallery.html with a screenshots/<folder>.

Data files

  • _data/rank.yaml: live 30-day and 3-month popularity ranking, generated by assets/pageview/fetch4.py. It also writes frozen snapshots to _data/rank_history/<key>.yaml, matching stub pages in rank-archive/, and updates the month in the titles of page-hit-rank*.md. Do not hand-edit these; existing snapshots are never overwritten unless --rebuild-history is passed.
  • _data/galleries.json, _data/image_dimensions.json: generated by scripts/ (see above).
  • _data/distro_groups.yml: distro-group definitions.

Front end

  • assets/style/style.scss is the single stylesheet. Design tokens are Sass variables at the top (palette, $color-*, radii, durations), exposed as --osf-* custom properties in :root for includes that use inline styles. It imports _sass/_foundation.scss.
  • _sass/_foundation.scss is a small in-house replacement for Bootstrap 5 that keeps Bootstrap’s class names (grid, navbar, dropdown, pagination, table, alert, badge, btn, form-control, utilities). Bootstrap is no longer loaded; add any missing class here rather than reintroducing the CDN.
  • assets/script/main.js is the only site script (vanilla JS): navbar collapse and dropdowns (Web Animations API, respects reduced motion), wrapping wide tables, home-page search filtering, and the shrinking navbar on scroll.
  • Layouts: default.html (three columns with sidebar ads), wide.html, post.html, distribution.html, desktop.html, distro-group.html, rank-archive.html, blog.html (paginated at /blog/). Most layouts wrap compress.html, which minifies HTML.
  • Brand assets live in assets/images/brand/ plus favicon.ico, favicon.svg, apple-touch-icon.png and site.webmanifest at the root. The navbar and footer render the wordmark as text (.wordmark / .wordmark-accent).

Conventions

  • assets/script/main.js and index.html use CRLF line endings; preserve them when editing.
  • The game directories (decordle/, pentordle/, word-gridle/, word-plant/, enlighten/, enlighten-tv/) are standalone HTML pages that do not use the site layouts or stylesheet. Leave them out of site-wide changes.
  • AdSense units are embedded directly in layouts and includes. Unfilled units are hidden by CSS, and in-content units use .ad-reserve to reserve height.