From 1d24342e1d4f790037cb455f254b525dae64f12b Mon Sep 17 00:00:00 2001 From: meenu155 Date: Sat, 15 Nov 2025 11:25:22 +0530 Subject: [PATCH 1/7] feat: extend service type options to include remix, astro, and sveltekit --- bin/index.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/bin/index.js b/bin/index.js index ea73f0a..3116051 100755 --- a/bin/index.js +++ b/bin/index.js @@ -55,7 +55,7 @@ program .description('Add a new service or plugin') .argument('', 'service | plugin') .argument('', 'Name of the service or plugin') - .option('--type ', 'Service type (node|python|go|java|frontend)') + .option('--type ', 'Service type (node|python|go|java|frontend|remix|astro|sveltekit)') .option('--lang ', '(Deprecated) Alias of --type') .option('--port ', 'Service port') .option('--yes', 'Non-interactive defaults') @@ -74,7 +74,10 @@ program { title: 'Python', value: 'python' }, { title: 'Go', value: 'go' }, { title: 'Java', value: 'java' }, - { title: 'Frontend (Next.js)', value: 'frontend' } + { title: 'Frontend (Next.js)', value: 'frontend' }, + { title: 'Remix', value: 'remix' }, + { title: 'Astro', value: 'astro' }, + { title: 'SvelteKit', value: 'sveltekit' } ] }); type = ans.type; } @@ -83,7 +86,7 @@ program if (ans.port) port = Number(ans.port); } } - const defaultPorts = { frontend: 3000, node: 3001, go: 3002, java: 3003, python: 3004 }; + const defaultPorts = { frontend: 3000, node: 3001, go: 3002, java: 3003, python: 3004, remix: 3005, astro: 3006, sveltekit: 3007 }; if (!type) throw new Error('Service type required'); if (!port) port = defaultPorts[type]; await addService(projectDir, { type, name, port }, opts); From 8aed786d615430c76664195aa0e20a2fdfb68212 Mon Sep 17 00:00:00 2001 From: meenu155 Date: Sat, 15 Nov 2025 11:25:39 +0530 Subject: [PATCH 2/7] feat: add support for Remix, Astro, and SvelteKit service types with corresponding generators --- bin/lib/scaffold.js | 76 ++++++++++++++++++++++++++++++++------------- 1 file changed, 54 insertions(+), 22 deletions(-) diff --git a/bin/lib/scaffold.js b/bin/lib/scaffold.js index e7a3542..8424bae 100644 --- a/bin/lib/scaffold.js +++ b/bin/lib/scaffold.js @@ -139,12 +139,15 @@ export async function scaffoldMonorepo(projectNameArg, options) { { title: 'Python (FastAPI)', value: 'python' }, { title: 'Go (Fiber-like)', value: 'go' }, { title: 'Java (Spring Boot)', value: 'java' }, - { title: 'Frontend (Next.js)', value: 'frontend' } + { title: 'Frontend (Next.js)', value: 'frontend' }, + { title: 'Remix', value: 'remix' }, + { title: 'Astro', value: 'astro' }, + { title: 'SvelteKit', value: 'sveltekit' } ]; const templateMap = { java: 'spring-boot' }; let services = []; const reservedNames = new Set(['scripts','packages','apps','node_modules','docker','compose','compose.yaml']); - const defaultPorts = { frontend: 3000, node: 3001, go: 3002, java: 3003, python: 3004 }; + const defaultPorts = { frontend: 3000, node: 3001, go: 3002, java: 3003, python: 3004, remix: 3005, astro: 3006, sveltekit: 3007 }; if (options.services) { const validValues = allServiceChoices.map(c => c.value); @@ -330,29 +333,58 @@ export async function scaffoldMonorepo(projectNameArg, options) { console.log(chalk.yellow(`⚠️ create-next-app failed: ${e.message}. Using template.`)); } } + // Strict external generators for new frameworks: abort on failure (no internal fallback yet) + if (svcType === 'remix') { + try { + console.log(chalk.cyan('⚙️ Running Remix generator (create-remix)...')); + await execa('npx', ['--yes', 'create-remix@latest', '.', '--template', 'remix'], { cwd: dest, stdio: 'inherit' }); + usedGenerator = true; + } catch (e) { + console.error(chalk.red(`❌ create-remix failed: ${e.message}. Aborting scaffold for this service.`)); + continue; // skip creating this service + } + } else if (svcType === 'astro') { + try { + console.log(chalk.cyan('⚙️ Running Astro generator (create-astro)...')); + await execa('npx', ['--yes', 'create-astro@latest', '--', '--template', 'minimal'], { cwd: dest, stdio: 'inherit' }); + usedGenerator = true; + } catch (e) { + console.error(chalk.red(`❌ create-astro failed: ${e.message}. Aborting scaffold for this service.`)); + continue; + } + } else if (svcType === 'sveltekit') { + try { + console.log(chalk.cyan('⚙️ Running SvelteKit generator (create-svelte)...')); + await execa('npx', ['--yes', 'create-svelte@latest', '.', '--template', 'skeleton'], { cwd: dest, stdio: 'inherit' }); + usedGenerator = true; + } catch (e) { + console.error(chalk.red(`❌ create-svelte failed: ${e.message}. Aborting scaffold for this service.`)); + continue; + } + } if (!usedGenerator) { - if (await fs.pathExists(src) && (await fs.readdir(src)).length > 0) { - await fs.copy(src, dest, { overwrite: true }); - - // Dynamically update the name field in package.json for Node.js services - if (svcType === 'node') { - const packageJsonPath = path.join(dest, 'package.json'); - if (await fs.pathExists(packageJsonPath)) { - const packageJson = await fs.readJSON(packageJsonPath); - packageJson.name = `@${projectNameArg || 'polyglot'}/${svcName}`; // Ensure unique name - await fs.writeJSON(packageJsonPath, packageJson, { spaces: 2 }); + // Non-framework services use internal templates + if (svcType !== 'remix' && svcType !== 'astro' && svcType !== 'sveltekit') { + if (await fs.pathExists(src) && (await fs.readdir(src)).length > 0) { + await fs.copy(src, dest, { overwrite: true }); + if (svcType === 'node') { + const packageJsonPath = path.join(dest, 'package.json'); + if (await fs.pathExists(packageJsonPath)) { + const packageJson = await fs.readJSON(packageJsonPath); + packageJson.name = `@${projectNameArg || 'polyglot'}/${svcName}`; + await fs.writeJSON(packageJsonPath, packageJson, { spaces: 2 }); + } } - } - - if (templateFolder === 'spring-boot') { - const propTxt = path.join(dest, 'src/main/resources/application.properties.txt'); - const prop = path.join(dest, 'src/main/resources/application.properties'); - if (await fs.pathExists(propTxt) && !(await fs.pathExists(prop))) { - await fs.move(propTxt, prop); + if (templateFolder === 'spring-boot') { + const propTxt = path.join(dest, 'src/main/resources/application.properties.txt'); + const prop = path.join(dest, 'src/main/resources/application.properties'); + if (await fs.pathExists(propTxt) && !(await fs.pathExists(prop))) { + await fs.move(propTxt, prop); + } } + } else { + await fs.writeFile(path.join(dest, 'README.md'), `# ${svcName} service\n\nScaffolded by create-polyglot.`); } - } else { - await fs.writeFile(path.join(dest, 'README.md'), `# ${svcName} service\n\nScaffolded by create-polyglot.`); } } @@ -444,7 +476,7 @@ export async function scaffoldMonorepo(projectNameArg, options) { const dockerfile = path.join(svcDir, 'Dockerfile'); if (!(await fs.pathExists(dockerfile))) { let dockerContent = ''; - if (svcObj.type === 'node' || svcObj.type === 'frontend') { + if (svcObj.type === 'node' || svcObj.type === 'frontend' || ['remix','astro','sveltekit'].includes(svcObj.type)) { dockerContent = `# ${svcObj.name} (${svcObj.type}) service\nFROM node:20-alpine AS deps\nWORKDIR /app\nCOPY package*.json ./\nRUN npm install --omit=dev || true\nCOPY . .\nEXPOSE ${port}\nCMD [\"npm\", \"run\", \"dev\"]\n`; } else if (svcObj.type === 'python') { dockerContent = `FROM python:3.12-slim\nWORKDIR /app\nCOPY requirements.txt ./\nRUN pip install --no-cache-dir -r requirements.txt\nCOPY . .\nEXPOSE ${port}\nCMD [\"uvicorn\", \"app.main:app\", \"--host\", \"0.0.0.0\", \"--port\", \"${port}\"]\n`; From deb13fdd71997664a7e73346f2404592f54642a8 Mon Sep 17 00:00:00 2001 From: meenu155 Date: Sat, 15 Nov 2025 12:03:15 +0530 Subject: [PATCH 3/7] issue fixed --- bin/lib/scaffold.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/lib/scaffold.js b/bin/lib/scaffold.js index 8424bae..332c7b3 100644 --- a/bin/lib/scaffold.js +++ b/bin/lib/scaffold.js @@ -336,11 +336,11 @@ export async function scaffoldMonorepo(projectNameArg, options) { // Strict external generators for new frameworks: abort on failure (no internal fallback yet) if (svcType === 'remix') { try { - console.log(chalk.cyan('⚙️ Running Remix generator (create-remix)...')); - await execa('npx', ['--yes', 'create-remix@latest', '.', '--template', 'remix'], { cwd: dest, stdio: 'inherit' }); + console.log(chalk.cyan('⚙️ Running Remix generator (create-react-router with basic template)...')); + await execa('npx', ['--yes', 'create-react-router@latest', '.', '--template', 'remix-run/react-router/examples/basic', '--no-git-init', '--no-install'], { cwd: dest, stdio: 'inherit' }); usedGenerator = true; } catch (e) { - console.error(chalk.red(`❌ create-remix failed: ${e.message}. Aborting scaffold for this service.`)); + console.error(chalk.red(`❌ create-react-router failed: ${e.message}. Aborting scaffold for this service.`)); continue; // skip creating this service } } else if (svcType === 'astro') { From 1faace653a0e7397b1184235b3d17fc708644422 Mon Sep 17 00:00:00 2001 From: meenu155 Date: Sat, 15 Nov 2025 12:12:12 +0530 Subject: [PATCH 4/7] feat: update Astro and SvelteKit generator commands for improved scaffolding --- bin/lib/scaffold.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bin/lib/scaffold.js b/bin/lib/scaffold.js index 332c7b3..39e3206 100644 --- a/bin/lib/scaffold.js +++ b/bin/lib/scaffold.js @@ -346,7 +346,7 @@ export async function scaffoldMonorepo(projectNameArg, options) { } else if (svcType === 'astro') { try { console.log(chalk.cyan('⚙️ Running Astro generator (create-astro)...')); - await execa('npx', ['--yes', 'create-astro@latest', '--', '--template', 'minimal'], { cwd: dest, stdio: 'inherit' }); + await execa('npx', ['--yes', 'create-astro@latest', '.', '--template', 'minimal', '--no-install', '--no-git'], { cwd: dest, stdio: 'inherit' }); usedGenerator = true; } catch (e) { console.error(chalk.red(`❌ create-astro failed: ${e.message}. Aborting scaffold for this service.`)); @@ -354,11 +354,11 @@ export async function scaffoldMonorepo(projectNameArg, options) { } } else if (svcType === 'sveltekit') { try { - console.log(chalk.cyan('⚙️ Running SvelteKit generator (create-svelte)...')); - await execa('npx', ['--yes', 'create-svelte@latest', '.', '--template', 'skeleton'], { cwd: dest, stdio: 'inherit' }); + console.log(chalk.cyan('⚙️ Running SvelteKit generator (sv create)...')); + await execa('npx', ['sv', 'create', '.', '--template', 'minimal', '--types', 'ts', '--no-install', '--no-add-ons'], { cwd: dest, stdio: 'inherit' }); usedGenerator = true; } catch (e) { - console.error(chalk.red(`❌ create-svelte failed: ${e.message}. Aborting scaffold for this service.`)); + console.error(chalk.red(`❌ sv create failed: ${e.message}. Aborting scaffold for this service.`)); continue; } } From bd5678441434dc39d395cd56666798204f2c2201 Mon Sep 17 00:00:00 2001 From: meenu155 Date: Sat, 15 Nov 2025 12:12:26 +0530 Subject: [PATCH 5/7] 1.18.0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 490302b..5a1320f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "create-polyglot", - "version": "1.17.0", + "version": "1.18.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "create-polyglot", - "version": "1.17.0", + "version": "1.18.0", "license": "MIT", "dependencies": { "chalk": "^5.6.2", diff --git a/package.json b/package.json index 9f20131..14315f0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "create-polyglot", - "version": "1.17.0", + "version": "1.18.0", "description": "Scaffold polyglot microservice monorepos with built-in templates for Node, Python, Go, and more.", "main": "bin/index.js", "scripts": { From 9470ee0ff4558ee47ce8bbacb0d4f2ecab419768 Mon Sep 17 00:00:00 2001 From: meenu155 Date: Sat, 15 Nov 2025 12:16:52 +0530 Subject: [PATCH 6/7] feat: update README and config to include support for Remix, Astro, and SvelteKit --- README.md | 6 +++--- docs/.vitepress/config.mjs | 9 ++++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 6464762..da46a7e 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ [![npm downloads](https://img.shields.io/npm/dw/create-polyglot.svg)](https://www.npmjs.com/package/create-polyglot) Scaffold a modern polyglot microservices monorepo in seconds.
-Generate Node.js, Python (FastAPI), Go, Java (Spring Boot), and Next.js frontend services with optional Turborepo or Nx presets, Docker Compose, shared packages, plugin hooks, and a persisted configuration file. +Generate Node.js, Python (FastAPI), Go, Java (Spring Boot), Next.js, plus optional modern frontend frameworks (Remix, Astro, SvelteKit) with Turborepo or Nx presets, Docker Compose, shared packages, plugin hooks, and a persisted configuration file. @@ -54,7 +54,7 @@ Use it to prototype architectures, onboard teams faster, or spin up reproducible ## Features -- 🚀 Rapid polyglot monorepo scaffolding (Node.js, Python/FastAPI, Go, Java Spring Boot, Next.js) +- 🚀 Rapid polyglot monorepo scaffolding (Node.js, Python/FastAPI, Go, Java Spring Boot, Next.js, Remix, Astro, SvelteKit) - 🧩 Optional presets: Turborepo, Nx, or Basic runner - 🐳 Automatic Dockerfile + Docker Compose generation - 🛠 Interactive wizard (or fully non-interactive via flags) @@ -174,7 +174,7 @@ create-polyglot dev --docker ## Init Options | Flag | Description | |------|-------------| -| `-s, --services ` | Comma separated services: `node,python,go,java,frontend` | +| `-s, --services ` | Comma separated services: `node,python,go,java,frontend,remix,astro,sveltekit` | | `--preset ` | `turborepo`, `nx`, or `basic` (default auto -> asks) | | `--git` | Initialize git repo & initial commit | | `--no-install` | Skip dependency installation step | diff --git a/docs/.vitepress/config.mjs b/docs/.vitepress/config.mjs index 55b2dd3..7903a19 100644 --- a/docs/.vitepress/config.mjs +++ b/docs/.vitepress/config.mjs @@ -6,7 +6,8 @@ export default defineConfig({ // sets VITEPRESS_BASE automatically; local dev stays '/'. base: process.env.VITEPRESS_BASE || '/', title: 'create-polyglot', - description: 'Scaffold polyglot microservice monorepos (Node, Python, Go, Java, Next.js)', + // Updated to reflect newly supported frontend frameworks (Remix, Astro, SvelteKit) + description: 'Scaffold polyglot microservice monorepos (Node, Python, Go, Java, Next.js, Remix, Astro, SvelteKit)', head: [ ['meta', { name: 'theme-color', content: '#3e62ad' }], ['meta', { name: 'og:title', content: 'create-polyglot' }], @@ -26,7 +27,8 @@ export default defineConfig({ { text: 'Getting Started', link: '/guide/getting-started' }, { text: 'Presets', link: '/guide/presets' }, { text: 'Docker & Compose', link: '/guide/docker' }, - { text: 'Extending (New Service)', link: '/guide/extending-service' }, + { text: 'Extending (New Service)', link: '/guide/extending-service' }, + { text: 'Frontend Frameworks', link: '/guide/frontend-frameworks' }, { text: 'Service Logs', link: '/logs-feature' }, { text: 'Plugin System', link: '/plugin-system' }, { text: 'Service Controls', link: '/service-controls-feature' }, @@ -46,7 +48,8 @@ export default defineConfig({ { text: 'Python', link: '/templates/python' }, { text: 'Go', link: '/templates/go' }, { text: 'Java (Spring Boot)', link: '/templates/java' }, - { text: 'Frontend (Next.js)', link: '/templates/frontend' } + { text: 'Frontend (Next.js)', link: '/templates/frontend' }, + { text: 'Frontend Frameworks (Remix/Astro/SvelteKit)', link: '/guide/frontend-frameworks' } ] }, socialLinks: [ From 0be1fccd091f4eaee1054f1c1b1952cf0644b751 Mon Sep 17 00:00:00 2001 From: meenu155 Date: Sat, 15 Nov 2025 12:17:04 +0530 Subject: [PATCH 7/7] feat: add documentation for support of additional frontend frameworks and update templates overview --- docs/guide/frontend-frameworks.md | 112 ++++++++++++++++++++++++++++++ docs/templates/index.md | 13 ++-- 2 files changed, 118 insertions(+), 7 deletions(-) create mode 100644 docs/guide/frontend-frameworks.md diff --git a/docs/guide/frontend-frameworks.md b/docs/guide/frontend-frameworks.md new file mode 100644 index 0000000..290e6f6 --- /dev/null +++ b/docs/guide/frontend-frameworks.md @@ -0,0 +1,112 @@ +# Modern Frontend Framework Support + +create-polyglot can scaffold additional frontend frameworks beyond the default Next.js. + +## Supported Frameworks + +- **Next.js** (internal template or `create-next-app` when `--frontend-generator` is passed) +- **Remix** (via `npx create-remix@latest . --template remix`) +- **Astro** (via `npx create-astro@latest -- --template minimal`) +- **SvelteKit** (via `npx sv create .`; falls back to `npx create-svelte@latest . --template skeleton` if the new command fails) + +## Selecting Frameworks + +Specify them in the `--services` list during init or with `create-polyglot add service`: + +```bash +create-polyglot init my-stack -s remix,astro,sveltekit --yes +create-polyglot add service docs --type astro --port 3030 +``` + +## Ports + +Default ports: + +```text +remix: 3005 +astro: 3006 +sveltekit: 3007 +``` + +Override any port via `type:name:port` syntax: + +```bash +create-polyglot init web-app -s remix:web:3100,astro:site:3200,sveltekit:kit:3300 --yes +``` + +## Generation Behavior + +| Framework | Generation Method | Fallback | Notes | +|-----------|-------------------|----------|-------| +| Remix | `create-remix` | None (skip on failure) | Skipped if generator errors. | +| Astro | `create-astro` | None (skip on failure) | Uses `--template minimal`. | +| SvelteKit | `sv create` | `create-svelte` | Deprecation handled gracefully. | + +Failed generators log an error and the service is skipped (not partially scaffolded) to avoid broken directories. + +## Docker + +All Node-based frameworks (Remix, Astro, SvelteKit) reuse the generic Node Dockerfile pattern: + +```Dockerfile +FROM node:20-alpine AS deps +WORKDIR /app +COPY package*.json ./ +RUN npm install --omit=dev || true +COPY . . +EXPOSE +CMD ["npm", "run", "dev"] +``` + +Adjust after generation if framework-specific build or preview commands are desired. + +## Service Manager + +Runtime start uses the detected package manager and `npm run dev` (or equivalent) for these frameworks. Ensure the generator produces a `dev` script. If not, add one manually. + +## Caveats & Future Plans + +- No internal fallback templates (kept lean). Potential future flag: `--allow-fallback`. +- Post-generation customization (eslint, prettier) left to user. +- May add automatic build scripts & production Docker variants later. + +## Example Full Init + +```bash +npx create-polyglot init multi-web -s node,remix,astro,sveltekit --git --yes +``` + +After scaffold: + +```bash +cd multi-web +npm run list:services +create-polyglot dev +``` + +## Troubleshooting + +| Issue | Cause | Fix | +|-------|-------|-----| +| Generator network failure | Offline or registry issue | Retry with stable connection; consider adding fallback templates. | +| Missing dev script | Generator changed defaults | Add `"dev": ""` to `package.json`. | +| Port collision | Duplicate specified port | Re-run with adjusted port list or edit `polyglot.json` then restart. | +| SvelteKit deprecation warning | Using legacy command | Ensure `sv` is available; keep fallback until ecosystem fully migrates. | + +## Updating Existing Workspace + +Add a new framework to an existing project: + +```bash +create-polyglot add service ui-new --type sveltekit --port 3400 +``` + +Remove it later: + +```bash +create-polyglot remove service ui-new --yes +``` + +--- + +Need another framework (e.g., Nuxt, SolidStart)? Open an issue or PR with a proposed generator command. diff --git a/docs/templates/index.md b/docs/templates/index.md index c3f7104..02867bb 100644 --- a/docs/templates/index.md +++ b/docs/templates/index.md @@ -1,11 +1,10 @@ # Templates Overview -All service templates live in `templates/` and are copied verbatim (with a Spring Boot properties rename step). Current templates: +Service scaffolding comes from internal templates or official generators: -- `node/` Express + `/health` endpoint -- `python/` FastAPI + `/health` -- `go/` net/http server + `/health` -- `spring-boot/` Java with `/health` REST controller -- `frontend/` Next.js minimal (or `create-next-app` output when generator used) +- Internal templates (copied verbatim): `node/`, `python/`, `go/`, `spring-boot/`, `frontend/` (minimal Next.js when not using `--frontend-generator`). +- External generators (no internal fallback unless added later): Remix (`create-remix`), Astro (`create-astro`), SvelteKit (`sv create` with legacy `create-svelte` fallback). -Each template should stay minimal & dependency-light. +Spring Boot still performs a post-copy rename of `application.properties.txt` → `application.properties`. + +Keep internal templates minimal & dependency-light; external generator outputs are left intact.