πŸš€ DEPLOYMENT COMMAND

npm run pages:build && wrangler deploy
[![Contributors][contributors-shield]][contributors-url] [![Forks][forks-shield]][forks-url] [![Stargazers][stars-shield]][stars-url] [![Issues][issues-shield]][issues-url] [![LinkedIn][linkedin-shield]][linkedin-url]
United Tattoo Logo

United Tattoo

Professional tattoo studio platform built on Cloudflare's edge network
⚑ Lightning-fast β€’ 🎨 Artist-first β€’ πŸ“… Calendar-integrated

🌐 View Live Site »

Quick Start Β· πŸ› Report Bug Β· ✨ Request Feature

---

πŸ“‘ Table of Contents

  1. 🎯 About The Project
  2. πŸ› οΈ Tech Stack
  3. πŸ—οΈ Architecture
  4. πŸš€ Getting Started
  5. πŸ’» Development
  6. 🌍 Deployment
  7. πŸ“š Documentation
  8. πŸ—ΊοΈ Roadmap
  9. 🀝 Contributing
  10. πŸ“„ License
  11. πŸ“¬ Contact
---
## 🎯 About The Project
United Tattoo Studio

**United Tattoo** is a comprehensive tattoo studio management platform designed for [United Tattoo](https://united-tattoos.com), a professional tattoo studio in **Fountain, Colorado**. This platform seamlessly integrates artist portfolios, appointment booking, flash tattoo marketplace, and real-time calendar synchronizationβ€”all running on Cloudflare's global edge network for exceptional performance. ### ✨ Key Features
#### 🎨 **Artist Management** - Dynamic portfolio galleries with Instagram integration - SEO-friendly artist pages (`/artists/artist-name`) - Specialty tracking and hourly rate management - Active/inactive status control - Self-service artist dashboard #### ⚑ **Flash Tattoo Marketplace** - Pre-drawn designs available for instant booking - Responsive carousel UI with smooth scrolling - Pricing and availability management - Direct integration with booking system #### πŸ“… **Smart Booking System** - Client appointment scheduling - Multiple status workflows (PENDING β†’ CONFIRMED β†’ IN_PROGRESS β†’ COMPLETED) - Deposit and payment tracking - Real-time conflict detection #### πŸ”„ **CalDAV/Nextcloud Integration** - **Bidirectional calendar sync** with Nextcloud - Real-time availability checking - Per-artist calendar configuration - Sync logging and monitoring - Automatic conflict prevention #### πŸ” **Nextcloud OAuth Authentication** - Auto-provisioning based on Nextcloud groups - Role-based access control (SUPER_ADMIN, SHOP_ADMIN, ARTIST, CLIENT) - Seamless integration with existing artist portal - Emergency admin credentials fallback #### πŸ“Š **Comprehensive Dashboards** - **Admin Dashboard**: Analytics, portfolio management, calendar oversight, artist management - **Artist Dashboard**: Profile editing, portfolio management, appointment view - File upload management with R2 cloud storage
### πŸ’‘ Why United Tattoo?
**🌍 Edge-First Architecture** Built on Cloudflare Workers for global performance with <100ms response times worldwide. **πŸ”— Nextcloud-First Integration** Seamless authentication and calendar sync with existing artist infrastructureβ€”no duplicate account management. **⚑ Zero-ORM Overhead** Direct Cloudflare D1 integration via bindings for maximum performance. **πŸ“¦ Bundle Size Enforced** CI/CD enforces 3MB static budget to ensure lightning-fast page loads. **πŸ§ͺ Test Coverage** Comprehensive Vitest test suite with coverage tracking.

(back to top)

--- ## πŸ› οΈ Tech Stack
### Core Framework [![Next.js][nextjs-badge]][next-url] [![React][react-badge]][react-url] [![TypeScript][typescript-badge]][typescript-url] ### Cloudflare Infrastructure [![Cloudflare Workers][cloudflare-badge]][cloudflare-url] [![OpenNext][opennext-badge]][opennext-url] ### UI & Styling [![ShadCN UI][shadcn-badge]][shadcn-url] [![Tailwind CSS][tailwind-badge]][tailwind-url] [![Framer Motion][framer-badge]][framer-url] ### Database & Storage [![Cloudflare D1][d1-badge]][d1-url] [![Cloudflare R2][r2-badge]][r2-url] ### Authentication & Integration [![NextAuth.js][nextauth-badge]][nextauth-url] [![CalDAV][caldav-badge]][caldav-url] ### Testing & Quality [![Vitest][vitest-badge]][vitest-url] [![ESLint][eslint-badge]][eslint-url] [![Prettier][prettier-badge]][prettier-url]
πŸ“¦ Complete Dependency List **Core Dependencies:** - Next.js 14.2.33 (App Router) - React 18 - TypeScript 5 - OpenNext for Cloudflare 1.8.2 **UI Components:** - 30+ Radix UI components (via ShadCN) - Framer Motion 12.23.24 (animations) - Lenis (smooth scrolling) - next-themes 0.4.6 (dark mode) **Data & State:** - TanStack React Query 5.89.0 - Zod 3.25.67 (validation) - React Hook Form 7.60.0 **Calendar & CalDAV:** - tsdav 2.1.5 (CalDAV client) - react-big-calendar 1.19.4 - ical.js 1.5.0 - date-fns **File Processing:** - Sharp 0.34.4 (image processing) - heic-convert 2.1.0 (HEIC β†’ JPEG) - AWS SDK for S3 3.890.0 (R2 compatible) **Testing:** - Vitest 3.2.4 - React Testing Library 16.3.0 - @vitest/coverage-v8

(back to top)

--- ## πŸ—οΈ Architecture
```mermaid graph TB subgraph "Client Layer" Browser[🌐 Browser] end subgraph "Edge Layer - Cloudflare Workers" NextJS[Next.js 14
App Router] OpenNext[OpenNext
Adapter] end subgraph "Cloudflare Services" D1[(D1 Database
SQLite)] R2[R2 Storage
Files & Images] end subgraph "External Services" Nextcloud[Nextcloud
OAuth + CalDAV] end Browser --> NextJS NextJS --> OpenNext OpenNext --> D1 OpenNext --> R2 OpenNext <--> Nextcloud style Browser fill:#667eea,color:#fff style NextJS fill:#000,color:#fff style OpenNext fill:#f38020,color:#fff style D1 fill:#f38020,color:#fff style R2 fill:#f38020,color:#fff style Nextcloud fill:#0082c9,color:#fff ```
### πŸ”„ System Flow
Authentication Flow ``` User Request β†’ NextAuth.js ↓ β”œβ”€ Nextcloud OAuth (Primary) β”‚ β”œβ”€ Check user groups (via OCS API) β”‚ β”œβ”€ Assign role based on group β”‚ β”‚ β”œβ”€ "admins" β†’ SUPER_ADMIN β”‚ β”‚ β”œβ”€ "shop_admins" β†’ SHOP_ADMIN β”‚ β”‚ β”œβ”€ "artists" β†’ ARTIST (auto-create profile) β”‚ β”‚ └─ Other β†’ Deny access β”‚ └─ Create/update user in D1 β”‚ β”œβ”€ Credentials (Fallback - Admin Only) β”‚ β”œβ”€ Query parameter: ?admin=true β”‚ β”œβ”€ Email/password validation β”‚ └─ Dev mode: Auto-create SUPER_ADMIN β”‚ └─ Session Created (JWT) ```
CalDAV Sync Flow ``` Appointment Created/Updated ↓ syncAppointmentToCalendar() ↓ β”œβ”€ Get artist's Nextcloud calendar config β”œβ”€ Connect to CalDAV server β”œβ”€ Create/update VEVENT β”œβ”€ Store calendar_event_uid in D1 └─ Log sync operation Background Sync (Periodic) ↓ pullCalendarEventsToDatabase() ↓ β”œβ”€ Fetch events from CalDAV β”œβ”€ Compare with D1 appointments β”œβ”€ Update changed appointments β”œβ”€ Import external events └─ Log sync results ```
Database Schema **Core Tables:** | Table | Description | Key Fields | |-------|-------------|------------| | `users` | Authentication & profiles | id, email, name, role, nextcloud_user_id | | `artists` | Artist profiles | id, user_id, slug, bio, specialties (JSON), hourly_rate | | `portfolio_images` | Artist work gallery | id, artist_id, image_url, tags (JSON), order, is_public | | `flash_items` | Pre-drawn designs | id, artist_id, title, price, is_available | | `appointments` | Booking system | id, artist_id, client_id, status, start_time, end_time, deposit | | `availability` | Artist schedules | id, artist_id, day_of_week, start_time, end_time | | `artist_calendars` | CalDAV configuration | id, artist_id, calendar_url, username, password | | `calendar_sync_logs` | Sync monitoring | id, artist_id, operation, status, details | | `site_settings` | Global config | key, value, type | | `file_uploads` | R2 file tracking | id, user_id, file_url, file_size, mime_type | **Indexes:** Optimized for artist lookups, appointment queries, and calendar sync operations.
### πŸ“ Project Structure ``` united-tattoo/ β”œβ”€β”€ app/ # Next.js App Router β”‚ β”œβ”€β”€ (public)/ # Public pages (no auth) β”‚ β”‚ β”œβ”€β”€ artists/ # Artist profiles & portfolios β”‚ β”‚ β”œβ”€β”€ book/ # Booking pages β”‚ β”‚ └── page.tsx # Homepage β”‚ β”œβ”€β”€ admin/ # Admin dashboard (SUPER_ADMIN, SHOP_ADMIN) β”‚ β”œβ”€β”€ artist-dashboard/ # Artist self-service (ARTIST) β”‚ β”œβ”€β”€ api/ # API routes β”‚ β”‚ β”œβ”€β”€ artists/ # Artist CRUD β”‚ β”‚ β”œβ”€β”€ appointments/ # Booking endpoints β”‚ β”‚ β”œβ”€β”€ caldav/ # Calendar sync β”‚ β”‚ β”œβ”€β”€ flash/ # Flash items β”‚ β”‚ └── upload/ # R2 file uploads β”‚ └── auth/ # NextAuth pages β”œβ”€β”€ lib/ # Core logic β”‚ β”œβ”€β”€ db.ts # D1 database functions β”‚ β”œβ”€β”€ auth.ts # NextAuth config + helpers β”‚ β”œβ”€β”€ caldav-client.ts # CalDAV integration β”‚ β”œβ”€β”€ calendar-sync.ts # Sync logic β”‚ β”œβ”€β”€ nextcloud-client.ts # Nextcloud API client β”‚ β”œβ”€β”€ r2-upload.ts # R2 file handling β”‚ └── env.ts # Environment validation β”œβ”€β”€ components/ # React components β”‚ β”œβ”€β”€ ui/ # ShadCN components β”‚ └── ... # Feature components β”œβ”€β”€ sql/ # Database β”‚ β”œβ”€β”€ schema.sql # Main schema β”‚ └── migrations/ # Migration files β”œβ”€β”€ docs/ # Documentation β”œβ”€β”€ .gitea/workflows/ # CI/CD pipelines └── wrangler.toml # Cloudflare config ```

(back to top)

--- ## πŸš€ Getting Started ### πŸ“‹ Prerequisites
⚠️ Required Accounts & Access Before starting, ensure you have: - βœ… **Cloudflare Account** with access to Workers, D1, R2, and Pages - βœ… **Nextcloud Instance** with admin access for OAuth app creation - βœ… **Node.js 18+** and npm installed - βœ… **Wrangler CLI** version 3+
**Install Wrangler:** ```bash npm install -g wrangler ``` **Cloudflare Resources Required:** - **Workers & Pages**: For hosting the application - **D1 Database**: SQLite database (named `united-tattoo`) - **R2 Buckets**: File storage (`united-tattoo`, `united-tattoo-inc-cache`) ### βš™οΈ Installation 1. **Clone the repository** ```bash git clone https://git.biohazardvfx.com/nicholai/united-tattoo.git cd united-tattoo ``` 2. **Install dependencies** ```bash npm install ``` 3. **Configure environment variables** ```bash cp .env.example .env.local # Edit .env.local with your credentials (see Environment Variables section) ``` 4. **Set up Cloudflare D1 database** ```bash # Create D1 database (if not exists) wrangler d1 create united-tattoo # Apply schema to local D1 npm run db:migrate:local # Apply schema to preview/production npm run db:migrate:latest:preview ``` 5. **Configure Nextcloud OAuth** See [`docs/NEXTCLOUD-OAUTH-SETUP.md`](docs/NEXTCLOUD-OAUTH-SETUP.md) for detailed instructions on: - Creating OAuth application in Nextcloud - Configuring group-based role assignment - Setting up service account for CalDAV 6. **Run locally** ```bash # Next.js dev server (port 3000) npm run dev # OR with Cloudflare Workers simulation npm run dev:wrangler ``` 7. **Access the application** - Local: `http://localhost:3000` - Sign in: `http://localhost:3000/auth/signin` - Admin signin: `http://localhost:3000/auth/signin?admin=true`

(back to top)

### πŸ” Environment Variables
πŸ“ Required Variables | Variable | Description | Example | |----------|-------------|---------| | **Database** | | | | `DATABASE_URL` | PostgreSQL URL (legacy, using D1 via bindings) | `postgresql://...` | | `DIRECT_URL` | Direct database connection (optional) | `postgresql://...` | | **Authentication** | | | | `NEXTAUTH_URL` | Application URL | `https://united-tattoos.com` | | `NEXTAUTH_SECRET` | NextAuth secret key | Generate with `openssl rand -base64 32` | | **File Storage (Cloudflare R2)** | | | | `AWS_ACCESS_KEY_ID` | R2 access key ID | From Cloudflare dashboard | | `AWS_SECRET_ACCESS_KEY` | R2 secret access key | From Cloudflare dashboard | | `AWS_REGION` | Region (any valid AWS region) | `us-east-1` | | `AWS_BUCKET_NAME` | R2 bucket name | `united-tattoo` | | `AWS_ENDPOINT_URL` | R2 endpoint URL | `https://.r2.cloudflarestorage.com` | | **Nextcloud OAuth** | | | | `NEXTCLOUD_BASE_URL` | Nextcloud instance URL | `https://portal.united-tattoos.com` | | `NEXTCLOUD_OAUTH_CLIENT_ID` | OAuth app client ID | From Nextcloud admin | | `NEXTCLOUD_OAUTH_CLIENT_SECRET` | OAuth app client secret | From Nextcloud admin | | `NEXTCLOUD_ARTISTS_GROUP` | Group name for artists | `artists` | | `NEXTCLOUD_ADMINS_GROUP` | Group name for shop admins | `shop_admins` |
πŸ”§ Optional Variables | Variable | Description | Default | |----------|-------------|---------| | **CalDAV (Calendar Sync)** | | | | `NEXTCLOUD_USERNAME` | Service account username | β€” | | `NEXTCLOUD_PASSWORD` | Service account password/app password | β€” | | `NEXTCLOUD_CALENDAR_BASE_PATH` | CalDAV base path | `/remote.php/dav/calendars` | | **OAuth Providers (Deprecated)** | | | | `GOOGLE_CLIENT_ID` | Google OAuth client ID | β€” | | `GOOGLE_CLIENT_SECRET` | Google OAuth client secret | β€” | | `GITHUB_CLIENT_ID` | GitHub OAuth client ID | β€” | | `GITHUB_CLIENT_SECRET` | GitHub OAuth client secret | β€” | | **Migration** | | | | `MIGRATE_TOKEN` | Token for public migration endpoint | Generate random string | | **Analytics** | | | | `VERCEL_ANALYTICS_ID` | Vercel Analytics ID | β€” |
πŸ’‘ Pro Tip: Use .env.local for local development and configure production variables in Cloudflare dashboard under Settings β†’ Environment Variables.

(back to top)

--- ## πŸ’» Development ### ⌨️ Common Commands
Command Description
πŸ”§ Development
npm run dev Start Next.js dev server (port 3000)
npm run dev:wrangler Build and preview with OpenNext/Cloudflare
πŸ§ͺ Testing
npm run test Run Vitest in watch mode
npm run test:ui Run Vitest with interactive UI
npm run test:run Run tests once (CI mode)
npm run test:coverage Run tests with coverage report
πŸ—οΈ Build & Deployment
npm run pages:build Build with OpenNext for Cloudflare
npm run build Standard Next.js build (standalone)
npm run preview Preview OpenNext build locally
npm run deploy Deploy to Cloudflare Pages
πŸ” Code Quality
npm run ci:lint Run ESLint
npm run ci:typecheck TypeScript type checking (noEmit)
npm run ci:test Run tests with coverage (CI)
npm run ci:build Build for production (CI)
npm run ci:budgets Check bundle size budgets
✨ Formatting
npm run lint Run ESLint
npm run format Format code with Prettier
npm run format:check Check formatting without changing files
### πŸ—„οΈ Database Management
πŸ“¦ Migration Commands **Local Database:** ```bash # Apply schema to local D1 npm run db:migrate:local # View tables in local D1 npm run db:studio:local # Backup local database npm run db:backup:local ``` **Preview Environment (default):** ```bash # Apply schema to preview D1 npm run db:migrate # Apply all migrations from sql/migrations/ npm run db:migrate:latest:preview # View tables in preview D1 npm run db:studio # Backup preview database npm run db:backup ``` **Production Environment:** ```bash # Apply specific migration to production npm run db:migrate:up:prod # Apply all migrations to production npm run db:migrate:latest:prod ``` **Direct Wrangler Commands:** ```bash # Execute SQL query on local D1 wrangler d1 execute united-tattoo --local --command="SELECT * FROM artists" # Apply schema file wrangler d1 execute united-tattoo --file=./sql/schema.sql # Execute with preview (remote) wrangler d1 execute united-tattoo --command="SELECT * FROM users" ```
πŸ”„ Creating New Migrations 1. Create migration file in `sql/migrations/` with format: ``` YYYYMMDD_NNNN_description.sql ``` Example: `20250130_0001_add_flash_items_table.sql` 2. Write your SQL migration: ```sql -- Add flash_items table CREATE TABLE IF NOT EXISTS flash_items ( id TEXT PRIMARY KEY, artist_id TEXT NOT NULL, title TEXT NOT NULL, price REAL NOT NULL, is_available INTEGER DEFAULT 1, created_at TEXT DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (artist_id) REFERENCES artists(id) ON DELETE CASCADE ); ``` 3. Test locally: ```bash npm run db:migrate:local ``` 4. Apply to preview: ```bash npm run db:migrate:latest:preview ``` 5. Apply to production (when ready): ```bash npm run db:migrate:latest:prod ```

(back to top)

--- ## 🌍 Deployment **Production URL:** [https://united-tattoos.com](https://united-tattoos.com) ### πŸš€ Deployment Process
⚑ Quick Deploy Command

npm run pages:build && wrangler deploy
**Step-by-Step:** 1. **Build with OpenNext** ```bash npm run pages:build ``` This creates a Cloudflare-compatible build in `.vercel/output/static` 2. **Deploy to Cloudflare Pages** ```bash wrangler pages deploy .vercel/output/static ``` 3. **Verify deployment** - Check Cloudflare dashboard: Workers & Pages β†’ united-tattoo - Visit production URL: https://united-tattoos.com ### πŸ”„ CI/CD Pipeline The project uses **Gitea workflows** for automated CI/CD: **Workflows:** - **`ci.yaml`** - Main CI pipeline - βœ… ESLint - βœ… TypeScript type checking - βœ… Vitest tests with coverage - βœ… Production build - βœ… Bundle size budgets - **`deploy.yaml`** - Automated deployments - Triggers on push to `main` branch - Builds and deploys to Cloudflare - **`security.yaml`** - Security audits - npm audit - Dependency vulnerability scanning - **`performance.yaml`** - Performance checks - Bundle size analysis - Preview smoke tests **Bundle Size Budgets:** - Total static assets: **3MB max** - Individual assets: **1.5MB max** Enforced by `scripts/budgets.mjs` in CI. ### 🐳 Docker Support
πŸ‹ Docker Deployment (Alternative) The project includes a Dockerfile for self-hosting: ```bash # Build image docker build -t united-tattoo:latest . # Run container docker run --rm -p 3000:3000 \ -e PORT=3000 \ -e NEXTAUTH_URL=http://localhost:3000 \ -e NEXTAUTH_SECRET=your-secret \ # ... other env vars united-tattoo:latest ``` **Note:** Docker deployment bypasses Cloudflare Workers and uses Next.js standalone mode. For production, Cloudflare deployment is recommended.

(back to top)

--- ## πŸ“š Documentation Comprehensive documentation is available in the [`docs/`](docs/) directory: ### πŸ”‘ Key Documentation | Document | Description | |----------|-------------| | πŸ“˜ [**NEXTCLOUD-OAUTH-SETUP.md**](docs/NEXTCLOUD-OAUTH-SETUP.md) | Complete guide to setting up Nextcloud OAuth and group-based authentication | | πŸ“— [**CALDAV-SETUP.md**](docs/CALDAV-SETUP.md) | Instructions for configuring CalDAV calendar synchronization | | πŸ“™ [**CI-CD-PIPELINE.md**](docs/CI-CD-PIPELINE.md) | Detailed CI/CD pipeline documentation and troubleshooting | | πŸ“• [**BOOKING-WORKFLOW-FINAL-PLAN.md**](docs/BOOKING-WORKFLOW-FINAL-PLAN.md) | Complete booking system architecture and workflow | ### πŸ“‘ Additional Documentation
View All Documentation Files **Authentication & Integration:** - [`CALDAV-IMPLEMENTATION-SUMMARY.md`](docs/CALDAV-IMPLEMENTATION-SUMMARY.md) - [`NEXTCLOUD-OAUTH-SETUP.md`](docs/NEXTCLOUD-OAUTH-SETUP.md) **Booking & Calendar:** - [`BOOKING-WORKFLOW-FINAL-PLAN.md`](docs/BOOKING-WORKFLOW-FINAL-PLAN.md) - [`BOOKING-WORKFLOW-REVISED-PLAN.md`](docs/BOOKING-WORKFLOW-REVISED-PLAN.md) - [`BOOKING-WORKFLOW-RISKS.md`](docs/BOOKING-WORKFLOW-RISKS.md) - [`CALDAV-SETUP.md`](docs/CALDAV-SETUP.md) **CI/CD & DevOps:** - [`CI-CD-PIPELINE.md`](docs/CI-CD-PIPELINE.md) - [`CI-CD-QUICK-REFERENCE.md`](docs/CI-CD-QUICK-REFERENCE.md) **Performance & SEO:** - [`SEO-AND-PERFORMANCE-IMPROVEMENTS.md`](docs/SEO-AND-PERFORMANCE-IMPROVEMENTS.md) - [`SEO-TESTING-GUIDE.md`](docs/SEO-TESTING-GUIDE.md) - [`PERFORMANCE-SEO-SUMMARY.md`](docs/PERFORMANCE-SEO-SUMMARY.md) **Project Management:** - [`PROJECT-DOCUMENTATION.md`](docs/PROJECT-DOCUMENTATION.md) - [`technical-decisions-template.md`](docs/technical-decisions-template.md)
### πŸ€– AI Development Guide The project includes **[`CLAUDE.md`](CLAUDE.md)** with comprehensive instructions for AI assistants (like Claude Code) working with this codebase, including: - Complete architecture overview - Common commands reference - Database layer patterns - Authentication flows - CalDAV integration details - Development best practices

(back to top)

--- ## πŸ—ΊοΈ Roadmap ### βœ… Completed Features - [x] Artist portfolio system with galleries - [x] Nextcloud OAuth with auto-provisioning - [x] CalDAV bidirectional sync - [x] Flash tattoo marketplace - [x] Admin dashboard with analytics - [x] Artist self-service dashboard - [x] Appointment booking system - [x] R2 file storage integration - [x] Role-based access control - [x] CI/CD pipeline with Gitea - [x] Bundle size enforcement - [x] HEIC image conversion - [x] Artist slug-based URLs ### 🚧 In Progress - [ ] Email notifications for appointments - [ ] SMS reminders for clients - [ ] Advanced calendar conflict resolution - [ ] Payment integration (Stripe/Square) - [ ] Gift card system enhancements - [ ] Enhanced analytics dashboard ### πŸ’‘ Future Enhancements - [ ] Client self-service portal - [ ] Online deposit payments - [ ] Artist earnings reports - [ ] Inventory management - [ ] Social media auto-posting - [ ] Mobile app (React Native) - [ ] Webhook integrations - [ ] Advanced reporting See the [open issues](https://git.biohazardvfx.com/nicholai/united-tattoo/issues) for a full list of proposed features and known issues.

(back to top)

--- ## 🀝 Contributing Contributions are welcome! This project follows standard Git workflows and conventional commits. ### Development Workflow 1. **Fork the project** ```bash # Via Gitea UI or git clone git clone https://git.biohazardvfx.com/nicholai/united-tattoo.git ``` 2. **Create your feature branch** ```bash git checkout -b feat/amazing-feature ``` 3. **Make your changes** - Follow existing code style (enforced by ESLint/Prettier) - Add tests for new features - Update documentation as needed 4. **Run quality checks** ```bash npm run lint # Check linting npm run format # Format code npm run ci:typecheck # Check types npm run test:run # Run tests npm run ci:budgets # Check bundle sizes ``` 5. **Commit your changes** ```bash git add . git commit -m "feat: add amazing feature" ``` Use [Conventional Commits](https://www.conventionalcommits.org/) format: - `feat:` New feature - `fix:` Bug fix - `docs:` Documentation changes - `style:` Formatting, missing semicolons, etc. - `refactor:` Code refactoring - `test:` Adding tests - `chore:` Maintenance tasks 6. **Push to your branch** ```bash git push origin feat/amazing-feature ``` 7. **Open a Pull Request** - Via Gitea UI - Provide clear description of changes - Reference any related issues ### Code Style Guidelines - **TypeScript**: Prefer strict typing, avoid `any` - **React**: Use functional components with hooks - **File organization**: Keep components modular - **Comments**: Explain "why", not "what" - **Tests**: Test user-facing behavior, not implementation ### Top Contributors Contributors

(back to top)

--- ## πŸ“„ License
⚠️ License Status

This project currently does not have a LICENSE file in the repository. If you intend to use GNU GPLv3 (as referenced in the original README template), please add a LICENSE or COPYING file with the full license text.

Alternatively, consider: - MIT License - Permissive, allows commercial use - Apache 2.0 - Permissive with patent grant - GNU GPLv3 - Copyleft, requires source disclosure - Proprietary - All rights reserved Choose A License can help you decide.
**Current Status:** No license specified. Please add a LICENSE file to clarify usage terms.

(back to top)

--- ## πŸ“¬ Contact
**Nicholai Vogel** [![Website](https://img.shields.io/badge/Website-nicholai.work-667eea?style=for-the-badge&logo=google-chrome&logoColor=white)](https://nicholai.work) [![LinkedIn](https://img.shields.io/badge/LinkedIn-Nicholai_Vogel-0077B5?style=for-the-badge&logo=linkedin&logoColor=white)](https://linkedin.com/in/nicholai-vogel) [![Instagram](https://img.shields.io/badge/Instagram-@nicholai.exe-E4405F?style=for-the-badge&logo=instagram&logoColor=white)](https://instagram.com/nicholai.exe) **Project Repository** [https://git.biohazardvfx.com/nicholai/united-tattoo](https://git.biohazardvfx.com/nicholai/united-tattoo) **Live Website** [https://united-tattoos.com](https://united-tattoos.com)
---
### ⭐ Star this repository if you find it helpful!

(back to top)

--- **Made with ❀️ for United Tattoo Studio, Fountain, CO**
[contributors-shield]: https://img.shields.io/badge/Contributors-1-667eea?style=for-the-badge [contributors-url]: https://git.biohazardvfx.com/nicholai/united-tattoo/graphs/contributors [forks-shield]: https://img.shields.io/badge/Forks-0-667eea?style=for-the-badge [forks-url]: https://git.biohazardvfx.com/nicholai/united-tattoo/network/members [stars-shield]: https://img.shields.io/badge/Stars-0-667eea?style=for-the-badge [stars-url]: https://git.biohazardvfx.com/nicholai/united-tattoo/stargazers [issues-shield]: https://img.shields.io/badge/Issues-0-667eea?style=for-the-badge [issues-url]: https://git.biohazardvfx.com/nicholai/united-tattoo/issues [linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=for-the-badge&logo=linkedin&colorB=0077B5 [linkedin-url]: https://linkedin.com/in/nicholai-vogel [nextjs-badge]: https://img.shields.io/badge/Next.js_14-000000?style=for-the-badge&logo=nextdotjs&logoColor=white [next-url]: https://nextjs.org/ [react-badge]: https://img.shields.io/badge/React_18-20232A?style=for-the-badge&logo=react&logoColor=61DAFB [react-url]: https://react.dev/ [typescript-badge]: https://img.shields.io/badge/TypeScript-3178C6?style=for-the-badge&logo=typescript&logoColor=white [typescript-url]: https://www.typescriptlang.org/ [cloudflare-badge]: https://img.shields.io/badge/Cloudflare_Workers-F38020?style=for-the-badge&logo=cloudflare&logoColor=white [cloudflare-url]: https://developers.cloudflare.com/workers/ [opennext-badge]: https://img.shields.io/badge/OpenNext-18181B?style=for-the-badge&logo=vercel&logoColor=white [opennext-url]: https://opennext.js.org/ [shadcn-badge]: https://img.shields.io/badge/ShadCN_UI-000000?style=for-the-badge&logo=shadcnui&logoColor=white [shadcn-url]: https://ui.shadcn.com [tailwind-badge]: https://img.shields.io/badge/Tailwind_CSS-38B2AC?style=for-the-badge&logo=tailwind-css&logoColor=white [tailwind-url]: https://tailwindcss.com [framer-badge]: https://img.shields.io/badge/Framer_Motion-0055FF?style=for-the-badge&logo=framer&logoColor=white [framer-url]: https://www.framer.com/motion/ [d1-badge]: https://img.shields.io/badge/D1_Database-F38020?style=for-the-badge&logo=cloudflare&logoColor=white [d1-url]: https://developers.cloudflare.com/d1/ [r2-badge]: https://img.shields.io/badge/R2_Storage-F38020?style=for-the-badge&logo=cloudflare&logoColor=white [r2-url]: https://developers.cloudflare.com/r2/ [nextauth-badge]: https://img.shields.io/badge/NextAuth.js-000000?style=for-the-badge&logo=nextdotjs&logoColor=white [nextauth-url]: https://next-auth.js.org/ [caldav-badge]: https://img.shields.io/badge/CalDAV-0082C9?style=for-the-badge&logo=nextcloud&logoColor=white [caldav-url]: https://en.wikipedia.org/wiki/CalDAV [vitest-badge]: https://img.shields.io/badge/Vitest-6E9F18?style=for-the-badge&logo=vitest&logoColor=white [vitest-url]: https://vitest.dev/ [eslint-badge]: https://img.shields.io/badge/ESLint-4B32C3?style=for-the-badge&logo=eslint&logoColor=white [eslint-url]: https://eslint.org/ [prettier-badge]: https://img.shields.io/badge/Prettier-F7B93E?style=for-the-badge&logo=prettier&logoColor=black [prettier-url]: https://prettier.io/