Build and maintain a Next.js 16 dog adoption platform with protected admin dashboard, i18n support, and Cloudinary image management. Follows strict patterns for auth, database, and image uploads.
Build and maintain a Next.js 16 dog adoption platform with a protected admin dashboard for managing adoptable dogs. The platform features bilingual support (English/Spanish), secure authentication, and Cloudinary-based image management.
1. **Middleware Protection**: Use `proxy.ts` with NextAuth's `auth` as default export
- Protect `/admin/*` routes (exclude `/admin/login`)
- Redirect unauthorized users to `/admin/login`
2. **Credentials Provider**: Validate against `Admin` table using bcrypt
- Configuration in `auth.config.ts`
- Session-based authentication (no JWT)
3. **API Route Protection**: Always check `await auth()` before mutations
- Return 401 if no session
- Verify session exists before processing requests
1. **JSON String Storage**: `Dog.gallery` stored as `String?` in Prisma, handled as `string[]` in TypeScript
- **Parse on read**: `JSON.parse(dog.gallery)` in data access layer
- **Stringify on write**: `JSON.stringify(gallery)` in API routes
2. **Status Filtering**: Public queries ALWAYS filter `WHERE status != 'Adopted'`
- Prevent adopted dogs from appearing on public site
- Admin dashboard shows all statuses
3. **Client Singleton**: Use `prisma` from `lib/prisma.ts`
- Prevents hot reload connection issues
- Singleton pattern for development
1. **Admin selects image** → DogForm component
2. **Show crop modal** → ImageCropModal with resize, crop, rotate, quality controls
3. **Convert to blob** → POST to `/api/upload`
4. **Upload to Cloudinary** → Convert File to Buffer, upload to `dogs/[dogName]/` folder
5. **Store URL in database** → Cloudinary URL (never local files)
**Key Rules**:
1. **Server-side locale detection** (`lib/i18n-server.ts`):
- Check cookie → `Accept-Language` header → default "en"
2. **Message structure**: Flat JSON in `lib/i18n-messages.ts`
- Dot notation keys (e.g., `"hero.title"`)
3. **Client hydration**: LocaleProvider wraps app with React Context
- Use `useI18n()` hook in client components
4. **Switching**: LanguageSwitcher calls server action `setLocaleCookie()` → revalidates path
1. **Shared schemas** in `lib/validations.ts`:
- `dogSchema`, `dogUpdateSchema`, `loginSchema`
2. **Usage patterns**:
- API routes: `.parse()` throws 400 on validation error
- Form submissions: Client-side validation
- TypeScript types: `z.infer<typeof schema>`
3. **Enum enforcement**: `sex`, `size`, `status` use Zod enums matching Prisma exactly
```
app/
├── (protected)/ # Admin routes with shared layout
│ └── admin/
│ ├── components/ # Admin-only components (NOT shared)
│ ├── dogs/
│ └── login/
├── components/ # Public site components
├── api/ # API routes (route.ts files)
│ ├── dogs/
│ ├── upload/
│ └── auth/
lib/
├── db/ # Database utilities
├── i18n-server.ts # Server-side i18n
├── i18n-messages.ts # Translation messages
├── validations.ts # Zod schemas
├── dogs.ts # Data access layer
├── styles.ts # Shared Tailwind classes
└── prisma.ts # Prisma client singleton
prisma/
├── schema.prisma # Database schema
├── migrations/ # Migration files
└── seed.ts # Seed script
```
```bash
pnpm install
npx prisma migrate dev --name init
npx prisma generate
pnpm dev
```
```bash
npx prisma studio # Database GUI (localhost:5555)
npx prisma migrate dev --name <name> # Create migration
npx prisma db seed # Seed default admin + dogs
npx prisma migrate reset # ⚠️ Reset database
```
- Email: `[email protected]`
- Password: `password123`
1. **Gallery field**: ALWAYS JSON.parse on read, JSON.stringify on write
2. **Status filtering**: NEVER show adopted dogs publicly
3. **Auth timing**: `await auth()` BEFORE accessing request body in API routes
4. **Image paths**: NO references to `/public/dogs/` (Cloudinary URLs only)
5. **Locale detection**: Runs every request - don't call `getLocale()` in client components
6. **Prisma generation**: Run `npx prisma generate` after schema changes
7. **Middleware matcher**: MUST exclude `/admin/login` to avoid redirect loops
```bash
DATABASE_URL=<production-postgresql-url>
NEXTAUTH_URL=https://yourdomain.com # NOT localhost
NEXTAUTH_SECRET=<openssl rand -base64 32> # Generate new for production
CLOUDINARY_CLOUD_NAME=<your-cloud-name>
CLOUDINARY_API_KEY=<your-api-key>
CLOUDINARY_API_SECRET=<your-api-secret>
ADMIN_EMAIL=<real-email> # NOT [email protected]
ADMIN_PASSWORD=<strong-password> # NOT password123
```
**CRITICAL**: Update documentation when making changes:
```
README.md # User-facing overview
.github/copilot-instructions.md # Architecture, workflows
documentation/ARCHITECTURE.md # System architecture
documentation/TESTING_CHECKLIST.md # Manual testing procedures
documentation/ADMIN_SETUP.md # Admin dashboard guide
documentation/DATABASE_SETUP.md # Database configuration
QUICKSTART.md # Quick reference
```
1. **Admin workflow testing**:
- Authentication (login, logout, session)
- CRUD operations (dogs)
- Image upload validation
- Form validation (Zod)
- Authorization checks
2. **Testing stack**:
- **Unit**: Vitest for lib functions
- **Integration**: Vitest + MSW for API routes
- **E2E**: Playwright for user workflows
3. **Test patterns**:
- Mock Prisma with `prisma-mock` or in-memory SQLite
- Mock Cloudinary (don't hit real API)
- Use `DATABASE_URL_TEST` in `.env.test`
- Seed test data before each suite
4. **Coverage goals**:
- Admin API routes: 90%+
- Database queries: 80%+
- Validation schemas: 100%
- Public API routes: 70%+
When building new features, consider these planned additions:
1. **Visitor inquiry submissions**: Email notifications, database tracking
2. **Payment processing**: Stripe integration for donations
3. **Multiple admin roles**: RBAC (viewer, editor, super-admin)
4. **Email newsletters**: SendGrid/Mailchimp integration
5. **Volunteer requests**: Application form, admin review workflow
When working on this codebase:
1. **Always read files before modifying** - Use Read tool to understand existing patterns
2. **Follow authentication patterns** - All admin routes must check `await auth()`
3. **Handle gallery field correctly** - Remember JSON parse/stringify for `Dog.gallery`
4. **Use Cloudinary for images** - Never store images locally in `/public`
5. **Filter adopted dogs** - Public queries must exclude adopted status
6. **Update documentation** - Modify relevant docs when making changes
7. **Use shared patterns** - Import from `lib/styles.ts`, `lib/validations.ts`
8. **Server components by default** - Only use `"use client"` when necessary
9. **Validate with Zod** - Always use schemas from `lib/validations.ts`
10. **Test manually** - Follow `documentation/TESTING_CHECKLIST.md` after changes
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/nextjs-dog-adoption-platform-builder/raw