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.
Files changed (82) hide show
  1. package/README.md +207 -0
  2. package/dist/cli.d.ts +6 -0
  3. package/dist/cli.js +45 -0
  4. package/dist/commands/check.d.ts +8 -0
  5. package/dist/commands/check.js +96 -0
  6. package/dist/commands/init.d.ts +12 -0
  7. package/dist/commands/init.js +1201 -0
  8. package/dist/commands/sync.d.ts +8 -0
  9. package/dist/commands/sync.js +126 -0
  10. package/dist/types.d.ts +246 -0
  11. package/dist/types.js +4 -0
  12. package/dist/utils.d.ts +53 -0
  13. package/dist/utils.js +142 -0
  14. package/package.json +65 -0
  15. package/templates/LINTING_SETUP.md +205 -0
  16. package/templates/README_TEMPLATE.md +68 -0
  17. package/templates/STYLE_GUIDE.md +241 -0
  18. package/templates/assets/favicon.png +0 -0
  19. package/templates/assets/favicon.svg +17 -0
  20. package/templates/biome.json +43 -0
  21. package/templates/cursor/rules/drizzle.mdc +165 -0
  22. package/templates/cursor/rules/fastify.mdc +132 -0
  23. package/templates/cursor/rules/general.mdc +112 -0
  24. package/templates/cursor/rules/nextjs.mdc +89 -0
  25. package/templates/cursor/rules/python.mdc +89 -0
  26. package/templates/cursor/rules/react.mdc +200 -0
  27. package/templates/cursor/rules/sqlalchemy.mdc +205 -0
  28. package/templates/cursor/rules/tailwind.mdc +139 -0
  29. package/templates/cursor/rules/typescript.mdc +112 -0
  30. package/templates/cursor/rules/vite.mdc +169 -0
  31. package/templates/cursor/rules/workflows.mdc +349 -0
  32. package/templates/docker-compose.example.yml +55 -0
  33. package/templates/drizzle/db-index.ts +15 -0
  34. package/templates/drizzle/drizzle.config.ts +10 -0
  35. package/templates/drizzle/schema.ts +12 -0
  36. package/templates/env.example +15 -0
  37. package/templates/fastapi/app/__init__.py +1 -0
  38. package/templates/fastapi/app/config.py +12 -0
  39. package/templates/fastapi/app/database.py +16 -0
  40. package/templates/fastapi/app/models.py +13 -0
  41. package/templates/fastapi/main.py +22 -0
  42. package/templates/fastify/index.ts +40 -0
  43. package/templates/github/CODEOWNERS +10 -0
  44. package/templates/github/ISSUE_TEMPLATE/bug_report.md +39 -0
  45. package/templates/github/ISSUE_TEMPLATE/feature_request.md +23 -0
  46. package/templates/github/PULL_REQUEST_TEMPLATE.md +25 -0
  47. package/templates/gitignore/node.gitignore +41 -0
  48. package/templates/gitignore/python.gitignore +49 -0
  49. package/templates/multi-api/README.md +60 -0
  50. package/templates/multi-api/gitignore +28 -0
  51. package/templates/multi-api/node-api/drizzle.config.ts +10 -0
  52. package/templates/multi-api/node-api/package-simple.json +13 -0
  53. package/templates/multi-api/node-api/package.json +16 -0
  54. package/templates/multi-api/node-api/src/db/index.ts +13 -0
  55. package/templates/multi-api/node-api/src/db/schema.ts +9 -0
  56. package/templates/multi-api/node-api/src/index-simple.ts +36 -0
  57. package/templates/multi-api/node-api/src/index.ts +50 -0
  58. package/templates/multi-api/node-api/tsconfig.json +20 -0
  59. package/templates/multi-api/python-api/app/__init__.py +1 -0
  60. package/templates/multi-api/python-api/app/config.py +12 -0
  61. package/templates/multi-api/python-api/app/database.py +16 -0
  62. package/templates/multi-api/python-api/app/models.py +13 -0
  63. package/templates/multi-api/python-api/main-simple.py +25 -0
  64. package/templates/multi-api/python-api/main.py +44 -0
  65. package/templates/multi-api/python-api/requirements-simple.txt +3 -0
  66. package/templates/multi-api/python-api/requirements.txt +8 -0
  67. package/templates/next/globals.css +126 -0
  68. package/templates/next/layout.tsx +34 -0
  69. package/templates/next/next.config.static.ts +10 -0
  70. package/templates/next/page-fullstack.tsx +120 -0
  71. package/templates/next/page.tsx +72 -0
  72. package/templates/presets.json +581 -0
  73. package/templates/ruff.toml +30 -0
  74. package/templates/tsconfig.base.json +17 -0
  75. package/templates/vite/index.css +127 -0
  76. package/templates/vite/vite.config.ts +7 -0
  77. package/templates/worker/py/cron.py +53 -0
  78. package/templates/worker/py/worker.py +95 -0
  79. package/templates/worker/py/workflow.py +73 -0
  80. package/templates/worker/ts/cron.ts +49 -0
  81. package/templates/worker/ts/worker.ts +84 -0
  82. 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
+ [![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](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
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * create-render-app CLI
4
+ * Scaffold and deploy applications on Render with best practices
5
+ */
6
+ export {};
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,8 @@
1
+ /**
2
+ * Check command - Verify if local rules are up to date
3
+ */
4
+ import type { CheckOptions } from "../types.js";
5
+ /**
6
+ * Main check command handler
7
+ */
8
+ export declare function check(options: CheckOptions): Promise<void>;
@@ -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>;