Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ jobs:
matrix:
group:
- name: frontend-core
args: --scenario landing-react-vite --scenario frontend-nextjs --scenario frontend-react-vite-netlify --scenario frontend-astro --scenario frontend-remix-bun
args: --scenario landing-react-vite --scenario frontend-nextjs --scenario frontend-nextjs-railway --scenario frontend-react-vite-netlify --scenario frontend-astro --scenario frontend-remix-bun
- name: frontend-apps
args: --scenario frontend-vue-vite --scenario frontend-nuxt --scenario frontend-svelte --scenario frontend-solidjs
- name: backends
args: --scenario backend-express --scenario backend-fastify --scenario backend-hono --scenario backend-koa-javascript --scenario backend-nestjs
args: --scenario backend-express --scenario backend-fastify --scenario backend-fastify-render --scenario backend-hono --scenario backend-koa-javascript --scenario backend-nestjs --scenario backend-nestjs-enterprise-pnpm
- name: fullstack-workspaces
args: --scenario fullstack-nextjs --scenario fullstack-react-api --scenario microfrontend-workspace
- name: extensions-cli
args: --scenario chrome-extension-react --scenario chrome-extension-vanilla-ts --scenario cli-tool
args: --scenario chrome-extension-react --scenario chrome-extension-react-jest-pnpm --scenario chrome-extension-vanilla-ts --scenario cli-tool
steps:
- uses: actions/checkout@v6
- uses: oven-sh/setup-bun@v2
Expand Down
30 changes: 30 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,36 @@ The format follows Keep a Changelog and the version numbers follow Semantic Vers

## [Unreleased]

## [0.5.1] - 2026-04-09

### Added

- Added a deployment profile layer that records provider-specific build commands, start commands, ports, health paths, generated files, secrets, and environment-variable expectations for verified scaffold pairs.
- Added `Render` deployment baselines for verified `react-vite` frontend apps and `express`, `fastify`, and `hono` backend APIs, including generated `render.yaml` output and deploy workflow guidance.
- Added `Railway` deployment baselines for verified `nextjs` frontend apps and `express`, `fastify`, and `hono` backend APIs, including generated `railway.toml` output and deploy workflow guidance.
- Added deployment-profile regression coverage, provider-specific generator assertions, runtime-matrix scenarios for `frontend-nextjs-railway` and `backend-fastify-render`, and packed-artifact smoke coverage for deployment-target upgrades.
- Added deployment-aware `.env.example`, README, architecture, and getting-started outputs so generated projects surface provider env vars and deployment expectations alongside local run commands.
- Added end-to-end runtime coverage for capability-heavy `NestJS + Fastify + pnpm + Jest` backends and `React Chrome extension + pnpm + Jest` scaffolds so non-default package-manager and test-runner paths are exercised as generated projects.

### Changed

- Expanded deployment-aware scaffold docs and CLI guidance so generated projects now explain build commands, start commands, health checks, provider secrets, and expected environment variables for the selected deployment target.
- Updated `devforge upgrade` so deployment target changes can remove stale managed provider files such as `vercel.json`, `netlify.toml`, `render.yaml`, `railway.toml`, and `docker-compose.yml` when those files still match a previous generated baseline.
- Updated generated backend and Next.js runtime commands to bind to deployment-friendly hosts, which makes managed hosting baselines more usable without manual edits.
- Expanded CI and packed-artifact smoke coverage so the shipped npm package now exercises deployment-target refresh against `Render`, while source CI validates the new `Railway` and `Render` runtime scenarios directly.
- Clarified backend capability prompts and generated guidance so authentication, database, ORM, Redis, Swagger, and WebSocket selections are described as starter baselines unless the scaffold fully wires them.

### Fixed

- Fixed deployment-target support so verified managed-hosting targets are exercised by the runtime matrix and packed npm smoke path instead of relying only on unit-level generation checks.
- Fixed deployment upgrade behavior for users switching providers by cleaning up obsolete managed deployment files even when the stored project plan has already been normalized to the new target.
- Fixed generated Jest example tests so TypeScript projects include explicit Jest type references during `build` and `typecheck` instead of depending on missing ambient globals.
- Fixed generated Jest configs so TypeScript 6 based scaffolds ignore the known `ts-jest` deprecation codes that would otherwise break `pnpm run test` on browser-oriented projects.
- Fixed NestJS Fastify scaffolds so the generated server bootstrap uses `@nestjs/platform-fastify` instead of falling back to the default Express driver.
- Fixed runtime-matrix package-manager installs so `pnpm` and `yarn` scenarios can run through Corepack when the package manager is not globally installed.
- Fixed the runtime matrix to cover the exact `NestJS + Fastify + pnpm + Jest` backend path and `React Chrome extension + pnpm + Jest` path that had previously escaped end-to-end validation.
- Fixed runtime-matrix `pnpm` fallbacks on CI runners by switching the no-global-`pnpm` path away from Corepack key resolution and onto an npm-backed `pnpm` invocation.

## [0.5.0] - 2026-04-02

### Added
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ DevForge helps you:
- AI rule outputs for Cursor, Claude, Codex, and `AGENTS.md`
- testing setup for Vitest, Jest, Playwright, and Cypress
- optional ESLint, Prettier, Husky, Commitlint, Docker, and GitHub Actions setup
- deployment baselines for verified Vercel, Netlify, and Docker Compose scaffold pairs
- deployment baselines for verified Vercel, Netlify, Render, Railway, and Docker Compose scaffold pairs
- generated docs, changelog-ready project metadata, and baseline repository hygiene

## Quick Start
Expand Down Expand Up @@ -170,10 +170,10 @@ npm run runtime:matrix -- --scenario backend-hono --scenario cli-tool
## Deployment Targets

- Verified deployment targets are offered only for supported stack pairs.
- `react-vite` frontend apps can target `Vercel` or `Netlify`.
- `nextjs` frontend apps can target `Vercel`.
- `express`, `fastify`, and `hono` backend APIs can target `Docker Compose`.
- Deployment generation includes target-specific config files and optional manual deploy workflows when GitHub Actions is enabled.
- `react-vite` frontend apps can target `Vercel`, `Netlify`, or `Render`.
- `nextjs` frontend apps can target `Vercel`, `Render`, or `Railway`.
- `express`, `fastify`, and `hono` backend APIs can target `Docker Compose`, `Render`, or `Railway`.
- Deployment generation includes provider-specific config files, build/start/health-path guidance, expected env vars, and optional manual deploy workflows when GitHub Actions are enabled.

## Repository Docs

Expand Down
30 changes: 30 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,36 @@ Track what changed in DevForge CLI across releases, including scaffolding behavi
- [GitHub Releases](https://github.com/Ali-dev11/devforge/releases)
- [Repository Changelog](https://github.com/Ali-dev11/devforge/blob/main/CHANGELOG.md)

## [0.5.1] - 2026-04-09

### Added

- Added a deployment profile layer that records provider-specific build commands, start commands, ports, health paths, generated files, secrets, and environment-variable expectations for verified scaffold pairs.
- Added `Render` deployment baselines for verified `react-vite` frontend apps and `express`, `fastify`, and `hono` backend APIs, including generated `render.yaml` output and deploy workflow guidance.
- Added `Railway` deployment baselines for verified `nextjs` frontend apps and `express`, `fastify`, and `hono` backend APIs, including generated `railway.toml` output and deploy workflow guidance.
- Added deployment-profile regression coverage, provider-specific generator assertions, runtime-matrix scenarios for `frontend-nextjs-railway` and `backend-fastify-render`, and packed-artifact smoke coverage for deployment-target upgrades.
- Added deployment-aware `.env.example`, README, architecture, and getting-started outputs so generated projects surface provider env vars and deployment expectations alongside local run commands.
- Added end-to-end runtime coverage for capability-heavy `NestJS + Fastify + pnpm + Jest` backends and `React Chrome extension + pnpm + Jest` scaffolds so non-default package-manager and test-runner paths are exercised as generated projects.

### Changed

- Expanded deployment-aware scaffold docs and CLI guidance so generated projects now explain build commands, start commands, health checks, provider secrets, and expected environment variables for the selected deployment target.
- Updated `devforge upgrade` so deployment target changes can remove stale managed provider files such as `vercel.json`, `netlify.toml`, `render.yaml`, `railway.toml`, and `docker-compose.yml` when those files still match a previous generated baseline.
- Updated generated backend and Next.js runtime commands to bind to deployment-friendly hosts, which makes managed hosting baselines more usable without manual edits.
- Expanded CI and packed-artifact smoke coverage so the shipped npm package now exercises deployment-target refresh against `Render`, while source CI validates the new `Railway` and `Render` runtime scenarios directly.
- Clarified backend capability prompts and generated guidance so authentication, database, ORM, Redis, Swagger, and WebSocket selections are described as starter baselines unless the scaffold fully wires them.

### Fixed

- Fixed deployment-target support so verified managed-hosting targets are exercised by the runtime matrix and packed npm smoke path instead of relying only on unit-level generation checks.
- Fixed deployment upgrade behavior for users switching providers by cleaning up obsolete managed deployment files even when the stored project plan has already been normalized to the new target.
- Fixed generated Jest example tests so TypeScript projects include explicit Jest type references during `build` and `typecheck` instead of depending on missing ambient globals.
- Fixed generated Jest configs so TypeScript 6 based scaffolds ignore the known `ts-jest` deprecation codes that would otherwise break `pnpm run test` on browser-oriented projects.
- Fixed NestJS Fastify scaffolds so the generated server bootstrap uses `@nestjs/platform-fastify` instead of falling back to the default Express driver.
- Fixed runtime-matrix package-manager installs so `pnpm` and `yarn` scenarios can run through Corepack when the package manager is not globally installed.
- Fixed the runtime matrix to cover the exact `NestJS + Fastify + pnpm + Jest` backend path and `React Chrome extension + pnpm + Jest` path that had previously escaped end-to-end validation.
- Fixed runtime-matrix `pnpm` fallbacks on CI runners by switching the no-global-`pnpm` path away from Corepack key resolution and onto an npm-backed `pnpm` invocation.

## [0.5.0] - 2026-04-02

### Added
Expand Down
3 changes: 3 additions & 0 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ npx --yes @ali-dev11/devforge@latest add testing
- Config-driven runs pass through the same normalization and compatibility checks as interactive runs, so invalid hand-written combinations are still corrected or rejected with guidance.
- `devforge upgrade` refreshes DevForge-managed docs, workflows, AI rules, deployment files, and core tooling surfaces while skipping files that no longer match the previous generated baseline.
- `devforge add <feature>` updates an existing DevForge project by reading `.devforge/project-plan.json` and rewriting only the managed files for that feature.
- Verified deployment targets now carry a normalized provider profile, so generated docs and workflows stay aligned on build commands, start commands, health checks, secrets, and expected environment variables.

## Repository Commands

Expand Down Expand Up @@ -72,9 +73,11 @@ npm run runtime:matrix -- --scenario backend-hono --scenario cli-tool
- Use `npx --yes @ali-dev11/devforge@latest init --save-config` when you want an interactive run to become a reusable team preset later.
- Use `npx --yes @ali-dev11/devforge@latest init --config ./devforge.config.json --output ./my-app` when validating reproducible scaffold output.
- Use `npx --yes @ali-dev11/devforge@latest upgrade` when changing generated docs, workflows, deployment baselines, or other managed tooling surfaces.
- When changing deployment targets, verify both the generated provider file and the follow-up workflow guidance because `upgrade` now removes stale managed provider files that still match a previous generated baseline.
- Use `npx --yes @ali-dev11/devforge@latest add testing`, `add docker`, `add github-actions`, or `add ai-rules` when validating managed post-scaffold updates.
- Use `npm run runtime:matrix` when changing templates, prompts, package-manager behavior, or generated runtime surfaces.
- Use `npm run smoke:packed` when changing the package entrypoints, published files, CLI dispatch, or install-time behavior.
- If you touch deployment generation, validate `Render` and `Railway` flows through `npm run runtime:matrix` or `npm run smoke:packed`, not just unit-level file snapshots.
- If you touch microfrontend templates, validate the generated `dev` workflow, not just build output.
- If you touch docs or release notes, rerun `npm run docs:changelog`.

Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ DevForge CLI turns project intent into a runnable JavaScript or TypeScript repos
- ESLint and Prettier are baseline defaults because most teams want immediate quality and formatting consistency.
- Husky and Commitlint are optional because local git-hook enforcement varies by team and workflow.
- Testing, AI rules, backend capabilities, frontend libraries, and DevOps extras can all stay on recommended defaults or be customized only when needed.
- Deployment targets are limited to verified stack pairs so DevForge only offers deployment baselines it can actually generate and validate.
- Deployment targets are limited to verified stack pairs so DevForge only offers deployment baselines it can actually generate and validate, including the current `Vercel`, `Netlify`, `Render`, `Railway`, and `Docker Compose` paths.

## Command Reference

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ali-dev11/devforge",
"version": "0.5.0",
"version": "0.5.1",
"description": "Production-focused AI-native project scaffolding CLI for JavaScript and TypeScript teams.",
"license": "MIT",
"author": "Ali-dev11",
Expand Down
6 changes: 3 additions & 3 deletions scripts/smoke-packed.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ try {

const storedPlanPath = resolve(outputDir, ".devforge/project-plan.json");
const storedPlan = JSON.parse(readFileSync(storedPlanPath, "utf8"));
storedPlan.deployment.target = "vercel";
storedPlan.deployment.target = "render";
writeFileSync(storedPlanPath, `${JSON.stringify(storedPlan, null, 2)}\n`, "utf8");

run(
Expand Down Expand Up @@ -123,8 +123,8 @@ try {
throw new Error("Packed smoke run did not create Dockerfile after `devforge add docker`.");
}

if (!existsSync(resolve(outputDir, "vercel.json"))) {
throw new Error("Packed smoke run did not create vercel.json after `devforge upgrade`.");
if (!existsSync(resolve(outputDir, "render.yaml"))) {
throw new Error("Packed smoke run did not create render.yaml after `devforge upgrade`.");
}
} finally {
rmSync(workspace, { recursive: true, force: true });
Expand Down
86 changes: 85 additions & 1 deletion src/commands/upgrade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import type {
InstallResult,
ProjectPlan,
} from "../types.js";
import { pathExists, readJson, writeJson, writeTextFile } from "../utils/fs.js";
import { pathExists, readJson, removeFile, writeJson, writeTextFile } from "../utils/fs.js";
import { banner, info, step, success, warn } from "../utils/logger.js";

export type ApplyUpgradeOptions = {
Expand All @@ -41,6 +41,14 @@ type PackageJsonShape = {
engines?: Record<string, string>;
};

const TARGET_EXCLUSIVE_MANAGED_PATHS = [
"vercel.json",
"netlify.toml",
"render.yaml",
"railway.toml",
"docker-compose.yml",
] as const;

function printAdvisorySection(
title: string,
items: AdvisoryItem[],
Expand Down Expand Up @@ -115,6 +123,36 @@ function buildGeneratedFileMap(
return new Map(files.map((file) => [file.path, file]));
}

function buildTargetExclusiveManagedContentCandidates(
plan: ProjectPlan,
environment: EnvironmentInfo,
path: (typeof TARGET_EXCLUSIVE_MANAGED_PATHS)[number],
): Set<string> {
const candidates = new Set<string>();
const targets: ProjectPlan["deployment"]["target"][] = [
"vercel",
"netlify",
"render",
"railway",
"docker-compose",
];

for (const target of targets) {
const variant: ProjectPlan = JSON.parse(JSON.stringify(plan)) as ProjectPlan;
variant.deployment.target = target;
if (target === "docker-compose") {
variant.tooling.docker = true;
}

const content = buildGeneratedFileMap(variant, environment).get(path)?.content;
if (content) {
candidates.add(content);
}
}

return candidates;
}

function shouldManagePathForUpgrade(path: string): boolean {
return (
path === "README.md" ||
Expand All @@ -139,6 +177,8 @@ function shouldManagePathForUpgrade(path: string): boolean {
path === "docker-compose.yml" ||
path === "vercel.json" ||
path === "netlify.toml" ||
path === "render.yaml" ||
path === "railway.toml" ||
path === "AGENTS.md" ||
path === "docs/architecture.md" ||
path === "docs/getting-started.md" ||
Expand Down Expand Up @@ -351,6 +391,50 @@ export async function applyUpgrade(
skippedManaged.push(relativePath);
}

for (const [relativePath, previousFile] of previousGenerated.entries()) {
if (!shouldManagePathForUpgrade(relativePath) || nextGenerated.has(relativePath)) {
continue;
}

const absolutePath = join(cwd, relativePath);
const currentContent = await readTextFileIfExists(absolutePath);

if (currentContent === undefined) {
continue;
}

if (currentContent === previousFile.content || hasManagedMarker(currentContent)) {
await removeFile(absolutePath);
filesWritten.push(absolutePath);
continue;
}

skippedManaged.push(relativePath);
}

for (const relativePath of TARGET_EXCLUSIVE_MANAGED_PATHS) {
if (nextGenerated.has(relativePath)) {
continue;
}

const absolutePath = join(cwd, relativePath);
const currentContent = await readTextFileIfExists(absolutePath);
if (currentContent === undefined) {
continue;
}

const generatedCandidates = buildTargetExclusiveManagedContentCandidates(
plan,
environment,
relativePath,
);

if (generatedCandidates.has(currentContent)) {
await removeFile(absolutePath);
filesWritten.push(absolutePath);
}
}

const projectPlanPath = join(cwd, PROJECT_PLAN_PATH);
const previousPlanJson = JSON.stringify(previousPlan, null, 2);
const nextPlanJson = JSON.stringify(plan, null, 2);
Expand Down
2 changes: 2 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@ export const DEPLOYMENT_TARGET_CHOICES: Array<{
{ title: "None", value: "none" },
{ title: "Vercel", value: "vercel" },
{ title: "Netlify", value: "netlify" },
{ title: "Render", value: "render" },
{ title: "Railway", value: "railway" },
{ title: "Docker Compose", value: "docker-compose" },
];

Expand Down
Loading
Loading