Files
Cyborg Viktor 248af07a54 fix(website): unescape JSON-LD strings, answer "is this Screenly OSE?" (#3222)
Two things, both found while looking at why the old product name
converts so badly in Search Console.

1. Every JSON-LD string value is wrapped in literal quote characters.

   Go's html/template applies contextual auto-escaping inside <script>,
   so `{{ .Title | jsonify }}` gets escaped a second time as a JS
   string. The emitted value is "\"Installation Options\"" rather than
   "Installation Options". The JSON stays valid, which is why this went
   unnoticed, but every headline, description and FAQ question carries
   stray quotes into Google's rich results.

   19 affected values: TechArticle headline + description on all 9 docs
   pages, the site description, and all 29 FAQ questions and answers.
   Fixed by adding `| safeJS` after `jsonify` at all five call sites —
   jsonify already produces correctly escaped JSON, so the second pass
   was pure corruption. All 11 ld+json blocks now parse clean with zero
   stray-quote values.

2. The site never mentioned "Screenly OSE" — its own former name.

   Search Console, last 90 days: 23 old-name queries, 1,962 impressions,
   43 clicks (2.19% CTR). "screenly ose" alone is 1,253 impressions at
   position 6.8 for 17 clicks; "screenly ose pi3" and "screenly ose
   pi 3" are 429 impressions for zero clicks.

   Where the two names appear together, the same searchers convert an
   order of magnitude better: "anthias (screenly ose)" is 16 clicks from
   31 impressions (51.6%) and "anthias screenly ose" 9 from 20 (45%).
   People looking for the old name do want this project — the site just
   never confirms they are in the right place.

   Adds an FAQ entry (inherits the existing FAQPage schema, so it is
   eligible as a rich result) citing the December 2022 announcement
   linked from the repo README, plus one line under the homepage hero.

hugo 0.157.0 (the version pinned in deploy-website.yaml) builds clean.

Co-authored-by: Cyborg Viktor <307551610+vpetersson-bot@users.noreply.github.com>
2026-07-28 09:47:04 +01:00
..

Anthias Website

This is the source code for anthias.screenly.io, built with Hugo and Tailwind CSS v4.

Local Development

The site needs the Tailwind output and self-hosted fonts to be generated before Hugo serves anything. Run the bun pipeline once, then start Hugo (or use bun run dev to do both with watchers):

cd website
bun install
bun run css:build      # generates assets/styles/style.css and static/fonts/
hugo server

Or, with hot reload on CSS + templates:

cd website
bun run dev            # bun css:watch + hugo server in parallel

The site will be available at http://localhost:1313.

Skipping the bun step will load the page with broken styling and 404s for /fonts/...woff2 — the font files come from the npm package @fontsource/plus-jakarta-sans and are materialized at build time, not committed. Icons are handled the same way: bun run icons:install copies a curated subset of Font Awesome SVGs from @fortawesome/fontawesome-free into assets/images/icons/ (gitignored). Both run automatically as part of css:build / css:watch.

Home-page screenshot slider

The hero on / is a slider fed by PNGs in assets/images/screenshots/. The directory is gitignored — captures are produced by the marketing-screenshots.yaml workflow and pulled into the build at deploy time. To preview the real slider locally:

bun run screenshots:fetch     # latest successful master run
bun run dev

The fetch script needs the gh CLI authenticated; it targets Screenly/Anthias by default so the upstream artifact is reachable even from a fork clone. Pass --ref <branch> to pull from a different branch's most recent run, or --repo <owner>/<repo> to point at a different repo. Without screenshots, Hugo still builds — the slider section simply omits.

Build

cd website
bun run build          # bun css:build && hugo

Output goes to website/public/.

Project Structure

website/
├── assets/                       # Hugo Pipes inputs
│   ├── docs/                     # Doc images / d2 diagram
│   ├── fonts/                    # Generated by bun fonts:install (gitignored)
│   ├── images/                   # Site images, logos, hero
│   └── styles/                   # Built Tailwind + chroma stylesheets
├── content/
│   ├── _index.md
│   ├── api.md                    # /api/ — OpenAPI rendered server-side
│   ├── docs/                     # /docs/* (rendered via layouts/docs/)
│   ├── faq.md                    # /faq/ — driven by data/faq.yaml
│   ├── features.md
│   └── get-started.md
├── data/
│   ├── faq.yaml                  # FAQ entries grouped by section
│   └── openapi.yaml              # drf-spectacular dump for the /api/ page
├── layouts/
│   ├── _default/
│   │   ├── _markup/              # Goldmark render hooks (image, blockquote)
│   │   ├── api.html              # /api/ template
│   │   ├── baseof.html           # Base HTML
│   │   ├── faq.html              # /faq/ template
│   │   └── ...
│   ├── docs/                     # /docs/ list and single layouts
│   ├── index.html                # Home page
│   └── partials/                 # navbar, footer
├── scripts/
│   └── install-fonts.ts          # Materializes Plus Jakarta Sans from npm
├── src/
│   └── main.css                  # Tailwind entrypoint
├── static/
│   ├── fonts/                    # Generated by bun fonts:install (gitignored)
│   └── robots.txt
├── hugo.toml                     # Hugo configuration
├── package.json                  # Bun scripts: dev / css:build / fonts:install
└── public/                       # Build output (gitignored)