Skip to content

Repository files navigation

TabMates website

The promotional website for TabMates, published at tabmates.de.

This repository contains only the marketing site. It is not the app.

What Where
This site (marketing) tabmates.de — this repo
The actual app (Web/PWA) app.tabmates.deTabMates/app
Backend TabMates/server

Static Astro site, built to plain HTML/CSS and served by GitHub Pages. No analytics, no cookies, and no third-party requests at runtime — that is a deliberate constraint, not an accident, because the site makes that claim on the privacy section of the landing page.

Quick start

Requires Node 22 (see .nvmrc).

npm ci
npm run dev      # http://localhost:4321
Script Does
npm run dev Dev server with hot reload
npm run build Static build into dist/
npm run preview Serve the built dist/ locally
npm run check astro check — TypeScript and template diagnostics
npm run format Prettier, write
npm run format:check Prettier, verify only (this is what CI runs)
npm run og Regenerate public/og-image.png from the feature graphic

Structure

src/
├─ assets/
│  ├─ brand/feature-graphic.png     source for the OG image
│  ├─ logo.svg                      the mark, copied from the app repo
│  └─ screenshots/*-{light,dark}.png
├─ components/
│  ├─ Landing.astro                 composes the whole landing page
│  ├─ Hero / FeatureGrid / ... one file per section
│  └─ ui/                           Button, Card-ish primitives, Icon, PhoneFrame
├─ i18n/{en,de,utils}.ts            all user-facing copy
├─ integrations/placeholder-check.ts  fails the deploy on unfilled TODOs
├─ layouts/{Base,Legal}.astro
├─ pages/
│  ├─ index.astro  privacy.mdx  imprint.mdx  account-deletion.mdx  404.astro
│  └─ de/index.astro  de/privacy.mdx  de/imprint.mdx  de/account-deletion.mdx
├─ styles/global.css                design tokens
└─ config.ts                        every outbound URL + launch flags

Design tokens

src/styles/global.css is a port, not a design. Every colour, radius and type size is copied from the app's own design system so the site and the app read as one product. If the app's palette changes, change it here to match.

Token group Source of truth in TabMates/app
Light colours core/designsystem/.../theme/Color.kt:5-33
Dark colours core/designsystem/.../theme/Color.kt:35-63
positive/negative core/designsystem/.../theme/Color.kt:65-87 (the ExtendedColors block)
Corner radii core/designsystem/.../theme/Shape.kt:7-14
Type scale core/designsystem/.../theme/Type.kt:10-131
Logo docs/images/logo.svg (cream #FBE9C7 + burnt orange #D2762A)

Two intentional deviations from a pure port, both documented inline in global.css:

  • Font. The app uses FontFamily.Default (Roboto on Android). The site self-hosts Inter Variable, because a system-font stack renders the hero headline differently on every OS. Inter is bundled from npm and served from this domain — never Google Fonts, which would be both a third-party request and a GDPR problem on a German site.
  • Tracking on display sizes. Inter needs slightly tighter letter-spacing than Roboto above 45px. Everything from headline down is a 1:1 conversion.

Editing copy

All user-facing text lives in src/i18n/en.ts and src/i18n/de.ts. No copy is hardcoded in a component.

  1. Add or change the key in en.ts first — it is the source of truth.
  2. Add the same key to de.ts.

de.ts is typed as Strings (i.e. typeof en), so forgetting step 2 is a build error, not a paragraph that silently ships in English. Run npm run check to see it.

German pages currently reuse the English slugs (/privacy/de/privacy). To switch to translated slugs like /de/datenschutz, fill in LOCALIZED_SLUGS in src/i18n/utils.ts and rename the page files — the header language switch and the hreflang tags both already route through that map.

Deployment

Push to main.github/workflows/deploy.yml builds and publishes to GitHub Pages. Pull requests run .github/workflows/ci.yml (format, type-check, build, offline link check).

The deploy build runs with CHECK_PLACEHOLDERS=strict, which fails the build while any TODO: placeholder remains in the output, so a half-finished page can never reach production. Local and PR builds only print a warning. Nothing ships a placeholder today — the guard is there for the next draft that does.

Licence

GPL-3.0-or-later, matching the app. See LICENSE.

Contributors

Languages