Changed
main and test (and on pull requests) instead of on every branchcommit.sh and commit.bat end by saying to push test and open a pull request into maintest branch flow: work and releases happen on test, and reach main only through a reviewed pull request that needs CI to passFixed
requirements.txt lists hypercorn, which start.sh runs, so a fresh venv can start the appFixed
kittens-deploy.sh checks the venv with an explicit if instead of A && B || C, which CI's shellcheck
rejects (SC2015)Added
main, .github/workflows/deploy.yml asks the server to
deploy that exact commit. The server side, deploy/auto-deploy/ (kittens-deploy.sh and install.sh), runs
from a root-owned copy outside the checkout, behind a deploy-only key restricted to that one command. It takes
a lock, refuses a commit that is no longer the tip of main, backs up config.json, fast-forwards as the
site's user, installs requirements.txt into the venv when it changed, restarts the pm2 app and checks its
health. The README's new "Deploying" section covers setting it up.github/workflows/ci.yml: the unit tests, the version check and a lint of the deploy scripts, on every push
and pull request/health.json, reporting ok (the app is serving and has images), the running version and the image count.gitattributes, keeping shell scripts on LF line endingsChanged
Added
discord_embed.py). The Open Graph tags stay as the fallback, and error pages don't get one/favicon.ico (16, 32 and 48px), /apple-touch-icon.png, /site.webmanifest and the 192 and 512px icons (including a maskable one), served from public/. The tags are printed on every page from templates/_head_extra.html, including the error pagestests/test_site.py, covering the Discord embed, the favicon set and the changelog renderer with Date Version headingstests/version.sh, which checks that VERSION.md is a valid Date Version, a real calendar date not in the future, and the same as the newest entry in this changelogChanged
YY.MM.DD, with -1, -2… for later releases the same day. This release follows v1.9.1commit.sh and commit.bat refuse a VERSION.md that isn't a valid Date Version or is dated in the future (UTC), and warn when it's dated before todayREADME.md and CONTRIBUTING.md describe Date Versioning and the release stepsFixed
/dog, /puppy and friends) was a bare fragment with no title or styling; it's now a full page in the same style as the other error pages, with a title, the Kittens look and a random-kitten link, and the same jokeAdded
templates/error.html (same look as the 404 page), each with a plain-English explanation, and the 4xx ones still suggest a random kittenerrors/ (400, 413, 502, 503 and 504): when Kittens is down or restarting, nginx serves these instead of a generic page. They're generated from the same template, with the CSS inlined, by bin/build_static_errors.pynginx/kittens-errors.conf, the nginx snippet that serves errors/ for those codes on kittens.stuxapis.net and kittensapi.stuxapis.netChanged
logo-light/logo-dark and icon-light/icon-dark filesFixed
Changed
Changed
### sections within each release are sorted into that same fixed order (Added, Changed, Fixed, Removed, Security, Deprecated) at render time, whatever order CHANGELOG.md lists them in; unknown types go lastAdded
404.html (matching the about/legal page style) for unmatched routes and missing kitten files, replacing Quart's default plain-text error page.Changed
2024-<current year> range, even in 2024 itself (when it should've just read 2024). Now shows just 2024 (Kittens' real first-commit year) until the current year moves past it, then the range.Added
templates/index.html
(og:type, og:site_name, og:url, image dimensions/alt, and the full
twitter:* set) — previously only a partial og:image/og:title/
og:description set existed, with no Twitter card tags at all.Added
https://services.stuxapis.net) in the site footer.Fixed
LICENSE and README.md's copyright line named Stux.Group (a brand, not a legal entity) — corrected to Stux Group Ltd.Fixed
README.md's Stux.Group brand icon URL had a leftover duplicated /global/ path segment (global.media.stux.group/global/icon.png) — corrected to https://global.media.stux.group/icon.pngAdded
assets/fontawesome/, served via the existing /assets/<path:filename> route) — the GitHub links on /about and /legal/imprint now show the GitHub brand icon. legal/_base.html gained a {% block head_extra %} so only the sub-page that needs Font Awesome's CSS loads it, instead of every legal page paying for itChanged
/changelog restyled to match the TIGHC changelog page (tighc.stuxie.dev/changelogs): each ### Added/Changed/Fixed/Removed/Deprecated/Security heading now renders as a colored uppercase pill badge instead of plain text, version headings use a bold monospace font, and list items get an accent-colored dash marker instead of the default bullet. index.py's /changelog route now post-processes the rendered Markdown to swap <h3> headings for badge <p> tags and tag <ul> elements for the new styling; kittens.css gains the corresponding .cl-label/.cl-list rulesAdded
/about — a new page describing what Kittens is, its endpoints, and who runs it, linked from the homepage footer, /changelog footer, and the legal pages' shared footerChanged
[email protected] instead of the general [email protected]; the Imprint and Disclaimer pages' own contact links, and CONTRIBUTING.md's "Questions" section, now point at the general [email protected] insteadFixed
/changelog (and any other page using the shared .legal-body narrow-column layout) could overflow horizontally on mobile: long unbroken inline code spans and URLs in the rendered Markdown had no wrapping rule, so they'd extend past the content column instead of breaking onto a new line — body.legal-body now sets overflow-wrap: break-word/legal hub page inherited the shared legal-page header link ("← Back to Boring Legal Stuff") from legal/_base.html, which pointed right back at itself — it now reads "← Back to Kittens" and links to /, like every other page's back link. legal/_base.html's top link is now a {% block backlink %} so the hub page can override itChanged
logo.svg/icon.png (profile.png renamed) moved from being vendored locally to the shared CDN at https://global.media.stuxapis.net/kittens/logo.svg / /icon.png — every template/README reference updated accordingly and no longer carries the ?v= cache-buster, since cache invalidation for that asset is now the CDN's concern rather than this repo's release versionassets/ moved out of templates/ to the project root, since it's not Jinja template content — only templates/assets/css/kittens.css and templates/assets/fonts/ survive the move (to assets/css/ and assets/fonts/); templates/assets/images/ is gone entirely now that those assets live on the CDN. index.py's /assets/<path:filename> route now serves from assets instead of templates/assets, and the /assets/css/kittens.css route no longer goes through Jinja's render_template (which requires the file to live under templates/) — it's now a plain file read with a manual {{ version }} substitution, since that placeholder was the only reason it was ever Jinja-rendered in the first place(Page) | Legal - Kittens format (e.g. Privacy Policy | Legal - Kittens), matching the convention used across the org; the hub page itself is titled just Legal - KittensChanged
README.md's footer "Built & Maintained by StuxAPIs" icon now uses StuxAPIs' own logo (https://global.media.stuxapis.net/icon.png) instead of the GitHub org avatar (github.com/StuxAPIs.png), now that StuxAPIs has real branding of its ownAdded
?v={{ version }} cache-busting extended to every asset reference, not just kittens.css: logo.svg and profile.png (favicon/og:image, across all three page templates) now carry it tookittens.css is now served through a dedicated route (/assets/css/kittens.css) that renders it via Jinja instead of as a static file, so the Fredoka @font-face URL embedded inside the CSS can also carry ?v={{ version }} — the one asset reference that couldn't be versioned just by editing HTML templates, since it lives inside the CSS file itselfFixed
logo.svg's viewBox was cropped tight horizontally (v1.5.0) but the "Kittens" wordmark was still only font-size 52 against a 96px-tall icon badge, leaving a lot of visually empty space above/below the text relative to the icon's weight. Bumped to font-size 80 (measured the actual rendered text width/height to keep the crop tight rather than guessing) for a much better-balanced icon/wordmark lockup/changelog (and any other long-content page using .legal-body) had its bottom padding effectively swallowed: the global body { height: 100% } rule (needed for the homepage's fullscreen single-viewport layout) clamped the body's box to one viewport tall, so on pages taller than the viewport the specified 5rem bottom padding was calculated relative to that clamped box instead of after the actual (overflowing) content — visually, the last element sat flush against the bottom of the page with no padding at all. body.legal-body now sets height: auto to opt out of that constraintFixed
kittens.css was linked with a hardcoded ?v=1.0.0 query string that was never bumped across any release since it was introduced in v1.2.0 — Cloudflare/the browser kept serving a stale cached copy of the CSS from before v1.5.0 forever, since the cache key (the URL) never changed even though the file's actual content kept changing underneath it. Confirmed directly: the browser's parsed stylesheet had 33 rules and was missing .site-footer entirely, while the origin file (verified via a cache-busted fetch) was the correct, current 175-line file all along — the server-side files (profile.png included) were never actually wrong, they just weren't being fetchedindex.html, legal/_base.html, changelog.html) now link kittens.css?v={{ version }} instead of a hardcoded string, so every release automatically busts the cache going forward — legal(), legal_page(), and changelog() now also pass version=VERSION to their templates (previously only index() did)Changed
README.md's two "Built & Maintained by StuxAPIs" links (tagline and footer disclaimer) now also point to stuxapis.net, matching the homepage change in v1.5.1Changed
github.com/StuxAPIs — the README's own disclaimer footer still links to GitHub, matching the convention used across the rest of the org's reposChanged
clamp()-based fluid font sizing instead of fixed rem values (which didn't scale down for mobile), .center-object gained horizontal padding, body gained overflow-x: hidden as a safety net, and the viewport meta tag no longer disables pinch-zoom (user-scalable=no, maximum-scale=1.0 removed — an accessibility/mobile-friendliness anti-pattern)Fixed
/ (the homepage route) never passed domain to its template, unlike every other route — {{ domain }} silently rendered as empty everywhere on the homepage. It happened to still resolve correctly by coincidence there (root-relative paths behave the same as domain-absolute ones at /), but broke the Open Graph og:image tag, which requires an absolute URL for link previews on Discord/Twitter/etc. Now passes domain=domain like every other routetemplates/assets/images/profile.png (used for the favicon and og:image) was still the literal old Twemoji cat-emoji graphic — the one that used to sit in the homepage <h1> before the logo redesign, never actually replaced when that redesign happened. Replaced with a proper square icon matching the new logo's cat-face designlogo.svg's viewBox was 400 wide, but the actual icon+wordmark content only occupied about the first 300px, leaving ~70px of dead space on the right — this made the logo look off-center on the page even though its bounding box genuinely was centered. Trimmed the viewBox to fit the content tightly (measured the actual rendered text width rather than guessing).logo-img set both a fixed height: 90px and max-width: 85vw without height: auto — on any viewport narrower than ~423px this would have squished the logo's aspect ratio once max-width became the binding constraint. Changed to max-height + max-width with both width/height: auto, the standard "fit in box, preserve aspect ratio" patternChanged
README.md's "Website" section updated to reflect the site as it actually is now: added the /changelog page link, and notes on the self-hosted kittens.css stylesheet and self-hosted Fredoka font (previously undocumented)config.json.example's description field ("Get random pictures of kittens") reworded to "An API that provides random images of kittens", matching README.md's tagline. Note: this only updates the template — the actual config.json on the production server is gitignored and won't pick this up automatically; it needs updating there by hand (same as the title field previously)Fixed
README.md's header logo pointed at templates/assets/logo.svg, which moved to templates/assets/images/logo.svg in the v1.4.0 asset reorg — the .md file wasn't caught by that pass since it only swept .html templates, so the logo stopped rendering on the GitHub repo pageFixed
{{ config.title }} ("Kittens") as the copyright holder with only the current year — now reads 2024-{{ year }} StuxAPIs, matching the copyright holder/start year used in LICENSEAdded
templates/assets/fonts/Fredoka.woff2 plus its OFL.txt license, wired up via @font-face in kittens.css. Replaces the default system font stack site-wide; no external Google Fonts request is madeChanged
templates/assets/ reorganized into css/, fonts/, and images/ subfolders instead of one flat directory/assets/<filename> route changed to /assets/<path:filename> so nested asset paths (e.g. assets/fonts/Fredoka.woff2) actually resolve — the previous single-segment route 404'd on anything not directly in templates/assets/. This only affects the /assets/* prefix; the root-level kitten image routes (/<filename>, /random, etc.) are untouched and still resolve exactly as before (e.g. https://kittens.stuxapis.net/ch5brn70egd_kitten.jpeg)Added
/changelog — renders this file (minus the leading title/intro) as HTML via the new markdown dependency, styled to match the legal pagesVERSION.md at startup), linked to /changelog — replacing the old bare "Boring Legal Stuff" linkChanged
templates/legal/_base.html's embedded <style> block and into templates/assets/kittens.css, so the new changelog page (which isn't part of the legal-page block hierarchy) can reuse the same layoutAdded
templates/assets/kittens.css — a small, self-contained stylesheet replacing the ModestaCSS/Twemoji framework dependency, covering exactly what the homepage and legal pages actually use (dark theme base, hero layout, buttons, animation keyframe)Changed
logo.svg); "Built & Maintained by StuxAPIs, Hosted by Stuxedo" moved to its own line, after the "Images in API" count instead of sharing a line with it#d35400) exactly, instead of ModestaCSS's default honey/orange/pinewood palette (#eab543/#f39c12/#fdcb6e) — classes renamed honey-text/pinewood-text/orange-bg → accent-text/accent-bg to matchREADME.md's "Open Source"/"Website" sections no longer credit AlexFlipnote's Coffee API fork or ModestaCSS, since neither is used anymoreRemoved
templates/assets/modesta.css, modesta3.1.0.css, twemoji.css — no longer referenced by anythingFixed
templates/assets/logo.svg redesigned — the plain circle-with-triangle-ears silhouette didn't read as a cat at all. Added whiskers and shaded inner ears (the actual recognizable cat cues) and dropped the mouth curves, which were rendering as an unintentional frownAdded
templates/assets/logo.svg — a full wordmark logo (cat-face icon + "Kittens" text), used as the README header image. The existing templates/assets/profile.png icon is unchanged and still used for the site's favicon/og:image.Changed
README.md, CONTRIBUTING.md, CHANGELOG.md, config.json/config.json.example's title field, pm2.json's app name, and all five templates/legal/*.html pagesgithub.com/StuxAPIs and stuxedo.com), matching the branding used everywhere else in the orgREADME.md's tagline now matches the live GitHub description, ending in "Built & Maintained by StuxAPIs, Hosted by Stuxedo."Changed
LICENSE and README.md copyright year updated from 2024 to 2024-2026Changed
README.md's footer brand-attribution block updated to the new two-line format (Built & Maintained by StuxAPIs, Hosted by Stuxedo / StuxAPIs is a part of the Stux.Group brand of businesses), replacing the older single-line disclaimerChanged
Changed
README.md's "StuxAPIs is part of the Stux.Group Brand of Companies" line now includes the Stux.Group icon inlineAdded
VERSION.md, CHANGELOG.md, CONTRIBUTING.md, commit.sh/commit.bat — brought the repo onto the standard StuxAPIs release flow (bump VERSION.md, update this changelog, run commit.sh/commit.bat to commit and tag vX.Y.Z)/legal, linked from the homepage footer as "Boring Legal Stuff", with six sub-pages: Privacy Policy, Terms and Ethics, Cookies Policy, Imprint, Disclaimer, and Opt-Out Preferences (templates/legal/, routed in index.py)dev-server.sh/dev-server.bat — local dev launcher that forces dev-mode config ("localhost": true, pointing asset/redirect URLs at 127.0.0.1) by default, with a --no-dev-mode flag to test production config locally; also bootstraps config.json and a placeholder images/ folder if missing so the app doesn't crash on a fresh checkoutChanged
README.md given a proper header image, quick endpoint reference, local development instructions and license/copyright sectionsLICENSE copyright holder normalized to Stux.Group