21 Commits

Author SHA1 Message Date
enricobuehler 619e2ccf0b chore(analytics): switch to new Plausible script snippet
Build & Deploy unom website / build (push) Successful in 54s
Build & Deploy unom website / deploy (push) Successful in 5s
Replace the legacy plausible.js + data-domain tag with Plausible's new
per-site script (pa-*.js) plus its inline init queue. The site identity
is baked into the script hash, so data-domain is no longer needed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 02:07:46 +02:00
enricobuehler 66ff3cffa8 Revert "fix(footer): default nav + tagline when the tenant's CMS footer is empty"
Build & Deploy unom website / build (push) Successful in 26s
Build & Deploy unom website / deploy (push) Successful in 5s
This reverts the hardcoded footer fallback. The footer stays fully CMS-driven;
the unom tenant's footer will be populated to mirror punktfunk's instead.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 18:25:19 +02:00
enricobuehler f47f7989e0 fix(footer): default nav + tagline when the tenant's CMS footer is empty
Build & Deploy unom website / build (push) Successful in 26s
Build & Deploy unom website / deploy (push) Successful in 4s
The unom tenant's footer doc has no sections yet (the multi-tenant migration
backfilled the old footer to the punktfunk tenant), so the footer rendered as
an empty, near-invisible bar. Render a sensible default (Übersicht/Rechtliches
links + site tagline) when there are no CMS sections; CMS content overrides it
once the unom footer is populated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 18:19:19 +02:00
enricobuehler 15130ae4df feat: adopt @unom/ui + add Projects section to the landing page
Build & Deploy unom website / build (push) Successful in 41s
Build & Deploy unom website / deploy (push) Successful in 5s
- Pull in @unom/ui (0.8.16) + @unom/style + peers; bump @unom/cms to 0.3.0.
- globals.css now provides the full semantic-token contract @unom/ui consumes
  (primary/accent/background/ring/radius-card/…), expressed with unom's violet
  brand + Inter/Ubuntu.
- Section wraps @unom/ui's Section (in-view animation orchestrator); PostCard,
  LatestPosts, and the hero use AnimatedCard/AnimatedText/AnimatedButton/Heading.
- lib/cms.ts moves to the multi-tenant model (tenant=unom), header/footer as
  per-tenant collections, + findProjects().
- New Projects section lists this tenant's projects on the landing page
  (soft-fails to hidden when empty). Starts with punktfunk.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 18:11:35 +02:00
enricobuehler 76dabef23d ci(deploy): self-install on a blank host via clone-if-absent [skip ci]
Mirror played/workflows build-deploy-game.yml so a freshly provisioned
unom-1 box self-installs the website repo on first deploy instead of
failing on a missing ~/unom-website checkout.

Before `cd ~/unom-website` the remote ssh script now:
  - installs git if absent (deploy user has NOPASSWD sudo)
  - clones the repo if ~/unom-website/.git is missing, reusing the
    existing REGISTRY_USER / REGISTRY_TOKEN secrets

Registry creds are passed into the remote shell via appleboy/ssh-action
`envs:` and consumed from the environment (docker login now uses
--password-stdin), so the token is never interpolated into the script
text / run log / process args.

Refs task #27.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 13:47:42 +02:00
enricobuehler 3eec9ba8b7 routes/index: use m.home_title() + pass undefined locale to findPosts
Build & Deploy unom website / build (push) Successful in 21s
Build & Deploy unom website / deploy (push) Successful in 5s
Title was hardcoded to the German string when I migrated the rest of
the site to paraglide — the rest of the site looked correct on /en/
because the localized meta came from the root route's head() which DID
use m.foo(). Index also passed 'de' literally to findPosts, ignoring
the request locale.
2026-05-26 19:33:45 +02:00
enricobuehler 7bf10b6a12 i18n: paraglide setup mirroring played/plaza, de unprefixed + /en/ prefixed
Build & Deploy unom website / build (push) Successful in 21s
Build & Deploy unom website / deploy (push) Successful in 4s
- project.inlang/settings.json with locales [de, en], baseLocale de.
- messages/{de,en}.json hold the strings (tagline, blog labels, etc.).
- vite.config.ts: paraglideVitePlugin compiles to src/paraglide/
  (gitignored) on dev/build. Strategy: url → cookie →
  preferredLanguage → baseLocale. URL pattern keeps German at /:path
  (unprefixed) and English at /en/:path so existing URLs stay valid.
- server.tsx wraps the handler in paraglideMiddleware so AsyncLocalStorage
  carries the per-request locale into SSR.
- router.tsx adds rewrite { input: deLocalizeUrl, output: localizeUrl }
  so route matching stays locale-agnostic — the router sees /blog while
  URLs show /en/blog.
- cms.ts narrows getLocale()'s union back to the de|en pair the CMS
  supports, used as the default for find/findGlobal calls.
- Components/routes switch to m.foo() for user-visible strings; date
  formatting picks de-DE / en-GB from getLocale().
- Root html lang reads getLocale() so the document language flips per
  request.

Known minor: TanStack Start's { title } meta entry still serves the base
locale value (og:title and the description meta are localized correctly).
Will track separately.
2026-05-26 19:23:35 +02:00
enricobuehler a7ebe77979 visual polish: typography rhythm, hover states, post card, hero overlay
Build & Deploy unom website / build (push) Successful in 19s
Build & Deploy unom website / deploy (push) Successful in 5s
- globals.css: tighter type scale (display h1 = 4xl, snug leading), section
  spacing scales up at xl (45→80px y), section width caps at 1280 (was 1550)
  for better text-line-length, paragraphs constrained to 65ch.
- Secondary text bumped to 0.78 lightness for better contrast on the dark
  bg (was 0.85, too low).
- Hover: links get underline-offset + animated color transition; PostCard
  lifts on hover with a brand-tinted ring.
- Markdown rhythm rewritten: h2 starts a new visual section (mt-12), p/li
  use sensible margins. Drop whitespace-break-spaces (Lexical now emits
  real linebreaks).
- Hero: gradient overlay so the tagline reads cleanly over the busy image,
  subtle ↓ scroll hint at the bottom, logo scales between 180 / 220 px.
2026-05-26 19:17:31 +02:00
enricobuehler fdb6328807 landing: tagline below logo + 'Aus dem Blog' section with 2 latest posts
Build & Deploy unom website / build (push) Successful in 18s
Build & Deploy unom website / deploy (push) Successful in 4s
- Hero shrinks from 100vh to 90vh so a slice of below-fold content peeks.
- Logo is now in a normal flex column with the tagline 'Kreative
  Webentwicklung aus Rottweil' centered beneath it.
- New LatestPosts section reads the two most recent posts from CMS via
  the SDK and skips entirely if posts.length === 0 (so the section
  doesn't materialize while the blog is empty).
2026-05-26 19:13:50 +02:00
enricobuehler f19457337d website: switch to typed PayloadCMS SDK via @unom/cms
Build & Deploy unom website / build (push) Successful in 19s
Build & Deploy unom website / deploy (push) Successful in 6s
- Add @payloadcms/sdk + @unom/cms (typed Config) to deps
- .npmrc maps @unom to git.unom.io/api/packages/unom/npm/
- Rewrite src/lib/cms.ts: PayloadSDK<Config> client + typed helpers
  (findPageBySlug, findPostBySlug, findPosts, findFooter, findHeader)
- Re-export the structural types (Page, Post, Footer, Header) plus the
  legacy aliases (RichTextBlock, LexRoot/LexNode, NavigationSection,
  NavigationLink) so existing components keep compiling
- Dockerfile mounts /root/.npmrc as a build secret so bun install can
  pull @unom/cms from the private gitea registry
- deploy.yml stages an .npmrc with REGISTRY_TOKEN auth + passes it as
  the 'npmrc' build secret
- Add blog routes: /blog (list) + /blog/ (detail), PostCard, all
  reading from the CMS via the SDK
- Fix two pre-existing TS errors (@fontsource/inter import, server.tsx
  return type)
2026-05-26 19:10:27 +02:00
enricobuehler 70bd04a3f6 header: shrink logo link to 70% of header height so it stops clipping at smaller breakpoints
Build & Deploy unom website / build (push) Successful in 10s
Build & Deploy unom website / deploy (push) Successful in 5s
2026-05-26 19:00:20 +02:00
enricobuehler a327a2daf3 header logo + legal pages: fit-to-header + top inset
Build & Deploy unom website / build (push) Successful in 12s
Build & Deploy unom website / deploy (push) Successful in 4s
- Header link sizes to 70% of the header height (aspect-square) so it
  fits at all breakpoints instead of overflowing the 100px default
  height. Was hard-pinned to 120×120 which clipped on small headers.
- LegalPage adds pt-height-header so content starts below the fixed
  header instead of being covered by it (the Landing route stays
  full-bleed intentionally).
2026-05-26 19:00:06 +02:00
enricobuehler faa663c0e5 logos: set w-full on the SVGs so they actually fill their flex parents
Build & Deploy unom website / build (push) Successful in 11s
Build & Deploy unom website / deploy (push) Successful in 5s
Without explicit dimensions the browser fell back to the SVG default
(300×150 CSS px), overflowing the 120×120 header link and hiding
behind the backdrop-blur.
2026-05-26 18:57:50 +02:00
enricobuehler f4a08ea3a0 styles: fix --main oklch value (100 → 1)
Build & Deploy unom website / build (push) Successful in 11s
Build & Deploy unom website / deploy (push) Successful in 4s
Tailwind/CSS parser was normalizing the bare `100` lightness to
`10000%`, which is out of range — browsers fell back to the SVG
default (black), making the white logo invisible on the dark hero.
2026-05-26 18:54:30 +02:00
enricobuehler 42a47cd2ab website: read legal pages + footer from unom-cms
Build & Deploy unom website / build (push) Successful in 11s
Build & Deploy unom website / deploy (push) Successful in 4s
- Add src/lib/cms.ts: REST helpers (findPageBySlug, findFooter, findHeader)
- Add src/components/RichText.tsx: minimal Lexical → React renderer
  (heading h1-h4, paragraph, list, listitem, link, text + linebreaks +
  basic text-format bitflags).
- routes/legal/{imprint,privacy}.tsx now fetch via route loader; meta
  title + description come from the Page's own fields.
- Footer reads the Footer global via the root route's loader using
  getRouteApi('__root__'). Three sections + tagline match the previously
  hardcoded structure (now editable via cms.unom.io/admin).
- Drop react-markdown + src/content/legal/*.md (CMS is the source of truth).
2026-05-26 18:50:10 +02:00
enricobuehler ce63faa8f3 migrate from astro+netlify to tanstack start + self-hosted
Build & Deploy unom website / build (push) Successful in 12s
Build & Deploy unom website / deploy (push) Successful in 4s
Replace the Astro static site with a TanStack Start (Bun runtime) app and
add Dockerfile + compose files so the site can be served from home-main-2
behind the home-reverse-proxy-1 Caddy instead of Netlify. CI workflow
rewritten to build a container image and SSH-deploy to the home host.
2026-05-26 10:57:16 +02:00
enricobuehler b203d1b58a update favicon
Deploy to Netlify / deploy (push) Successful in 1m1s
2025-05-22 19:10:06 +02:00
enricobuehler 02efe24ba9 replace favicon
Deploy to Netlify / deploy (push) Successful in 1m0s
add correct favicon path to root layout
2025-05-22 19:08:00 +02:00
enricobuehler 65cf321781 add ci
Deploy to Netlify / deploy (push) Successful in 59s
2025-05-22 17:54:49 +02:00
enricobuehler 6fb1e51c79 initial commit 2025-05-22 17:46:02 +02:00
enricobuehler a6d168c504 Initial commit 2025-02-11 16:24:30 +00:00