A comprehensive technical analysis of the SkunkOrJunk cannabis review platform: modern monolithic architecture, data-driven review system, terpene and effect profiling, editorial workflow, and the custom CMS that powers content operations.
A modern, monolithic approach leveraging Next.js for both frontend rendering and backend API logic. Cohesive development experience optimized for serverless-friendly environments with file-based data persistence.
Next.js serves both frontend and backend from a single codebase. App Router for page rendering, API Routes for server-side logic. Unified deployment artifact simplifies operations.
SQLite database via Prisma ORM. Entire database in a single file—simplifies deployment, backup, and migration. Perfect for serverless and containerized environments with persistent disk.
Reviews are comprehensive data objects—not just text and ratings. Scientific profiles (terpenes), experiential data (effects), and rich media combine for multi-faceted product analysis.
TypeScript throughout. Prisma generates type-safe client from schema. Zod for runtime validation. Compile-time safety from database to UI.
Strategic selection of modern, production-proven technologies. Balance of high performance and rich UX with simplicity and ease of deployment.
NextAuth.js with credentials-based login. bcrypt for password hashing. Middleware-protected admin routes at /admin/:path*. Session management with secure cookies.
formidable library parses multipart/form-data. URL rewrite in next.config.js maps /uploads/* to /api/uploads/* for secure file serving. Persistent storage at UPLOAD_DIR.
SQLite FTS via scripts/create-fts.js. Creates reviews_fts virtual table for efficient keyword search. Raw queries via prisma.$queryRawUnsafe for SQLite-specific features.
Standard Next.js App Router structure. Conventional layout enhances maintainability, reduces learning curve, and ensures clear separation of concerns.
api/ — Backend API routes
admin/ — Protected admin pages
reviews/[slug]/ — Review pages
archive/ — Review archive
page.tsx — Homepage
reviews/ — Review CRUD
reviews/draft/ — Draft management
sponsors/ — Sponsor management
upload/ — File uploads
[...nextauth]/ — Auth handlers
src/components/ — Reusable UI
src/lib/ — Utilities, Prisma
prisma/ — Schema, migrations
scripts/ — Build utilities
public/ — Static assets
Defined in prisma/schema.prisma. Blueprint for application data with core models, relationships, and join tables for many-to-many associations.
Central model. strainName, method, brand, thc%, images (product, packaging, brandLogo). title, slug, excerpt, content.
Chemical compound data. name (Myrcene, Limonene, etc.) and percentage. Linked directly to Review.
Dictionary of possible effects. "Relaxed", "Creative", "Happy", etc. Many-to-many with Review via ReviewEffect.
Brand partners. name, logo, url, category, active flag. Many-to-many with Review via ReviewSponsor.
Application administrators. email, passwordHash (bcrypt). Used by NextAuth credentials provider.
Key-value store. Site config: siteName, logo, highlightA/B colors, contactEmail, termsContent, privacyContent.
Four-step content pipeline from draft creation to publication. API endpoints and admin interfaces at each stage ensure quality control.
POST /api/reviews/draft/ — Core details entered, saved as draft
Images via /api/upload/, effects assigned, terpene %s entered
POST /api/reviews/draft/[id]/submit/ — Status → PENDING
POST /api/admin/reviews/[id]/approve/ — Publish or reject
Draft management interface. Create, edit, enrich content.
Moderation queue. Review pending submissions.
Published review management. Search, filter, edit, delete.
Site-wide configuration. Branding, theming, legal content.
Containerized deployment with Docker. Multi-stage build for optimized images. Persistent disk for SQLite database and user uploads.
prisma generate &&
node scripts/maybe-migrate.js &&
node scripts/create-fts.js &&
next build/var/data/database.db — SQLite file path
/var/data/uploads — Persistent file storage
Session signing key (long random string)
Canonical URL for auth callbacks
Initial admin email/password for seed
deps → builder → runner stages. Minimal production image with only necessary artifacts.
next.config.js: output: 'standalone'. Only essential files copied to .next/standalone.
Mount at /var/data. Database and uploads preserved across deployments.
NextAuth.js credentials provider with bcrypt password hashing. Middleware-based route protection for all administrative paths.
All admin routes protected by middleware. Unauthenticated users redirected to login.
Email + password → bcrypt compare against AdminUser.passwordHash → Session cookie issued.
Homepage, review pages (/reviews/[slug]), archive. All public content accessible without login.
SkunkOrJunk delivers data-centric cannabis reviews through a robust technical foundation. Modern monolith, scientific data integration, structured editorial workflow, and containerized deployment.