- Remove the Selected Projects, Capabilities and Process sections from the
home page (placeholder-heavy content).
- Take the tools marquee out of its card and let it span the full site width
(full-bleed band) instead.
- Wrap #smooth-wrapper in an .app-shell: a fixed, inset, rounded, bordered
panel. Its transform makes it the containing block for the fixed wrapper, so
ScrollSmoother sizes the scroll viewport to the shell (content scrolls inside
it) without fighting ScrollSmoother's inline styles.
- Dock and corner controls stay outside the shell, on a brand-tinted 'desktop'
wallpaper painted on body.
- Reduced-motion path: the shell scrolls its content natively.
A template.tsx is re-created on every navigation, resetting AnimatePresence
so neither enter nor exit ran. Move the transition into a PageTransition
client component rendered in the persistent (site) layout, so AnimatePresence
survives navigations and the old page animates out before the new one in.
Wrap the template in AnimatePresence (mode="wait") with a FrozenRouter that
pins the layout-router context, so the outgoing page animates out (blur +
rise) before the incoming page animates in.
- Add (site)/template.tsx: one framer-motion enter animation (fade + rise +
blur) that runs on every navigation, so moving between dock pages has a
clean transition.
- Disable the staggered .hero-rise entrance now that the template handles it.
- Bring back the corner fan-out controls; drop the in-dock settings tile.
- Regenerate public/dock/*.svg so the squircle fills the whole tile with
no inner margin.
Replace the custom radial corner menu with in-dock control tiles so the
whole bar reads as one macOS dock: logo | pages | settings, each group
divided by a separator. Controls reuse the existing toggle components on
graphite squircle tiles matching the page icons.
- Dock icons are now real SVG files under public/dock/ (macOS squircle
look, active variants), so they can be replaced with custom art later.
- Full-bleed icons (DockIcon padding 0), fixed logo src to stop the
refresh flash.
- Remove the top menu bar entirely; relocate theme/language/sound (+admin)
into a corner control dock that expands on click.
Swap the pill navigation for a macOS-style dock as the primary nav and a
slim top menu bar for utilities:
- components/ui/dock.tsx: Magic UI Dock/DockIcon (magnification via
useSpring/useTransform), ported to the project's framer-motion.
- components/layout/site-dock.tsx: bottom dock with the logo as the first
icon, each item a real next/link (SEO preserved, active state from the
pathname), monochrome squircle tiles, hover tooltips and a "soon" badge
for Products; top menu bar keeps locale/sound/theme/admin + a live clock.
- (site)/layout.tsx: render SiteDock instead of SiteHeader.
Home bento grid and all page content are unchanged.
Add a prepare script that runs 'git config core.hooksPath .githooks' on every
npm install, so the commit-msg style gate and pre-push test gate turn on
automatically per clone with nothing to remember. Guarded with '|| true' so
installs never fail where git is absent (e.g. tarball deploys). Document that
the deploy server never needs it since it only pulls.
Add a commit-msg git hook that rejects any subject not matching
"VERB - Description" (ALL-CAPS verb + " - " + description), letting
merge/revert/fixup commits through. Document the mandatory style and the
no-attribution rule in CLAUDE.md, and note that .githooks is activated per
clone with core.hooksPath. Prevents the prefix-less commits agents kept
producing.
Merge the category and project routes under a single /portfolio/[slug]
segment via resolvePortfolioSlug (category wins over project on a slug
clash). Removes the /portfolio/category/... prefix from links, redirect,
and sitemap. Adds resolver integration tests.
Replace the framer-motion hero entrance with pure-CSS staggered animations so
the hero is painted immediately instead of flashing blank until hydration.
Add a focused brand glow behind the hero title and an animated scroll cue at
the bottom of the home hero. Entrance and cue respect prefers-reduced-motion.
Replace the flat, empty hero background with a pure-CSS layered backdrop:
faded grid, brand glow, drifting brand orbs, grain, and a bottom fade that
blends the hero into page content. Applies to both the home hero and the
compact page heroes via HeroMotionBackdrop; respects prefers-reduced-motion.
Replace the flat two-column layout with a guided 4-step wizard
(Grundlagen -> Inhalte -> Abschnitte -> Medien) using the existing wizard
progress model:
- A top stepper shows each step's number/label and completion (check), and
jumps to any step on click.
- One step is visible at a time in a single comfortable centered column; the
others stay mounted but hidden, so every named field still submits.
- Footer navigation: Zurueck / Save as draft / Weiter, with Save Project on
the final step.
No field-name or save-logic changes. All 375 tests pass; tsc and eslint clean.
Experiment: remove the AppCard wrappers around Basic Information, Localized
Content, Sections and Cover/Assets, plus the action bar, so the form content
sits directly on the page. Section headers now carry a thin underline and the
action bar a top divider to keep structure without card chrome. Two-column
layout preserved. No field-name or save-logic changes.
- Remove the project summary/header card (project name, badges, progress);
it added no value while creating a project. Move the on-submit validation
alert down to the action bar.
- Lay the whole form out in two columns: Basic Information + Localized
Content, then Sections + Cover/Assets. Basic Information fields cap at two
columns and the Cover/Assets card stacks inside its column.
All 375 tests pass; tsc and eslint clean.
Fix the deeply nested cards in the project form (screenshot: Cover Media >
Cover > preview card, with duplicate labels):
- MediaFieldPicker no longer wraps itself in AppCards. It renders one flat
bordered box laid out in two columns (preview | controls), dropping two
nested card layers and the duplicate title.
- Cover Media and Assets now sit side by side in a two-column grid instead
of stacked with a separator.
All 375 tests pass; tsc and eslint clean.
Reorganize the project form for a lighter, more professional flow without
touching field names or the save action (all data preserved):
- LocaleInputs: drop the per-locale card wrappers for a tight 3-column
labelled grid; shorter textareas.
- Sections and Assets: collapse each item into an accordion (closed by
default) and show a proper empty state when there are none.
- Slim the header to badges + title + a compact progress indicator instead
of a stats grid; drop the assets stats sidebar.
- Tighten section paddings/spacing (lg -> md) throughout.
All 375 tests pass; tsc and eslint clean.
Replace the card grid with a compact data table (cover, project, category,
year, status, layout, actions) and a proper empty state that adapts to an
active category filter. Actions expose a public-view link plus the existing
edit/delete menu. No data-layer or save changes.
The double-layer AppCard look showcased in the UI Kit was only applied on
the public frontend; every admin surface was pinned to layer=single and
stayed flat. Convert the admin section/container cards to the default
layered look, keeping compact metric tiles, toolbars, image tiles and
nested leaf cards single.
Add AppCard contentClassName so content utilities (space-y-*, grid, flex)
keep applying to the inner shell after the switch to double layer.
- Add a Save as draft button that bypasses the completeness gate: the user
can save partial work and finish later
- projectDraftInputSchema makes the user-facing copy (title, summary, service
label, client) optional; the action auto-generates a slug from the title
(or draft-<timestamp>), defaults the year to the current year, and forces
the project unpublished
- Drafts drop not-yet-valid sections/assets instead of failing the save
- Pass intent via a hidden field set on click so the server reliably sees it
- Tests: draft schema accepts empty copy a strict save rejects, and still
requires a slug and a valid year
- Remove the tab navigation, per-step sidebar, and Previous/Next buttons;
render Basics, Localized Content, Sections and Assets stacked on a single
scrollable page
- Drop the now-unused wizard step machinery (currentStep state, wizardSteps,
StepStateBadge, step stat card) and related imports
- Keep the same fields, validation, and save gating (Basics + Localized
Content required; sections/assets optional)
- CASE_STUDY -> Web: two columns, stacked full-width screenshots with a
browser frame plus a sticky project info panel
- GRID -> Print: mixed-size gallery grid for logos/posters/etc.
- STORY -> Editorial: full-bleed hero with title overlay, then alternating
text/media sections
- Add a prominent title/summary intro (was missing from the header)
- Use PortfolioCover for all media so empty projects show the branded
placeholder instead of broken images; gallery sections render even
before an image is uploaded
- drizzle-kit does not read .env like the Next.js app, so DATABASE_URL was
undefined and fell back to the default host, causing migrate to hang and
push to fail against the wrong database
- Load .env via native process.loadEnvFile for local dev, guarded so
production (env already set, no .env file) is unaffected
- Fix critical bug: TabsContent unmounted inactive panels, so the project
form only submitted the active tab's fields and could never save; add an
opt-in forceMount that keeps panels mounted (hidden) and use it on all
four project-form tabs
- Make Sections and Assets optional: a project saves with just Basics and
Localized Content; new projects start with no sections/assets, and the
last one can now be removed
- Update wizard progress so empty sections/assets steps count as complete
- Update save hint copy and step labels to reflect the optional steps
- Correct .claude/launch.json dev port to 3014
- Update portfolio-form-progress tests for the optional-steps behaviour
- Replace stale Prisma commands/paths in CLAUDE.md with Drizzle (db:generate/migrate/push/studio, lib/db/index.ts, lib/db/schema.ts)
- Fix Docker/Makefile command block to match actual make targets
- Correct middleware.ts references to proxy.ts (Next.js 16 entry point)
- Rename ' AGENTS.md' (leading space) to AGENTS.md so agent tooling can find it
- Remove stray characters from the AGENTS.md documentation-updates list
- Drop badge, kicker, status, primaryCta, secondaryCta, countdownLabel from all locales
- These were orphaned when the coming-soon page was trimmed to title + countdown
- Remove CTA buttons (site is closed, no navigation)
- Drop the card wrapper: content sits on the page background, gradient included
- Remove the launch label; keep the countdown
- Fit the viewport (no scroll)
- postgres.js forwarded schema as a startup param; Postgres rejected the connection
- Remove ?schema=public from docker-compose, CI, and the client default
- Strip any query string in lib/db/index.ts so this cannot recur
- Join the app to the external proxy network and drop the published host port
- Add Traefik labels for mohfarawati.de, www, and root.mohfarawati.de
- Parametrize network/entrypoint/certresolver via TRAEFIK_* env with sane defaults
- Pass ADMIN_HOST to the app and document production env in .env.example