āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā š shadcn/directory/dodopayments/billingsdk/cli ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā
import { Callout } from 'fumadocs-ui/components/callout' import { Tab, Tabs } from 'fumadocs-ui/components/tabs' import { Cards, Card } from 'fumadocs-ui/components/card'
The Billing SDK CLI is a powerful command-line tool that helps you initialize new billing projects, add components, and manage your billing infrastructure with ease.
The CLI is published as an npm package and can be used with npx without installation:
npx @billingsdk/cli --help
For frequent use, you can install it globally:
npm install -g @billingsdk/cli
@billingsdk/cli --help
# Initialize a project (interactive)
npx @billingsdk/cli init
# Add a component to an existing project
npx @billingsdk/cli add <component-name>
| Framework | Dodo Payments | Stripe | |------------|---------------|---------------| | Next.js | Yes | Yes | | Express.js | Yes | Yes | | Hono | Yes | Yes | | React | Yes | Yes | | Fastify | Yes | Coming soon |
@billingsdk/cli initInitialize a new billing project with complete setup including framework configuration, payment provider integration, and essential dependencies.
npx @billingsdk/cli init
The command launches an interactive setup process:
npx @billingsdk/cli init
You'll be prompted to select:
After running init with Dodo Payments, you'll get:
<Tabs items={['Next.js + Dodo Payments', 'Express.js + Dodo Payments', 'React.js + Dodo Payments', 'Hono + Dodo Payments', 'Fastify + Dodo Payments']}>
<Tab value="Next.js + Dodo Payments">
your-project/ āāā app/api/ ā āāā (dodopayments)/ ā ā āāā checkout/route.ts ā ā āāā customer/route.ts ā ā āāā customer/payments/route.ts ā ā āāā customer/subscriptions/route.ts ā ā āāā product/route.ts ā ā āāā products/route.ts ā ā āāā webhook/route.ts āāā hooks/ ā āāā useBilling.ts āāā lib/ ā āāā dodopayments.ts āāā .env.example
</Tab>
<Tab value="Express.js + Dodo Payments">
your-project/ āāā lib/ ā āāā dodopayments.ts āāā routes/ āāā dodopayments/ āāā route.ts āāā checkout.ts āāā customer.ts āāā payments.ts āāā products.ts āāā subscriptions.ts āāā webhook.ts .env.example
</Tab>
<Tab value="React.js + Dodo Payments">
your-project/ āāā hooks/ ā āāā dodopayments/ ā āāā useBilling.ts āāā lib/ ā āāā dodopayments.ts .env.example
</Tab>
<Tab value="Hono + Dodo Payments">
your-project/ āāā lib/ ā āāā dodopayments.ts āāā routes/ āāā route.ts āāā dodopayments/ āāā checkout.ts āāā customer.ts āāā payments.ts āāā products.ts āāā subscriptions.ts āāā webhook.ts .env.example
</Tab>
<Tab value="Fastify + Dodo Payments">
your-project/ āāā lib/ ā āāā dodopayments.ts āāā routes/ āāā dodopayments/ āāā route.ts āāā checkout.ts āāā customer.ts āāā payments.ts āāā products.ts āāā subscriptions.ts āāā webhook.ts .env.example
</Tab>
</Tabs>
After running init with Stripe, you'll get:
<Tabs items={['Next.js + Stripe', 'React.js + Stripe', 'Express.js + Stripe', 'Hono + Stripe']}>
<Tab value="Next.js + Stripe">
your-project/ āāā app/api/ ā āāā (stripe)/ ā āāā checkout ā āāā customer ā āāā payments ā āāā products ā āāā subscriptions ā āāā webhook āāā hooks/ ā āāā useBilling.ts āāā lib/ ā āāā stripe.ts .env.example
</Tab>
<Tab value="React.js + Stripe">
your-project/ āāā hooks/ ā āāā stripe/ ā āāā useBilling.ts āāā lib/ ā āāā stripe.ts .env.example
</Tab>
<Tab value="Express.js + Stripe">
your-project/ āāā lib/ ā āāā stripe.ts āāā routes/ āāā stripe/ āāā route.ts āāā checkout.ts āāā customer.ts āāā payments.ts āāā products.ts āāā subscriptions.ts āāā webhook.ts .env.example
</Tab>
<Tab value="Hono + Stripe">
your-project/ āāā lib/ ā āāā stripe.ts āāā routes/ āāā route.ts āāā stripe/ āāā checkout.ts āāā customer.ts āāā payments.ts āāā products.ts āāā subscriptions.ts āāā webhook.ts .env.example
</Tab>
</Tabs>
The init command sets up comprehensive API routes for:
After running @billingsdk/cli init and selecting Next.js, the CLI scaffolds API routes under app/api/(dodopayments)/* and adds lib/dodopayments.ts and hooks/useBilling.ts.
hooks/useBilling.ts.Copy .env.example to .env.local in the project root and set:
# DodoPayments
DODO_PAYMENTS_API_KEY=your_api_key_here
DODO_PAYMENTS_ENVIRONMENT=test_mode
DODO_PAYMENTS_WEBHOOK_KEY=your_webhook_key_here
# App URL
NEXT_PUBLIC_APP_URL=http://localhost:3000
// app/(or any client component)
"use client"
import { useEffect } from 'react'
import { useBilling } from "@/app/hooks/useBilling"
export default function BillingExample() {
const { fetchProducts } = useBilling()
useEffect(() => {
fetchProducts().catch(console.error)
}, [fetchProducts])
return null
}
</details>
<details>
<summary><strong>Express.js Setup Instructions</strong></summary>
After running @billingsdk/cli init and selecting Express.js, you'll need to integrate the generated routes into your Express application:
// app.js or server.js
const express = require('express');
const { dodopaymentsRouter } = require('./src/routes/dodopayments/route');
const app = express();
// Middleware
app.use(express.json());
// Mount DodoPayments routes
app.use('/api/dodopayments', dodopaymentsRouter);
// Start server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Create a .env file in your project root:
# DodoPayments Configuration
DODO_PAYMENTS_API_KEY=your_api_key_here
DODO_PAYMENTS_ENVIRONMENT=test_mode
DODO_PAYMENTS_WEBHOOK_KEY=your_webhook_key_here
# Server Configuration
PORT=3000
NODE_ENV=development
The template includes full TypeScript support. To use with TypeScript:
npm install -D typescript @types/node ts-node nodemon
Create a tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"lib": ["ES2020"],
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
Update your package.json scripts:
{
"scripts": {
"dev": "nodemon --exec ts-node src/app.ts",
"build": "tsc",
"start": "node dist/app.js"
}
}
</details>
<details>
<summary><strong>Hono Setup Instructions</strong></summary>
After running @billingsdk/cli init and selecting Hono, you'll need to integrate the generated routes into your Hono application:
// src/index.ts
import { Hono } from 'hono'
import { dodopaymentsRouter } from './routes/route'
const app = new Hono()
// Mount DodoPayments routes
app.route('/api/dodopayments', dodopaymentsRouter)
// Start server
export default app
Create a .env file in your project root:
# DodoPayments Configuration
DODO_PAYMENTS_API_KEY=your_api_key_here
DODO_PAYMENTS_ENVIRONMENT=test_mode
DODO_PAYMENTS_WEBHOOK_KEY=your_webhook_key_here
# Server Configuration
PORT=3000
Hono works great with Bun. To run your application:
Add this to your package.json scripts:
{
"scripts": {
"dev": "bun run --hot src/routes/route.ts"
}
}
</details>
<details>
<summary><strong>React.js Setup Instructions</strong></summary>
After running @billingsdk/cli init and selecting React.js, the CLI generates a lib/dodopayments.ts and a hooks/useBilling.ts file for your project.
You can use the useBilling hook directly in your components to interact with the backend API:
// src/App.tsx or any component
import React, { useEffect } from 'react'
import { useBilling } from './hooks/useBilling'
function App() {
const { fetchProducts, loading, error } = useBilling()
useEffect(() => {
const loadProducts = async () => {
try {
const products = await fetchProducts()
console.log('Products:', products)
} catch (err) {
console.error('Failed to fetch products:', err)
}
}
loadProducts()
}, [fetchProducts])
if (loading) return <p>Loading...</p>
if (error) return <p style={{ color: 'red' }}>{error}</p>
return <h1>Welcome to DodoPayments + React</h1>
}
export default App
Create a .env (or .env.local if using Vite) in your project root:
# Backend API URL (Express.js server or Next.js API routes)
VITE_BASE_URL=http://localhost:3000
</details>
<details>
<summary><strong>Fastify Setup Instructions</strong></summary>
After running @billingsdk/cli init and selecting Fastify, integrate the generated routes into your Fastify application.
// src/index.ts
import Fastify from 'fastify'
import cors from '@fastify/cors'
import helmet from '@fastify/helmet'
import { dodopaymentsRoutes } from './routes/dodopayments/route'
const app = Fastify({ logger: true })
// Plugins (optional but recommended)
await app.register(cors)
await app.register(helmet)
// Mount DodoPayments routes
app.register(dodopaymentsRoutes, { prefix: '/api/dodopayments' })
const start = async () => {
try {
const port = Number(process.env.PORT) || 3000
await app.listen({ port, host: '0.0.0.0' })
app.log.info(`Server running on port ${port}`)
} catch (err) {
app.log.error(err)
process.exit(1)
}
}
start()
Create a .env file in your project root:
# DodoPayments Configuration
DODO_PAYMENTS_API_KEY=your_api_key_here
DODO_PAYMENTS_ENVIRONMENT=test_mode
DODO_PAYMENTS_WEBHOOK_KEY=your_webhook_key_here
# Server Configuration
PORT=3000
{
"scripts": {
"dev": "tsx watch src/server.ts",
"build": "tsc",
"start": "node dist/server.js"
}
}
</details>
<Tabs items={['Next.js', 'Express.js', 'React.js', 'Hono', 'Fastify']}>
<Tab value="Next.js">
json { "dependencies": { "dodopayments": "latest", "standardwebhooks": "latest", "zod": "latest" } }
</Tab>
<Tab value="Express.js">
json { "dependencies": { "dodopayments": "latest", "standardwebhooks": "latest", "zod": "latest", "express": "latest", "@types/express": "latest" } }
</Tab>
<Tab value="React.js">
json { "dependencies": { "dodopayments": "latest" } }
</Tab>
<Tab value="Hono">
json { "dependencies": { "dodopayments": "latest", "standardwebhooks": "latest", "zod": "latest", "hono": "latest", "@types/bun": "latest" } }
</Tab>
<Tab value="Fastify">
json { "dependencies": { "dodopayments": "latest", "standardwebhooks": "latest", "zod": "latest", "fastify": "latest", "fastify-raw-body": "latest" } }
</Tab>
</Tabs>
<Tabs items={['Express.js', 'Hono']}>
<Tab value="Express.js">
json { "dependencies": { "stripe": "latest", "standardwebhooks": "latest", "zod": "latest", "express": "latest", "@types/express": "latest" } }
</Tab>
<Tab value="Hono">
json { "dependencies": { "stripe": "latest", "standardwebhooks": "latest", "zod": "latest", "hono": "latest", "@types/bun": "latest" } }
</Tab>
</Tabs>
@billingsdk/cli addAdd individual billing components to your existing project using the shadcn/ui registry system.
npx @billingsdk/cli add <component-name>
See the components page for a list of available components.
# Add a pricing table
npx @billingsdk/cli add pricing-table-one
# Add subscription management
npx @billingsdk/cli add subscription-management
# Add usage monitoring
npx @billingsdk/cli add usage-meter-circle
components/billingsdk/ directoryCommand not found
# Make sure you're using npx
npx @billingsdk/cli --help
Permission errors
# On Unix systems, you might need to adjust permissions
chmod +x node_modules/.bin/@billingsdk/cli
Network issues
# Check your internet connection
# The CLI downloads templates from @billingsdk/cli.com
# Show all available commands
npx @billingsdk/cli --help
# Get help for a specific command
npx @billingsdk/cli init --help
npx @billingsdk/cli add --help
cd packages/cli
npm run build
cd packages/cli
npm run dev
The CLI is open source and welcomes contributions. See our contribution guide for details.
<Callout title="Need Help?"> If you encounter issues or have questions about the CLI, please [open an issue](https://github.com/dodopayments/billingsdk/issues) on GitHub. </Callout>ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā