A modern, full-stack application for creating stunning blog thumbnails in seconds. Built with a Turborepo monorepo architecture featuring a Next.js frontend and Express.js API backend.
Lomo is a professional thumbnail creation tool that allows content creators to:
- Choose from curated backgrounds - Select from a collection of high-quality background images
- Perfect text colors - Automatically suggested color palettes based on background selection
- Customize layouts - Pre-designed layout templates with drag-and-drop functionality
- Add visual assets - Categorized collection of icons, illustrations, and design elements
- Export high-quality thumbnails - Generate production-ready images for blogs, social media, and content platforms
- π¨ Visual Editor - Canvas-based editor built with Fabric.js for precise design control
- π± Responsive Design - Optimized for desktop use (mobile support coming soon)
- π― Template System - Pre-built layouts with customizable elements
- π Smart Color Suggestions - AI-powered color recommendations based on background analysis
- π¦ Asset Library - Organized collection of design assets by category
- β‘ Real-time Preview - Instant visual feedback while designing
This project uses a Turborepo monorepo structure with the following packages:
web- Next.js 15 frontend application with App Routerapi- Express.js backend API with TypeScript
@repo/ui- Shared UI component library built with shadcn/ui@repo/db- Database layer with Prisma ORM and MongoDB@repo/eslint-config- Shared ESLint configurations@repo/typescript-config- Shared TypeScript configurations
- Next.js 15 - React framework with App Router
- TypeScript - Type-safe development
- Tailwind CSS - Utility-first CSS framework
- Fabric.js - Canvas manipulation and graphics
- Framer Motion - Animation library
- TanStack Query - Data fetching and caching
- Zustand - State management
- shadcn/ui - UI component library
- Express.js - Node.js web framework
- TypeScript - Type-safe backend development
- Prisma - Database ORM
- MongoDB - NoSQL database
- Supabase - Backend-as-a-Service for file storage
- Zod - Runtime type validation
- tsup - TypeScript bundler
- ts-node - TypeScript execution environment
- Turborepo - Monorepo build system
- pnpm - Fast, disk space efficient package manager
- ESLint - Code linting
- Prettier - Code formatting
- Node.js 18+
- pnpm 9.0.0+
- MongoDB database
- Supabase account (for file storage)
-
Clone the repository
git clone <repository-url> cd lomo-new
-
Install dependencies
pnpm install
-
Environment Configuration
Create environment files:
# Database package cp packages/database/.env.example packages/database/.env # API app cp apps/api/.env.example apps/api/.env # Web app cp apps/web/.env.local.example apps/web/.env.local
Configure the following environment variables:
Database (
packages/database/.env):DATABASE_URL="mongodb://localhost:27017/lomo"
API (
apps/api/.env):DATABASE_URL="database-uri" SUPABASE_URL="your-supabase-url" SUPABASE_SERVICE_ROLE_KEY="your-supabase-service-role-key" PORT=8000
Web (
apps/web/.env.local):NEXT_PUBLIC_API_HOST="http://localhost:3001"
-
Database Setup Navigate to packages/database and run the following:
# Generate Prisma client pnpm run db:generate # Push database schema pnpm run db:push # (Optional) Seed database pnpm --filter @repo/db run db:seed
Running the build,dev or start commands at the root of the project also runs the db:push(see the turbo.json file ) which syncs the schema with the database and generated the prisma client in the generated/client directory
-
Development
# Start all applications in development mode pnpm dev # Or start specific applications pnpm dev --filter=web # Frontend only pnpm dev --filter=api # Backend only
-
Production Build
# Build all applications pnpm build # Start production servers pnpm start
During the development and deployment of this project, several challenges were encountered and resolved:
Challenge: Setting up shadcn/ui components to work across multiple applications in a monorepo while maintaining proper TypeScript support and build processes.
Solution:
- Created a dedicated
@repo/uipackage with proper export configuration - Configured
components.jsonwith monorepo-specific aliases:{ "aliases": { "components": "@repo/ui/components", "utils": "@repo/ui/lib/utils", "ui": "@repo/ui/components/ui" } } - Set up proper TypeScript path mapping in consuming applications
- Used workspace protocol (
workspace:*) for internal package dependencies - Created a global.css file in the web app and imported css file from the
@repo/uipackage(view global.css file in apps/web). - Import @repo/ui postcss config in web app postcss config file
Challenge: Building and running TypeScript API code efficiently in both development and production environments.
Solution:
- Development: Used
nodemonwithesbuild-registerfor fast TypeScript compilation:{ "dev": "nodemon --exec \"node -r esbuild-register ./src/index.ts\" -e .ts" } - Production: Implemented
tsupfor optimized builds:// tsup.config.ts export default defineConfig({ entryPoints: ['src/index.ts'], clean: true, format: ['cjs'] });
- Execution: Used
ts-nodefor running built JavaScript in production:{ "start": "ts-node dist/index.js" }
Challenge: Prisma client generation failing in production builds due to missing generated files and schema access issues.
Solution:
- Custom Output Directory: Configured Prisma to generate client in a tracked directory:
generator client { provider = "prisma-client-js" output = "../generated/client" }
- Build Process Integration: Ensured generated Prisma client is included in version control
- Turbo Configuration: Set up proper build dependencies so database operations happen before API builds:
{ "api#build": { "dependsOn": ["^build", "^db:push"] } }
Challenge: Managing build order and dependencies between packages, especially ensuring database operations complete before API builds.
Solution:
- Package-specific Build Tasks: Created targeted build configurations:
{ "api#build": { "dependsOn": ["^build", "^db:push"] }, "web#build": { "dependsOn": ["^build"] } } - Independent Production Web Builds: Removed API dependency from web builds in production
- Environment-specific Tasks: Separated development and production task dependencies
lomo-new/
βββ apps/
β βββ api/ # Express.js API server
β β βββ src/
β β βββ tsup.config.ts # Build configuration
β β βββ package.json
β βββ web/ # Next.js frontend
β βββ app/ # App Router pages
β βββ components/ # React components
β βββ lib/ # Utility functions
β βββ package.json
βββ packages/
β βββ database/ # Prisma schema and client
β β βββ prisma/
β β βββ generated/ # Generated Prisma client
β β βββ src/
β βββ ui/ # Shared UI components (shadcn/ui)
β β βββ src/
β β β βββ components/
β β β βββ lib/
β β βββ components.json
β βββ eslint-config/ # Shared ESLint configs
β βββ typescript-config/ # Shared TypeScript configs
βββ turbo.json # Turborepo configuration
βββ pnpm-workspace.yaml # pnpm workspace configuration
βββ package.json # Root package.json
pnpm dev # Start all apps in development
pnpm build # Build all apps and packages
pnpm start # Start all apps in production
pnpm lint # Lint all packages
pnpm format # Format code with Prettier
pnpm studio # Open Prisma Studiopnpm dev --filter=web # Start only web app
pnpm dev --filter=api # Start only API server
pnpm build --filter=web # Build only web app-
Start Development Environment
pnpm dev
This starts:
- Web app at
http://localhost:3000 - API server at
http://localhost:3001
- Web app at
-
Database Management
pnpm studio # Open Prisma Studio pnpm --filter @repo/db db:push # Push schema changes
-
Adding UI Components
cd packages/ui npx shadcn@latest add button # Add new shadcn component
-
Type Checking
pnpm check-types # Check types across all packages
The application is designed for deployment on modern platforms like Vercel(frontend), Railway(backend), or similar services that support monorepos.
-
Web App (Frontend)
- Build Command:
pnpm build --filter=web - Output Directory:
apps/web/.next - Environment Variables:
NEXT_PUBLIC_API_HOST
- Build Command:
-
API Server (Backend)
- Build Command:
pnpm build --filter=api - Start Command:
pnpm start --filter=api - Environment Variables:
DATABASE_URL,SUPABASE_URL,SUPABASE_SERVICE_ROLE_KEY
- Build Command:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request