Summary
Create a CLI tool that scaffolds UDL projects with composable framework + data source combinations.
MVP Scope
For initial release, support:
- Framework: Next.js only (14+)
- Source: Contentful only
Usage
# Interactive mode (prompts for missing options)
npx create-udl-app my-app
# Explicit flags
npx create-udl-app my-app --framework=nextjs --source=contentful
# Future: Multiple sources
npx create-udl-app my-app --framework=nextjs --source=contentful,shopify
Interactive Flow
? What is your project named? › my-app
? Which framework? › Next.js (more coming soon)
? Which data sources? › ☑ Contentful (more coming soon)
Next.js Adapter Package
The generated app uses @udl/adapter-nextjs which provides a unified CLI:
{
"scripts": {
"dev": "udl-next dev",
"build": "udl-next build",
"start": "udl-next start"
}
}
How udl-next works
- Starts UDL server (runs
sourceNodes, exposes GraphQL endpoint)
- Spawns the corresponding
next command (dev, build, start)
- Manages lifecycle (graceful shutdown, signal forwarding)
Adapter package structure
packages/adapter-nextjs/
├── package.json
├── src/
│ └── cli.ts # Entry point for udl-next command
└── README.md
// packages/adapter-nextjs/package.json
{
"name": "@udl/adapter-nextjs",
"bin": {
"udl-next": "./dist/cli.js"
},
"peerDependencies": {
"next": ">=14.0.0"
},
"dependencies": {
"universal-data-layer": "workspace:*"
}
}
The adapter uses the user's installed next (peer dep), so one package works for Next.js 14, 15, 16+.
Generated Output
package.json
{
"name": "my-app",
"scripts": {
"dev": "udl-next dev",
"build": "udl-next build",
"start": "udl-next start"
},
"dependencies": {
"next": "^15.0.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"universal-data-layer": "^1.0.0",
"@udl/adapter-nextjs": "^1.0.0",
"@udl/plugin-source-contentful": "^1.0.0"
}
}
udl.config.ts
import { defineConfig } from 'universal-data-layer';
export const { config } = defineConfig({
config: {
plugins: [
{
name: '@udl/plugin-source-contentful',
options: {
spaceId: process.env.CONTENTFUL_SPACE_ID,
accessToken: process.env.CONTENTFUL_ACCESS_TOKEN,
},
},
],
},
});
.env.example
# Contentful
CONTENTFUL_SPACE_ID=
CONTENTFUL_ACCESS_TOKEN=
CONTENTFUL_ENVIRONMENT=master
Package Structure
packages/create-udl-app/
├── package.json
├── src/
│ ├── index.ts # CLI entry point
│ ├── prompts.ts # Interactive prompts
│ ├── generator.ts # File generation logic
│ └── sources/
│ └── contentful.ts # Source plugin definition
└── templates/
└── frameworks/
└── nextjs/ # Base Next.js skeleton
Acceptance Criteria
Future Enhancements
- More frameworks: Nuxt, Express, Astro
- More sources: Shopify, Okendo (as plugins are published)
Related
Summary
Create a CLI tool that scaffolds UDL projects with composable framework + data source combinations.
MVP Scope
For initial release, support:
Usage
Interactive Flow
Next.js Adapter Package
The generated app uses
@udl/adapter-nextjswhich provides a unified CLI:{ "scripts": { "dev": "udl-next dev", "build": "udl-next build", "start": "udl-next start" } }How
udl-nextworkssourceNodes, exposes GraphQL endpoint)nextcommand (dev,build,start)Adapter package structure
The adapter uses the user's installed
next(peer dep), so one package works for Next.js 14, 15, 16+.Generated Output
package.json
{ "name": "my-app", "scripts": { "dev": "udl-next dev", "build": "udl-next build", "start": "udl-next start" }, "dependencies": { "next": "^15.0.0", "react": "^19.0.0", "react-dom": "^19.0.0", "universal-data-layer": "^1.0.0", "@udl/adapter-nextjs": "^1.0.0", "@udl/plugin-source-contentful": "^1.0.0" } }udl.config.ts
.env.example
# Contentful CONTENTFUL_SPACE_ID= CONTENTFUL_ACCESS_TOKEN= CONTENTFUL_ENVIRONMENT=masterPackage Structure
Acceptance Criteria
npx create-udl-app my-appworks interactivelynpx create-udl-app my-app --framework=nextjs --source=contentfulworksnpm install && npm run dev@udl/adapter-nextjspackage created withudl-nextCLIFuture Enhancements
Related
@udl/adapter-nextjs