create-estack-app
v0.1.0
Published
A powerful CLI tool to scaffold Next.js websites with DaisyUI styling
Downloads
136
Maintainers
Readme
create-estack-app
A powerful CLI tool to scaffold Next.js websites with DaisyUI styling and optional Payload CMS v3 integration.
Features
- Interactive CLI with modern prompts
- Next.js 15 with App Router
- DaisyUI + Tailwind CSS for styling
- Optional Payload CMS v3 integration
- Multiple database options (PostgreSQL, MongoDB)
- Pre-built section components (Hero, About, Features, Contact)
- TypeScript throughout
- CMS-agnostic components with fallback support
- Automatic schema generation based on selected sections
Quick Start
npx create-estack-app
# or
yarn create estack-app
# or
pnpm create estack-appWhat You Get
The CLI will ask you a series of questions to customize your project:
- Project Name - Your project identifier
- Sections - Choose which sections to include (order matters!)
- Header Style - Default, Centered, or Minimal
- DaisyUI Theme - Choose from 9 beautiful themes
- Package Manager - yarn, pnpm, or npm
- Include Payload CMS? - Full CMS integration or markdown-based
- Database Type - PostgreSQL or MongoDB (if using Payload)
Available Sections
- Hero - Full-width banner with heading, subheading, CTA buttons
- About - Two-column layout with text and image
- Features - Grid of feature cards with icons
- Contact - Contact form with validation
DaisyUI Themes
Choose from: light, dark, cupcake, corporate, synthwave, retro, cyberpunk, valentine, garden
Usage Examples
Markdown-Based Site (No CMS)
npx create-estack-app
# Answer prompts:
# - Project name: my-portfolio
# - Sections: Hero, About, Features
# - Header style: Default
# - Theme: dark
# - Package manager: yarn
# - Include Payload? NoThen:
cd my-portfolio
yarn devYour site is ready at http://localhost:3000! Content is managed via markdown files in the content/ directory.
Full CMS-Powered Site with Payload
npx create-estack-app
# Answer prompts:
# - Project name: my-business-site
# - Sections: Hero, About, Contact
# - Header style: Centered
# - Theme: corporate
# - Package manager: yarn
# - Include Payload? Yes
# - Database: MongoDBThen:
cd my-business-site
cp .env.example .env.local
# Edit .env.local and add:
# DATABASE_URI=mongodb://localhost:27017/my-business-site
# PAYLOAD_SECRET=your-secret-key-here
yarn install
yarn devVisit:
- Frontend:
http://localhost:3000 - Admin Panel:
http://localhost:3000/admin
Create your first user and start managing content!
Project Structure
Without Payload (Markdown-Based)
my-project/
├── src/
│ ├── app/
│ │ ├── layout.tsx
│ │ ├── page.tsx # Loads content from markdown
│ │ └── globals.css
│ ├── components/
│ │ ├── sections/
│ │ │ ├── Hero.tsx # Pure, logic-agnostic
│ │ │ ├── About.tsx
│ │ │ └── ...
│ │ ├── Header.tsx
│ │ └── Footer.tsx
│ └── content/ # Markdown content files
│ ├── site-config.md
│ └── sections/
│ ├── hero.md
│ └── ...
├── tailwind.config.ts
├── next.config.ts
└── package.jsonWith Payload CMS
my-project/
├── .env.example # Database connection template
├── src/
│ ├── app/
│ │ ├── (payload)/ # Admin routes
│ │ │ ├── admin/
│ │ │ │ ├── [[...segments]]/
│ │ │ │ │ └── page.tsx
│ │ │ │ └── importMap.js
│ │ │ └── layout.tsx
│ │ ├── api/
│ │ │ └── [...slug]/
│ │ │ └── route.ts # Payload REST API
│ │ ├── layout.tsx
│ │ └── page.tsx # Fetches from CMS abstraction
│ ├── components/
│ │ ├── sections/ # Same pure components
│ │ ├── Header.tsx
│ │ └── Footer.tsx
│ ├── content/ # Markdown fallbacks
│ ├── lib/
│ │ ├── cms.ts # CMS abstraction layer
│ │ └── fallbackData.ts # Default content
│ └── payload/
│ ├── payload.config.ts
│ ├── collections/
│ │ └── Users.ts
│ └── globals/ # Auto-generated schemas
│ ├── HeroSection.ts
│ ├── AboutSection.ts
│ └── ...
└── package.jsonHow It Works
CMS Abstraction Layer
The generated projects use a smart abstraction layer (lib/cms.ts) that:
- Tries Payload first: If
DATABASE_URIorDATABASE_URLis set, fetches from Payload - Falls back to markdown: If Payload isn't configured, reads from markdown files
- No runtime errors: Components work identically with either data source
This means:
- Your site builds and runs without a database
- You can develop locally with markdown
- Add Payload later by just setting environment variables
- Components never know where data comes from
Auto-Generated Schemas
When you select sections, the generator:
- Creates Payload Global schemas for each section
- Defines fields matching the component's props
- Auto-registers them in
payload.config.ts - Sets up proper access control
Only selected sections appear in the Payload admin!
Environment Variables (Payload Projects)
# Required for Payload
DATABASE_URI=mongodb://localhost:27017/dbname # For MongoDB
DATABASE_URL=postgres://user:pass@localhost:5432/db # For Postgres
PAYLOAD_SECRET=your-secret-key-here
# Optional
NEXT_PUBLIC_SERVER_URL=http://localhost:3000Development
Build from Source
git clone https://github.com/EladKarni/create-estack-app
cd create-estack-app
git checkout version-2
yarn install
yarn buildLocal Testing
# Build the CLI
yarn build
# Test it
node dist/index.js
# Or run automated tests
npx tsx test.jsTech Stack
CLI
- Prompts: @clack/prompts
- File System: fs-extra
- Process Execution: execa
- Build Tool: tsup
- Language: TypeScript
Generated Projects
- Framework: Next.js 15 (App Router)
- Styling: Tailwind CSS + DaisyUI
- CMS: Payload CMS v3 (optional)
- Database: MongoDB or PostgreSQL (with Payload)
- Content: gray-matter (for markdown)
Requirements
- Node.js 18 or higher
- npm, pnpm, or yarn
Architecture Highlights
Logic-Agnostic Components
UI components are pure and receive props:
// components/sections/Hero.tsx
export default function Hero({ title, subtitle, ctaButtons }) {
return (
<section>
<h1>{title}</h1>
<p>{subtitle}</p>
{ctaButtons.map(btn => <button>{btn.text}</button>)}
</section>
);
}They never import Payload or read files directly. This keeps them:
- Reusable
- Testable
- CMS-agnostic
Smart Data Fetching
The page component fetches data through the abstraction:
// app/page.tsx (Payload version)
import { fetchGlobal } from '@/lib/cms';
export default async function Home() {
const heroData = await fetchGlobal('hero-section');
return <Hero {...heroData} />;
}The abstraction handles the complexity of trying Payload, falling back to markdown, and error handling.
Extending
Want to add more sections? Just:
- Add metadata to
src/prompts/index.ts:
{
value: 'pricing',
label: 'Pricing - Pricing tables',
type: 'global',
payloadSlug: 'pricing-section'
}- Define fields in
src/utils/payload-generators.ts:
pricing: [
{ name: 'title', type: 'text', required: true },
{ name: 'plans', type: 'array', fields: [...] },
]Create component template in
src/templates/static/src/components/sections/Pricing.tsxAdd markdown template in
src/templates/static/content/sections/pricing.md
The generator handles the rest!
Roadmap
- [ ] More section types (Blog, Portfolio, Testimonials, FAQ)
- [ ] Collection-type sections (not just Globals)
- [ ] Media upload integration
- [ ] Section reordering UI
- [ ] Custom field types
- [ ] Theme customization wizard
- [ ] Deployment guides
- [ ] Video tutorials
Contributing
Contributions welcome! Please:
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Test thoroughly (
npx tsx test.js) - Commit your changes
- Push and open a Pull Request
License
MIT
Credits
Built with patterns from:
- create-t3-app - CLI inspiration
- nextjs-daisyui-payload-template - Payload v3 reference architecture
- Payload CMS - Headless CMS
Support
Troubleshooting
Payload Admin /admin ImportMap Error
If you see an error like:
Module not found: Package path ./generateComponentMap is not exported from package @payloadcms/richtext-lexicalThis happens because the importMap.js file needs to be regenerated by Payload. To fix:
Delete the existing importMap:
rm src/app/\(payload\)/admin/importMap.jsRun the Payload import map generator:
yarn generate:importmap # or npm run generate:importmapRestart your dev server:
yarn dev
The importMap will be automatically regenerated with the correct imports for your installed Payload version.
Note: The importMap.js is auto-generated and is ignored in .gitignore. Each developer needs to generate it locally.
Database Connection Issues
Make sure your database is running and the connection string in .env.local is correct:
MongoDB:
# Start MongoDB
brew services start mongodb-community
# or
docker run -d -p 27017:27017 mongoPostgreSQL:
# Start PostgreSQL
brew services start postgresql
# or
docker run -d -p 5432:5432 -e POSTGRES_PASSWORD=postgres postgresNote: This project implements Payload CMS v3 integration following the AI-oriented plan detailed in IMPLEMENTATION_SUMMARY.md.
