# United Tattoo — Official Website (Next.js + ShadCN UI) Hi, I’m Nicholai. I built this site for my friend Christy (aka Ink Mama) and the United Tattoo crew in Fountain, CO. The goal was simple: give the studio a site that actually reflects the art, the people, and the experience — not the stiff, generic stuff you usually see. This is also a thank you for everything Christy has done for Amari (my girlfriend and soulmate), who was her apprentice. So yeah, this is personal — and it shows. This repo powers the official United Tattoo website, built with: - Next.js App Router - TypeScript - Tailwind CSS - ShadCN UI components (used across all pages) - Lenis (smooth scroll) - Lucide (icons) Live dev server: http://localhost:3000 ## Project Structure - app/ - page.tsx — homepage (Hero, Artists, Services, Contact sections) - aftercare/page.tsx — aftercare instructions (ShadCN-driven) - deposit/page.tsx — deposit policy + payment options (Afterpay, Stripe) - terms/page.tsx — terms of service - privacy/page.tsx — privacy policy - artists/ — artists listing + dynamic routes for profiles (coming from data) - book/page.tsx — booking flow - specials/page.tsx — promotions (monthly specials, VIP list) - contact/page.tsx — contact - gift-cards/page.tsx — gift card info - components/ - hero-section.tsx, artists-section.tsx, services-section.tsx, contact-section.tsx - aftercare-page.tsx, deposit-page.tsx, terms-page.tsx, privacy-page.tsx - booking-form.tsx — multi-step form using ShadCN components - footer.tsx — contains direct links to Aftercare, Deposit Policy, Terms, and Privacy - ui/ — ShadCN UI primitives - data/ - artists.ts — single source of truth for artist metadata and images used across pages - public/ - united-logo-*.png/jpg, artists/, and other stable assets ## Content & Assets - All the “real” content, bios, and images are now wired in (not seed placeholders). - Artist portraits and tattoo samples live under public/artists/. - Pages like Aftercare, Deposit, Terms, and Privacy use consistent styling patterned after the homepage and portfolio pages — powered by ShadCN components. If you need to re-copy images from the temp folder into public (on your machine), there’s a helper script: - ./copy-artist-images.sh Note: This script expects the temp directory structure to exist locally; it silently skips if a source is missing. ## Getting Started (Local Dev) - Install deps: - npm install - Run dev server: - npm run dev - Open http://localhost:3000 - Lint (optional): - npm run lint Build: - npm run build - npm start ## Continuous Integration (CI) This repo includes a CI workflow that enforces linting, type safety, unit tests, build/preview, and bundle size budgets. - Workflow file: `.gitea/workflows/ci.yaml` - Triggers: Push and PR against `main`/`master` - Node: 20.x with `npm ci` Stages - Lint: `npm run ci:lint` (ESLint) - Typecheck: `npm run ci:typecheck` (TypeScript noEmit) - Unit tests: `npm run ci:test` (Vitest with coverage) - Build: `npm run ci:build` (OpenNext build to `.vercel/output/static`) - Preview smoke: start OpenNext preview briefly to ensure no immediate crash - Budgets: `npm run ci:budgets` (analyzes `.vercel/output/static`) Bundle Size Budgets - Defaults are defined in `package.json` under the `budgets` key: - `TOTAL_STATIC_MAX_BYTES`: 3,000,000 (≈3 MB) - `MAX_ASSET_BYTES`: 1,500,000 (≈1.5 MB) - Override via environment variables in CI: - `TOTAL_STATIC_MAX_BYTES` - `MAX_ASSET_BYTES` Artifacts - A budgets report is written to `.vercel/output/static-budgets-report.txt` and uploaded as a CI artifact. Migration Dry-Run (D1) - The workflow attempts a best‑effort local dry‑run: `wrangler d1 execute united-tattoo --local --file=./sql/schema.sql`. - If local bindings are unavailable in CI, the step is skipped with a note; wire it up later when CI bindings are configured. Rollback Strategy - This story does not deploy. To disable CI temporarily, remove or rename the workflow file or adjust failing stages. For full rollback strategy see `docs/prd/rollback-strategy.md`. ## Docker This repo is docker-ready. We build a standalone Next.js app for a smaller runtime image. Build image: - docker build -t united-tattoo:latest . Run container (port 3000): - docker run --rm -p 3000:3000 -e PORT=3000 united-tattoo:latest - Open http://localhost:3000 Notes: - next.config.mjs sets output: "standalone" - The Dockerfile copies .next/standalone + .next/static and runs the server with HOSTNAME=0.0.0.0 ## Pages Overview - Home — Bold, high-contrast, split imagery, parallax accents. This sets the identity. - Artists — Grid and profile surfaces wired to data/artists.ts. Each artist shows image, specialties, and sample work. - Aftercare — Two flows: General Aftercare and Transparent Bandage Aftercare (accurate, readable, ShadCN cards + alerts). - Deposit — Clear policy, payment options, and compliance notes (LW2 Investments, LLC oversight). - Terms & Privacy — Straightforward, legally sound, human-readable. Both accessible from the footer. - Booking — Multi-step form with ShadCN components and validation-friendly structure. - Specials — Marketing surface for time-bound promotions and membership-like advantages. ## Design Language - ShadCN components everywhere possible - Monochrome foundation with high contrast and cinematic image splits - Type scales + spacing match the homepage/portfolio feeling - Lucide icons for affordances ## Tech Notes - TypeScript errors are ignored during build in CI to allow non-blocking content/design iteration (next.config.mjs). - Images are unoptimized (no Next image loader), served statically; change if you plan to put this behind a CDN with transforms. - Smooth scroll and parallax-style offsets are kept subtle to let the work shine. ## Deployment - Standard Next.js deploys work (Vercel, Node server, Docker) - For self-hosting or VPS, use the Dockerfile in the repo - The site runs on port 3000 by default ## Why This Exists Because Christy deserved a proper site — and because the previous one was, bluntly, not it. United Tattoo is more than a shop. It’s a community with real people and real art. This site tries to honor that. — Nicholai