render-create 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +207 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.js +45 -0
- package/dist/commands/check.d.ts +8 -0
- package/dist/commands/check.js +96 -0
- package/dist/commands/init.d.ts +12 -0
- package/dist/commands/init.js +1201 -0
- package/dist/commands/sync.d.ts +8 -0
- package/dist/commands/sync.js +126 -0
- package/dist/types.d.ts +246 -0
- package/dist/types.js +4 -0
- package/dist/utils.d.ts +53 -0
- package/dist/utils.js +142 -0
- package/package.json +65 -0
- package/templates/LINTING_SETUP.md +205 -0
- package/templates/README_TEMPLATE.md +68 -0
- package/templates/STYLE_GUIDE.md +241 -0
- package/templates/assets/favicon.png +0 -0
- package/templates/assets/favicon.svg +17 -0
- package/templates/biome.json +43 -0
- package/templates/cursor/rules/drizzle.mdc +165 -0
- package/templates/cursor/rules/fastify.mdc +132 -0
- package/templates/cursor/rules/general.mdc +112 -0
- package/templates/cursor/rules/nextjs.mdc +89 -0
- package/templates/cursor/rules/python.mdc +89 -0
- package/templates/cursor/rules/react.mdc +200 -0
- package/templates/cursor/rules/sqlalchemy.mdc +205 -0
- package/templates/cursor/rules/tailwind.mdc +139 -0
- package/templates/cursor/rules/typescript.mdc +112 -0
- package/templates/cursor/rules/vite.mdc +169 -0
- package/templates/cursor/rules/workflows.mdc +349 -0
- package/templates/docker-compose.example.yml +55 -0
- package/templates/drizzle/db-index.ts +15 -0
- package/templates/drizzle/drizzle.config.ts +10 -0
- package/templates/drizzle/schema.ts +12 -0
- package/templates/env.example +15 -0
- package/templates/fastapi/app/__init__.py +1 -0
- package/templates/fastapi/app/config.py +12 -0
- package/templates/fastapi/app/database.py +16 -0
- package/templates/fastapi/app/models.py +13 -0
- package/templates/fastapi/main.py +22 -0
- package/templates/fastify/index.ts +40 -0
- package/templates/github/CODEOWNERS +10 -0
- package/templates/github/ISSUE_TEMPLATE/bug_report.md +39 -0
- package/templates/github/ISSUE_TEMPLATE/feature_request.md +23 -0
- package/templates/github/PULL_REQUEST_TEMPLATE.md +25 -0
- package/templates/gitignore/node.gitignore +41 -0
- package/templates/gitignore/python.gitignore +49 -0
- package/templates/multi-api/README.md +60 -0
- package/templates/multi-api/gitignore +28 -0
- package/templates/multi-api/node-api/drizzle.config.ts +10 -0
- package/templates/multi-api/node-api/package-simple.json +13 -0
- package/templates/multi-api/node-api/package.json +16 -0
- package/templates/multi-api/node-api/src/db/index.ts +13 -0
- package/templates/multi-api/node-api/src/db/schema.ts +9 -0
- package/templates/multi-api/node-api/src/index-simple.ts +36 -0
- package/templates/multi-api/node-api/src/index.ts +50 -0
- package/templates/multi-api/node-api/tsconfig.json +20 -0
- package/templates/multi-api/python-api/app/__init__.py +1 -0
- package/templates/multi-api/python-api/app/config.py +12 -0
- package/templates/multi-api/python-api/app/database.py +16 -0
- package/templates/multi-api/python-api/app/models.py +13 -0
- package/templates/multi-api/python-api/main-simple.py +25 -0
- package/templates/multi-api/python-api/main.py +44 -0
- package/templates/multi-api/python-api/requirements-simple.txt +3 -0
- package/templates/multi-api/python-api/requirements.txt +8 -0
- package/templates/next/globals.css +126 -0
- package/templates/next/layout.tsx +34 -0
- package/templates/next/next.config.static.ts +10 -0
- package/templates/next/page-fullstack.tsx +120 -0
- package/templates/next/page.tsx +72 -0
- package/templates/presets.json +581 -0
- package/templates/ruff.toml +30 -0
- package/templates/tsconfig.base.json +17 -0
- package/templates/vite/index.css +127 -0
- package/templates/vite/vite.config.ts +7 -0
- package/templates/worker/py/cron.py +53 -0
- package/templates/worker/py/worker.py +95 -0
- package/templates/worker/py/workflow.py +73 -0
- package/templates/worker/ts/cron.ts +49 -0
- package/templates/worker/ts/worker.ts +84 -0
- package/templates/worker/ts/workflow.ts +67 -0
package/README.md
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# render-create
|
|
2
|
+
|
|
3
|
+
CLI tool to scaffold Render projects with Cursor rules, linting configs, and templates. Supports both preset-based and composable project creation.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx render-create my-app
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
That's it. You'll get an interactive prompt to choose your stack, and a fully configured project ready to deploy.
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- **One command setup** - Go from zero to deployed in minutes
|
|
16
|
+
- **Infrastructure as Code** - Auto-generated `render.yaml` Blueprint
|
|
17
|
+
- **AI-ready** - Cursor rules for intelligent code assistance
|
|
18
|
+
- **Modern stacks** - Next.js, Fastify, FastAPI, and more
|
|
19
|
+
- **Composable** - Mix frontends, APIs, workers, and databases
|
|
20
|
+
- **Best practices** - Linting, TypeScript, and sensible defaults
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Interactive mode (recommended)
|
|
26
|
+
npx render-create my-app
|
|
27
|
+
|
|
28
|
+
# Use a preset directly
|
|
29
|
+
npx render-create my-app --preset fastify-api
|
|
30
|
+
|
|
31
|
+
# Composable mode - pick your own stack
|
|
32
|
+
npx render-create my-app --composable
|
|
33
|
+
|
|
34
|
+
# Keep existing project rules in sync
|
|
35
|
+
npx render-create sync
|
|
36
|
+
|
|
37
|
+
# Check if rules are up to date (CI-friendly)
|
|
38
|
+
npx render-create check --ci
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Available Presets
|
|
42
|
+
|
|
43
|
+
| Preset | Stack | Database |
|
|
44
|
+
| ---------------- | ------------------------------ | ---------- |
|
|
45
|
+
| `next-fullstack` | Next.js + Tailwind + Drizzle | PostgreSQL |
|
|
46
|
+
| `next-frontend` | Next.js + Tailwind (static) | - |
|
|
47
|
+
| `vite-spa` | Vite + React + Tailwind | - |
|
|
48
|
+
| `fastify-api` | Fastify + Drizzle + Zod | PostgreSQL |
|
|
49
|
+
| `fastapi` | FastAPI + SQLAlchemy | PostgreSQL |
|
|
50
|
+
| `multi-api` | Fastify + FastAPI side-by-side | - |
|
|
51
|
+
|
|
52
|
+
## Composable Mode
|
|
53
|
+
|
|
54
|
+
Build exactly what you need by mixing components:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
npx render-create my-app --composable
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Frontends
|
|
61
|
+
|
|
62
|
+
- **Next.js** - React framework with App Router
|
|
63
|
+
- **Vite** - Fast React SPA
|
|
64
|
+
|
|
65
|
+
### APIs
|
|
66
|
+
|
|
67
|
+
- **Fastify** - Node.js with Drizzle ORM
|
|
68
|
+
- **FastAPI** - Python with SQLAlchemy
|
|
69
|
+
|
|
70
|
+
### Workers
|
|
71
|
+
|
|
72
|
+
- **Background workers** - TypeScript or Python
|
|
73
|
+
- **Cron jobs** - Scheduled tasks
|
|
74
|
+
- **Workflows** - Render Workflows with SDK
|
|
75
|
+
|
|
76
|
+
### Infrastructure
|
|
77
|
+
|
|
78
|
+
- **PostgreSQL** - Managed database
|
|
79
|
+
- **Redis** - Managed cache
|
|
80
|
+
|
|
81
|
+
## What You Get
|
|
82
|
+
|
|
83
|
+
Every project includes:
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
my-app/
|
|
87
|
+
├── src/ # Your application code
|
|
88
|
+
├── .cursor/rules/ # AI coding assistance rules
|
|
89
|
+
├── render.yaml # Infrastructure as Code
|
|
90
|
+
├── biome.json / ruff.toml # Linting configuration
|
|
91
|
+
└── package.json # Dependencies
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Render Blueprint
|
|
95
|
+
|
|
96
|
+
The generated `render.yaml` defines your entire infrastructure:
|
|
97
|
+
|
|
98
|
+
```yaml
|
|
99
|
+
services:
|
|
100
|
+
- type: web
|
|
101
|
+
name: my-app
|
|
102
|
+
runtime: node
|
|
103
|
+
buildCommand: npm install && npm run build
|
|
104
|
+
startCommand: npm start
|
|
105
|
+
healthCheckPath: /health
|
|
106
|
+
envVars:
|
|
107
|
+
- key: DATABASE_URL
|
|
108
|
+
fromDatabase:
|
|
109
|
+
name: my-app-db
|
|
110
|
+
property: connectionString
|
|
111
|
+
|
|
112
|
+
databases:
|
|
113
|
+
- name: my-app-db
|
|
114
|
+
postgresMajorVersion: 16
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Cursor Rules
|
|
118
|
+
|
|
119
|
+
AI-assisted development with framework-specific guidance:
|
|
120
|
+
|
|
121
|
+
| Rule | Description |
|
|
122
|
+
| ---------------- | -------------------------------- |
|
|
123
|
+
| `general.mdc` | Project conventions and patterns |
|
|
124
|
+
| `typescript.mdc` | TypeScript best practices |
|
|
125
|
+
| `react.mdc` | React and component patterns |
|
|
126
|
+
| `nextjs.mdc` | Next.js App Router conventions |
|
|
127
|
+
| `fastify.mdc` | Fastify API patterns |
|
|
128
|
+
| `drizzle.mdc` | Drizzle ORM usage |
|
|
129
|
+
| `workflows.mdc` | Render Workflows SDK |
|
|
130
|
+
|
|
131
|
+
## Deploy to Render
|
|
132
|
+
|
|
133
|
+
After scaffolding, deploy in one click:
|
|
134
|
+
|
|
135
|
+
[](https://render.com/deploy)
|
|
136
|
+
|
|
137
|
+
Or connect your repo to Render and it will automatically detect the `render.yaml` Blueprint.
|
|
138
|
+
|
|
139
|
+
## Commands
|
|
140
|
+
|
|
141
|
+
### `render-create [name]`
|
|
142
|
+
|
|
143
|
+
Create a new project. If no name is provided, you'll be prompted.
|
|
144
|
+
|
|
145
|
+
Options:
|
|
146
|
+
|
|
147
|
+
- `-p, --preset <name>` - Use a preset (skip prompts)
|
|
148
|
+
- `-c, --composable` - Enable composable mode
|
|
149
|
+
- `-y, --yes` - Accept defaults
|
|
150
|
+
|
|
151
|
+
### `render-create sync`
|
|
152
|
+
|
|
153
|
+
Update Cursor rules to the latest version.
|
|
154
|
+
|
|
155
|
+
Options:
|
|
156
|
+
|
|
157
|
+
- `-f, --force` - Overwrite without prompting
|
|
158
|
+
- `--dry-run` - Preview changes
|
|
159
|
+
|
|
160
|
+
### `render-create check`
|
|
161
|
+
|
|
162
|
+
Verify rules are in sync.
|
|
163
|
+
|
|
164
|
+
Options:
|
|
165
|
+
|
|
166
|
+
- `--ci` - Exit code 1 if out of sync
|
|
167
|
+
|
|
168
|
+
## Contributing
|
|
169
|
+
|
|
170
|
+
We welcome contributions!
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
# Clone and setup
|
|
174
|
+
git clone https://github.com/R4ph-t/render-create-demo.git
|
|
175
|
+
cd render-create-demo
|
|
176
|
+
npm install
|
|
177
|
+
|
|
178
|
+
# Build and test
|
|
179
|
+
npm run build
|
|
180
|
+
npm test
|
|
181
|
+
|
|
182
|
+
# Test locally
|
|
183
|
+
npm link
|
|
184
|
+
render-create my-test-app
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Releases
|
|
188
|
+
|
|
189
|
+
To create a new release:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
npm run release:patch # 1.0.0 → 1.0.1
|
|
193
|
+
npm run release:minor # 1.0.0 → 1.1.0
|
|
194
|
+
npm run release:major # 1.0.0 → 2.0.0
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
This will automatically:
|
|
198
|
+
1. Run lint, build, and tests
|
|
199
|
+
2. Bump the version in `package.json`
|
|
200
|
+
3. Create a git commit and tag
|
|
201
|
+
4. Push to GitHub
|
|
202
|
+
|
|
203
|
+
GitHub Actions will then create a release with auto-generated release notes.
|
|
204
|
+
|
|
205
|
+
## License
|
|
206
|
+
|
|
207
|
+
MIT - see [LICENSE](LICENSE) for details.
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* create-render-app CLI
|
|
4
|
+
* Scaffold and deploy applications on Render with best practices
|
|
5
|
+
*/
|
|
6
|
+
import { program } from "commander";
|
|
7
|
+
import { check } from "./commands/check.js";
|
|
8
|
+
import { init } from "./commands/init.js";
|
|
9
|
+
import { sync } from "./commands/sync.js";
|
|
10
|
+
program
|
|
11
|
+
.name("render-create")
|
|
12
|
+
.description("Scaffold and deploy applications on Render with best practices")
|
|
13
|
+
.version("0.1.0");
|
|
14
|
+
// Default command: create a new project
|
|
15
|
+
program
|
|
16
|
+
.argument("[name]", "Project name (creates a new directory)")
|
|
17
|
+
.option("-p, --preset <preset>", "Use a specific preset (skip prompts)")
|
|
18
|
+
.option("-c, --composable", "Enable composable mode")
|
|
19
|
+
.option("-y, --yes", "Accept all defaults")
|
|
20
|
+
.option("--skip-install", "Skip package installation")
|
|
21
|
+
.action(init);
|
|
22
|
+
// Explicit init command (alternative syntax)
|
|
23
|
+
program
|
|
24
|
+
.command("init")
|
|
25
|
+
.description("Scaffold a new project (same as default command)")
|
|
26
|
+
.argument("[name]", "Project name (creates a new directory)")
|
|
27
|
+
.option("-p, --preset <preset>", "Use a specific preset (skip prompts)")
|
|
28
|
+
.option("-c, --composable", "Enable composable mode")
|
|
29
|
+
.option("-y, --yes", "Accept all defaults")
|
|
30
|
+
.option("--skip-install", "Skip package installation")
|
|
31
|
+
.action(init);
|
|
32
|
+
// Sync command
|
|
33
|
+
program
|
|
34
|
+
.command("sync")
|
|
35
|
+
.description("Update local Cursor rules to the latest version")
|
|
36
|
+
.option("-f, --force", "Overwrite without prompting")
|
|
37
|
+
.option("--dry-run", "Show changes without applying them")
|
|
38
|
+
.action(sync);
|
|
39
|
+
// Check command
|
|
40
|
+
program
|
|
41
|
+
.command("check")
|
|
42
|
+
.description("Verify Cursor rules are up to date")
|
|
43
|
+
.option("--ci", "Exit with code 1 if out of sync (for CI)")
|
|
44
|
+
.action(check);
|
|
45
|
+
program.parse();
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check command - Verify if local rules are up to date
|
|
3
|
+
*/
|
|
4
|
+
import { existsSync, readdirSync } from "node:fs";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
import { compareFiles, getTargetDir, TEMPLATES_DIR } from "../utils.js";
|
|
8
|
+
/**
|
|
9
|
+
* Main check command handler
|
|
10
|
+
*/
|
|
11
|
+
export async function check(options) {
|
|
12
|
+
const targetDir = getTargetDir();
|
|
13
|
+
const rulesDir = join(targetDir, ".cursor", "rules");
|
|
14
|
+
let inSync = 0;
|
|
15
|
+
let outOfSync = 0;
|
|
16
|
+
const _missing = 0;
|
|
17
|
+
let custom = 0;
|
|
18
|
+
console.log(chalk.blue("Checking cursor-rules status...\n"));
|
|
19
|
+
// Check rule files
|
|
20
|
+
if (existsSync(rulesDir)) {
|
|
21
|
+
const files = readdirSync(rulesDir);
|
|
22
|
+
for (const file of files) {
|
|
23
|
+
if (!file.endsWith(".mdc")) {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const ruleName = file.replace(".mdc", "");
|
|
27
|
+
const templatePath = `cursor/rules/${ruleName}.mdc`;
|
|
28
|
+
const targetPath = join(rulesDir, file);
|
|
29
|
+
// Check if template exists
|
|
30
|
+
if (!existsSync(join(TEMPLATES_DIR, templatePath))) {
|
|
31
|
+
console.log(chalk.gray(` ${file} - custom rule`));
|
|
32
|
+
custom++;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const result = compareFiles(templatePath, targetPath);
|
|
36
|
+
if (result.status === "in-sync") {
|
|
37
|
+
console.log(chalk.green(` ${file} - up to date`));
|
|
38
|
+
inSync++;
|
|
39
|
+
}
|
|
40
|
+
else if (result.status === "out-of-sync") {
|
|
41
|
+
console.log(chalk.yellow(` ${file} - out of sync`));
|
|
42
|
+
outOfSync++;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
console.log(chalk.yellow(" No .cursor/rules directory found"));
|
|
48
|
+
}
|
|
49
|
+
// Check config files
|
|
50
|
+
const configMappings = [
|
|
51
|
+
{ name: "biome.json", template: "biome.json", target: "biome.json" },
|
|
52
|
+
{ name: "ruff.toml", template: "ruff.toml", target: "ruff.toml" },
|
|
53
|
+
{ name: "tsconfig.base.json", template: "tsconfig.base.json", target: "tsconfig.base.json" },
|
|
54
|
+
];
|
|
55
|
+
for (const config of configMappings) {
|
|
56
|
+
const targetPath = join(targetDir, config.target);
|
|
57
|
+
if (!existsSync(targetPath)) {
|
|
58
|
+
continue; // Skip if not present (might not be needed for this project)
|
|
59
|
+
}
|
|
60
|
+
const result = compareFiles(config.template, targetPath);
|
|
61
|
+
if (result.status === "in-sync") {
|
|
62
|
+
console.log(chalk.green(` ${config.name} - up to date`));
|
|
63
|
+
inSync++;
|
|
64
|
+
}
|
|
65
|
+
else if (result.status === "out-of-sync") {
|
|
66
|
+
console.log(chalk.yellow(` ${config.name} - out of sync`));
|
|
67
|
+
outOfSync++;
|
|
68
|
+
}
|
|
69
|
+
else if (result.status === "template-missing") {
|
|
70
|
+
console.log(chalk.gray(` ${config.name} - custom config`));
|
|
71
|
+
custom++;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Summary
|
|
75
|
+
console.log();
|
|
76
|
+
console.log(chalk.blue("Summary:"));
|
|
77
|
+
console.log(` ${chalk.green(`${inSync} up to date`)}`);
|
|
78
|
+
if (outOfSync > 0) {
|
|
79
|
+
console.log(` ${chalk.yellow(`${outOfSync} out of sync`)}`);
|
|
80
|
+
}
|
|
81
|
+
if (custom > 0) {
|
|
82
|
+
console.log(` ${chalk.gray(`${custom} custom (not tracked)`)}`);
|
|
83
|
+
}
|
|
84
|
+
// Exit with error code if CI mode and out of sync
|
|
85
|
+
if (options.ci && outOfSync > 0) {
|
|
86
|
+
console.log(chalk.red("\nCI check failed: Files are out of sync."));
|
|
87
|
+
console.log(chalk.gray("Run 'npx @render-examples/cursor-rules sync' to update."));
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
if (outOfSync > 0) {
|
|
91
|
+
console.log(chalk.yellow("\nRun 'npx @render-examples/cursor-rules sync' to update."));
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
console.log(chalk.green("\nAll tracked files are up to date!"));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Init command - Scaffold a new project with dependencies, Cursor rules, and configs
|
|
3
|
+
*/
|
|
4
|
+
import type { ComponentsConfig, ComposableSelection, InitOptions } from "../types.js";
|
|
5
|
+
/**
|
|
6
|
+
* Scaffold a composable project with selected components
|
|
7
|
+
*/
|
|
8
|
+
export declare function scaffoldComposableProject(selection: ComposableSelection, components: ComponentsConfig, skipInstall: boolean): Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* Main init command handler
|
|
11
|
+
*/
|
|
12
|
+
export declare function init(nameArg: string | undefined, options: InitOptions): Promise<void>;
|