Static site for Iknaio Cryptoasset Analytics. Built with Hugo, plain CSS, and minimal vanilla JS. Currently published at https://iknaio.github.io/iknaio.com/ via GitHub Pages; final domain will be https://iknaio.com/ once DNS is flipped (see TODO.md).
Requires Hugo 0.147.4 extended (installed at ~/bin/hugo):
~/bin/hugo server # dev server with live reload at http://localhost:1313/
~/bin/hugo # production build into ./public/Drafts (draft: true in front matter) don't render unless you pass -D:
~/bin/hugo server -DDeployment is automatic: every push to main triggers the GitHub Actions workflow that builds and publishes to Pages.
Posts live in content/insights/ as Markdown files. The slug becomes the URL (/insights/<slug>/).
-
Create the post file at
content/insights/<slug>.mdwith this front matter:--- title: "Your Post Title" date: 2026-04-22 description: "One-sentence summary — used for SEO, OG preview, and insight-card subtitle." tags: ["tag1", "tag2"] image: "images/insights/<slug>/cover.png" posttype: "insight" aliases: ["/blog/<slug>/"] ---
posttypeaccepts"insight"(default editorial),"news"(announcements), or"case-study"(e.g. Operation Alice). The post-card label is set from this value.imageis the card thumbnail and the OG preview image; usecover.pngorcover.jpg.aliasespreserve old/blog/<slug>/URLs as redirects to the new/insights/<slug>/path.
-
Add images under
static/images/insights/<slug>/:cover.png(or.jpg) — required; used for card + social preview.figure-1.png,figure-2.png, … — optional inline figures.
-
Reference inline figures in the body as:

The leading slash is fine —
layouts/_default/_markup/render-image.htmlis a Hugo image render hook that strips the leading slash and pipes the path throughrelURLso it works under any baseURL (localhost or/iknaio.com/on GitHub Pages). -
Preview:
~/bin/hugo server -Dand open/insights/.
content/ Markdown content
_index.md Home (front-matter-driven; edit hero/products/why/trust/case-study/etc. here)
insights/ Blog posts + /insights/ landing
about/, packages/, solutions/, contact/ …
imprint.md, privacy.md, tcs.md
data/ YAML data files consumed by templates
packages.yaml Tiers, feature matrix, FAQ
team.yaml Founders + team + advisors
partners.yaml Customers, research, resellers, funding
press.yaml Press logos
use_cases.yaml Solutions page (Investigate / Comply / Advise)
layouts/ Hugo templates
_default/ baseof.html, single.html, _markup/render-image.html
partials/ head, nav, footer, cookie-banner, packages/comparison-cell
index.html Home (all home sections inlined — single readable template)
<section>/ Section-specific layouts (about, contact, packages, solutions, insights)
robots.txt Custom robots.txt with explicit AI-bot allowlist
assets/ Pipeline-processed (minified + fingerprinted)
css/main.css Full design system (tokens, components, dark mode, responsive)
js/main.js Mobile nav, dark-mode toggle, scroll behaviour
js/cookie-banner.js Consent banner + Plausible gate
static/ Files served as-is at site root
images/ Photos, product screenshots, logos, icons, insights/<slug>/ folders for post covers + figures
fonts/ woff2 (Brawler / General Sans / Roboto)
favicon/
- Home page copy lives in
content/_index.mdfront matter (hero, products, secondary_audience, why, trust, case_study, press, cta). Don't hunt through templates. - Team / partners / press / packages / use_cases are YAML in
data/. Changes there propagate automatically. - Navigation is defined in
hugo.tomlunder[[menus.main]]. - Design tokens (colors, spacing, fonts) are CSS custom properties at the top of
assets/css/main.css. - Dark mode is a
[data-theme="dark"]attribute on<html>; toggled inassets/js/main.js, respectsprefers-color-scheme. - Cookie banner is rendered from
layouts/partials/cookie-banner.html+assets/js/cookie-banner.js. Persists choice inlocalStorage(iknaio-cookie-consent), gates loading of Plausible analytics until consent is given. The footer "Cookie Settings" link reopens the banner.
Playwright check (screenshots + broken images/links + responsive + dark mode):
export FNM_DIR="$HOME/.local/share/fnm" && export PATH="$FNM_DIR:$PATH" && eval "$(fnm env)"
node qa-check.mjsScreenshots land in qa-screenshots/. Known false positive: lazy-loaded press logos / team photos / blog covers may be reported as "broken images" — spot-check via curl -sI <url> | head -1 confirms they serve HTTP 200.
See TODO.md for the remaining checklist (custom domain DNS, Formspree form ID, Plausible account, real content for placeholder pages).