EV Kitadoll EV Kitadoll
Two kindergartens. One site. Both feel like home.Zwei Kindergärten. Eine Website. Beide fühlen sich wie Zuhause an.
Website for the evangelical Kita-Verbund evkita doll in Wildeshausen — covering two kindergartens (Schatzinsel and Sternschnuppe) under a single parent-focused site. Next.js 15, Docker multi-stage build, Coolify deployment on Hetzner. Website für den Kita-Verbund evkita doll in Wildeshausen — zwei Kindergärten (Schatzinsel und Sternschnuppe) unter einer elternorientierten Website. Next.js 15, Docker Multi-Stage-Build, Coolify auf Hetzner.
// challenge // ausgangslage
Two kindergartens — Schatzinsel (since 1949) and Sternschnuppe — share a managing association but have distinct identities, staff, locations, and enrollment details. Parents need to find contact and opening hours in seconds. The site needed to honor both Kitas equally, never making one feel secondary to the other, while keeping navigation simple enough for every age group. Zwei Kindergärten — Schatzinsel (seit 1949) und Sternschnuppe — teilen einen Träger, haben aber eigene Identitäten, Leitungen, Adressen und Anmeldedaten. Eltern müssen Kontakt und Öffnungszeiten in Sekunden finden. Die Website sollte beide Kitas gleichwertig würdigen.
// approach // vorgehen
The split-screen hero puts both Kitas side by side from the first pixel — no hierarchy, no primary/secondary. Each side has its own identity card with animated illustration (treasure map for Schatzinsel, animated starfield for Sternschnuppe). The starfield uses seeded pseudo-random to generate consistent star positions across SSR and client render — eliminating the hydration mismatch that would occur with Math.random(). Docker multi-stage build produces a ~200MB standalone image; Coolify on Hetzner deploys it with a single push.
Der Split-Screen-Hero stellt beide Kitas nebeneinander — keine Hierarchie, kein Primär/Sekundär. Jede Seite hat eine eigene Identitätskarte mit animierter Illustration. Die Sternfeldgenerierung nutzt seeded Pseudo-Random für konsistente Positionen über SSR und Client-Render — ohne Hydration-Mismatch. Docker Multi-Stage erzeugt ein ~200MB Standalone-Image.
// code // code
Seeded pseudo-random star positions — no hydration mismatch Seeded Pseudo-Random Sternpositionen — kein Hydration-Mismatch
typescript// src/components/HeroSection.tsx
// Math.random() would differ between SSR and client → hydration error.
// Seeded deterministic function produces identical output on both sides.
function seeded(seed: number): number {
const x = Math.sin(seed + 1) * 10000;
return x - Math.floor(x);
}
function quantize(value: number, digits = 4): number {
return Number(value.toFixed(digits));
}
// Generated once at module level — same on server and client
const STARS = Array.from({ length: 70 }, (_, i) => ({
id: i,
x: quantize(seeded(i * 2.731) * 100),
y: quantize(seeded(i * 4.173) * 100),
size: quantize(seeded(i * 5.839) * 2.5 + 0.8),
delay: quantize(seeded(i * 7.412) * 5),
duration: quantize(seeded(i * 11.317) * 2.5 + 1.8),
})); Each star's position, size, and animation timing are deterministic — seeded by index. SSR renders exactly what the client hydrates. No flash, no layout shift. Position, Größe und Animationstiming jedes Sterns sind deterministisch — geseedet durch den Index. SSR rendert exakt das, was der Client hydriert. Kein Flash, kein Layout Shift.
Docker multi-stage build — ~200MB production image Docker Multi-Stage-Build — ~200MB Produktions-Image
docker# Dockerfile — three-stage build
FROM node:22-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
FROM node:22-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build # output: standalone
FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public
EXPOSE 3000
CMD ["node", "server.js"] Only the standalone output and static assets land in the final image. No build tools, no devDependencies, no source code. Deploy to Coolify with a single git push. Nur der Standalone-Output und statische Assets landen im finalen Image. Keine Build-Tools, keine DevDependencies, kein Quellcode. Deploy mit einem git push über Coolify.
// outcome // ergebnis
Single-page website covering both Kitas: animated split-screen hero, philosophy section (6 evangelical values), per-Kita detail cards with groups/spots/opening hours, enrollment FAQ, contact sections for both locations, and Docker deployment on Hetzner via Coolify. Einseitige Website für beide Kitas: animierter Split-Screen-Hero, Philosophiebereich (6 Werte), Detailkarten mit Gruppen/Plätzen/Öffnungszeiten, Anmelde-FAQ, Kontaktbereiche beider Standorte, Docker-Deployment auf Hetzner via Coolify.
// brand // marke
Audience
Zielgruppe
Parents of children aged 1–6 in Wildeshausen. They are looking for trust signals — warmth, stability, values — before they even think about logistics. They need enrollment info, but they need to feel good first.
Eltern von Kindern im Alter von 1–6 Jahren in Wildeshausen. Sie suchen Vertrauenssignale — Wärme, Stabilität, Werte — bevor sie überhaupt an Logistik denken. Sie brauchen Anmeldeinformationen, aber zuerst ein gutes Gefühl.
Positioning
Positionierung
Two kindergartens, one mission. The site never makes one Kita feel like an afterthought. Both identities are honored equally — different names, same values, same care.
Zwei Kindergärten, eine Mission. Die Website lässt keine Kita wie ein Nachgedanke wirken. Beide Identitäten werden gleich gewürdigt — verschiedene Namen, gleiche Werte, gleiche Fürsorge.
Tone of Voice
Tonalität
Warm, welcoming, and gently faith-rooted without being exclusionary. Speaks to the parent who is a little nervous about this decision. Every word earns trust before asking for an enrollment form.
Warm, einladend und sanft glaubensverwurzelt ohne ausgrenzend zu sein. Spricht Eltern an, die bei dieser Entscheidung etwas nervös sind. Jedes Wort verdient Vertrauen, bevor es um ein Anmeldeformular geht.
Visual Direction
Visual Direction
Warm off-white background (#F8F3E8). Nunito font — round, approachable, child-friendly without being childish. Soft pastel accent cards for values and groups. Playful animated illustrations (treasure map, starfield) that reference each Kita's name.
Warmer Off-White-Hintergrund (#F8F3E8). Nunito-Schrift — rund, zugänglich, kinderfreundlich ohne kindisch zu sein. Sanfte Pastell-Akzentkarten. Verspielt animierte Illustrationen (Schatzkarte, Sternfeld), die auf den Namen der Kitas verweisen.
// stack
- Next.js 15
- TypeScript
- Tailwind CSS
- Framer Motion
- Docker
- Coolify