mAi 2593122337 style: CSS foundation for minimalist UI redesign
Adds the spacing scale, status-pill tokens, and a set of new utility classes
that the per-screen commits will use:

- spacing scale: --space-1 through --space-9 (single source of truth for
  vertical rhythm; replaces ad-hoc rem values throughout the .svelte files)
- status pill tokens: --color-status-{open,closed}-{bg,fg} (dark-mode aware,
  closed pulls from the same warning palette as .fb-banner--closed)
- .fb-shell.fb-page-narrow + .fb-page-center for vertical-centred narrow
  shells (landing + login)
- .fb-back-link — quiet text-only back-link, replaces the chip-style button
- .fb-inline-error — quieter alternative to .fb-banner--error
- .fb-toggle / .fb-toggle__{text,label,hint} — label-left + checkbox-right
  boolean fields (no UI library)
- .fb-status-pill / .fb-status-pill__dot / --open / --closed — clickable
  pill that toggles status
- .fb-menu / .fb-menu__{btn,panel,item,divider,item--danger} — native
  <details>/<summary>-based ⋯ menu, no JS framework needed
- .fb-card / .fb-card__{head,title,actions,meta} + .fb-card-grid — minimalist
  card on the gradient page bg, no border + shadow stack, generous padding
- .fb-empty — generous empty state
- .fb-share-strip / __url / __placeholder / __replace — inline header strip
  for the detail page, replaces the standalone Share section
- .fb-closed-line — neutral muted closed-state line for /f/[slug]
- .fb-segment / __btn / __btn--active — small segmented control matching
  .fb-tabs (for inline Visual/JSON toggle on Edit tab)
- .fb-detail-head / __title / __actions, .fb-tab-body, .fb-version-note,
  .fb-save-row — detail-page header + tab-body layout primitives

Also normalises:

- .fb-section margin-bottom 1.75rem → var(--space-7) (≈ 2.5rem)
- focus-ring opacity 0.15 / 0.25 → 0.2 across .fb-input + .fb-btn for a
  single consistent focus treatment

No structural .svelte changes here — only CSS additions and three numeric
edits. Existing pages continue to render exactly as before; the per-screen
commits that follow consume these classes.
2026-05-06 12:25:29 +02:00
2026-05-05 11:38:11 +02:00

fdbck.msbls.de

Per-link feedback forms and live-chat masks. Anonymous, slug-gated, no auth required for participants.

Spun out from m/flexsiebels.de issue #63 — full design at docs/plans/feedback-feature.md.

Stack

SvelteKit 5 + Svelte 5 + bun + @sveltejs/adapter-node. Postgres + Supabase auth. Schema: fdbck.feedback_{instances,submissions,posts} on supa.flexsiebels.de (msupabase).

Run locally

cp .env.example .env  # fill SUPABASE_*
bun install
bun run dev

Test + check

bun run test    # rate-limit + public-scope unit tests
bun run check   # svelte-check (type errors / a11y)
bun run build   # adapter-node production build → ./build

Deploy

Dockerfile uses oven/bun:latest. Dokploy app: fdbck.msbls.de. DNS via Hostinger (handled out of band).

Structure

src/
  hooks.server.ts        — auth + public-scope policy gate
  lib/server/
    auth.ts              — cookie JWT + Supabase refresh
    fdb.ts               — Postgres `fdbck` schema accessor
    feedback.ts          — slug generator + DB helpers + rate-limit constants
    public-scope.ts      — anonymous-DB-access fail-closed gate
    rate-limit.ts        — in-memory token bucket
    schemas.ts           — Zod request validation
    supabase.ts          — admin + anon client singletons
  routes/
    +page.svelte         — landing
    f/[slug]/            — public participant page (form + live chat)
    admin/feedback/      — m's admin (list + detail + create)
    api/
      auth/              — sign-in / sign-out
      public/feedback/   — anonymous slug-gated endpoints
      admin/feedback/    — owner-scoped admin endpoints

Data model (canonical: design doc §5)

  • fdbck.feedback_instances — slug, title, description, owner_user_id, form_definition (jsonb), chat_enabled, status (open | closed), closed_at
  • fdbck.feedback_submissions — instance_id, display_name (nullable = anonymous), client_session_id, answers (jsonb), client_ip, user_agent
  • fdbck.feedback_posts — instance_id, display_name, client_session_id, body, hidden (m soft-moderate), client_ip, user_agent

Anti-abuse layers

  • 32-char base62 slugs (~190 bits entropy)
  • in-memory rate-limit (30 posts / 5 min, 10 submits / 5 min, per IP+slug)
  • honeypot field on forms + chat (silently dropped)
  • body length caps + closing kill-switch
  • noindex meta + robots.txt Disallow: /

Out of scope (v1)

Drag-drop form-builder · post reactions · realtime/SSE · CAPTCHA · trusted-tier owner sharing · branding/theming · auto-notifications. All have a clean upgrade path on the existing schema.

Issue origin

m/flexsiebels.de#63 — m PWA-voice 2026-05-05: "Im Wesentlichen quasi Microsoft Forms und Teams-Feedback in einem auf einer Webseite."

Description
fdbck.msbls.de — standalone anonymous feedback (forms + live chat) per-link app
Readme 344 KiB
Languages
TypeScript 48%
Svelte 37.9%
CSS 13.5%
HTML 0.3%
Dockerfile 0.2%