A single-page website for Periluna Studios, a picture editing service specializing in watermark creation and removal for verified owners.
- Framework: Next.js 14+ (App Router)
- Styling: Tailwind CSS
- Database: Supabase (PostgreSQL)
- File Storage: Supabase Storage
- Payments: Stripe Checkout
- Email: Resend
- Hosting: Vercel
npm installCopy .env.local.example to .env.local and fill in your credentials:
cp .env.local.example .env.localRequired variables:
NEXT_PUBLIC_SUPABASE_URL- Your Supabase project URLNEXT_PUBLIC_SUPABASE_ANON_KEY- Supabase anonymous keySUPABASE_SERVICE_ROLE_KEY- Supabase service role key (server-side only)STRIPE_SECRET_KEY- Stripe secret keySTRIPE_WEBHOOK_SECRET- Stripe webhook signing secretNEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY- Stripe publishable keyRESEND_API_KEY- Resend API key for emailsNEXT_PUBLIC_SITE_URL- Your site URL (e.g., http://localhost:3000)ADMIN_EMAIL- Email address for admin notificationsNEXT_PUBLIC_CONTACT_EMAIL- Public contact email displayed on site
Run the migration in your Supabase SQL editor:
# Copy the contents of supabase/migrations/001_initial_schema.sql
# and run it in your Supabase Dashboard > SQL EditorCreate a storage bucket:
- Go to Supabase Dashboard > Storage
- Create a new bucket called
order-files - Set it to private (not public)
- Recommended file size limit: 50MB
- Allowed MIME types:
image/*
- Create products in Stripe Dashboard for each pricing tier (optional - we use dynamic pricing)
- Set up webhook endpoint:
https://your-domain.com/api/webhook - Enable
checkout.session.completedevent - Copy the webhook signing secret to
STRIPE_WEBHOOK_SECRET
npm run devOpen http://localhost:3000 in your browser.
periluna/
├── app/
│ ├── layout.tsx # Root layout, fonts, metadata
│ ├── page.tsx # Main landing page
│ ├── api/
│ │ ├── submit/route.ts # Form submission handler
│ │ └── webhook/route.ts# Stripe webhook handler
│ ├── success/page.tsx # Payment success page
│ ├── cancel/page.tsx # Payment cancelled page
│ ├── sitemap.ts # Auto-generated sitemap
│ ├── robots.ts # Robots.txt configuration
│ └── globals.css # Tailwind + custom styles
├── components/
│ ├── Hero.tsx # Hero section with logo
│ ├── Services.tsx # Services overview
│ ├── Pricing.tsx # Pricing tiers
│ ├── PricingCalculator.tsx # Volume pricing calculator
│ ├── IntakeForm.tsx # Order intake form
│ ├── FileUpload.tsx # Drag-drop file upload
│ ├── FAQ.tsx # Accordion FAQ section
│ └── Footer.tsx # Site footer
├── lib/
│ ├── supabase.ts # Supabase client
│ ├── stripe.ts # Stripe client & pricing
│ └── email.ts # Email notifications
├── supabase/
│ └── migrations/ # Database migrations
├── public/
│ └── periluna.png # Logo
└── .env.local.example # Environment variables template
| Tier | Quantity | Price |
|---|---|---|
| Single | 1 image | $2.50 |
| Bundle | Up to 10 images | $20.00 |
| Custom | 11-25 images | $1.75/each |
| Custom | 26-50 images | $1.50/each |
| Custom | 51+ images | $1.25/each |
- Single-page design with smooth scroll navigation
- Dark navy theme matching the brand aesthetic
- File upload with drag-drop and image previews
- Real-time pricing calculator for volume orders
- Stripe Checkout for secure payments
- Etsy order support - bypass payment for existing customers
- Admin email notifications for all orders
- SEO optimized with meta tags, structured data, and sitemap
- Mobile responsive design
- Push to GitHub
- Import project in Vercel
- Add environment variables
- Deploy
npm run build
npm startnpm run dev- Start development servernpm run build- Build for productionnpm start- Start production servernpm run lint- Run ESLint
Private - All rights reserved