Skip to content
Closed
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
e8b0a51
chore: scaffold create-vinext-app package structure
Divkix May 3, 2026
934a2b9
feat(create-vinext-app): add package manager detection and install co…
Divkix May 3, 2026
44ca4ed
feat(create-vinext-app): add project name validation and path resolution
Divkix May 3, 2026
1e00020
feat(create-vinext-app): add catalog version baking from pnpm-workspa…
Divkix May 3, 2026
bdca5b0
feat(create-vinext-app): add template scaffolding with variable subst…
Divkix May 3, 2026
c26edfe
feat(create-vinext-app): add interactive prompts with @clack/prompts
Divkix May 3, 2026
afdab2f
feat(create-vinext-app): add main CLI entry point with arg parsing an…
Divkix May 3, 2026
a3fd0be
feat(create-vinext-app): add App Router template
Divkix May 3, 2026
0964d64
feat(create-vinext-app): add Pages Router template
Divkix May 3, 2026
046f7a8
feat(create-vinext-app): add integration tests for App Router and Pag…
Divkix May 3, 2026
89d874e
ci: add create-vinext-app job to CI workflow
Divkix May 3, 2026
0edd9f7
ci: add create-vinext-app publishing job
Divkix May 3, 2026
723823e
docs: add create-vinext-app README and update root README
Divkix May 3, 2026
3205bbc
fix(create-vinext-app): include templates in published package files
Divkix May 3, 2026
dcf8daa
fix(ci): fix create-vinext-app install failure and formatting
Divkix May 3, 2026
8187a0e
fix(ci): fix create-vinext-app build execution and knip config
Divkix May 3, 2026
ace0380
fix(create-vinext-app): align bin/main with vp pack output
Divkix May 3, 2026
a17bf0b
fix(knip): remove redundant config, add vitest ignore for create-vine…
Divkix May 3, 2026
600c6d5
remove docs
Divkix May 3, 2026
3c6af6b
fix(create-vinext-app): address PR review — version baking, worker de…
Divkix May 3, 2026
126abad
fix: sync pnpm lockfile after removing vitest from create-vinext-app …
Divkix May 3, 2026
ae20b22
fix: address PR review — scoped names, worker env/ctx, basePath middl…
Divkix May 3, 2026
5249f5a
Merge branch 'main' into feat/create-vinext-app
Divkix May 16, 2026
b6941bc
Merge branch 'main' into feat/create-vinext-app
Divkix May 16, 2026
ba60401
fix(create-vinext-app): remove unused @cloudflare/workers-types from …
Divkix May 16, 2026
d1674bc
fix(create-vinext-app): regenerate lockfile after removing root devDep
Divkix May 16, 2026
62af93e
fix(create-vinext-app): restore @cloudflare/workers-types to root dev…
Divkix May 16, 2026
9f3b3e8
Merge remote-tracking branch 'origin/main' into feat/create-vinext-app
Divkix Jun 8, 2026
cafba8a
Merge branch 'main' into feat/create-vinext-app
Divkix Jun 8, 2026
eb1ebcd
ci: fix zizmor security findings in ci and publish workflows
Divkix Jun 8, 2026
1070cce
ci: add explicit permissions to ci gate job in publish workflow
Divkix Jun 8, 2026
bc246ee
Merge remote-tracking branch 'origin/main' into feat/create-vinext-app
Divkix Jun 18, 2026
eed4faf
Merge branch 'main' into feat/create-vinext-app
Divkix Jun 21, 2026
8db052f
Merge origin/main into feat/create-vinext-app
Divkix Jul 13, 2026
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
31 changes: 30 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,35 @@ jobs:
kill "$SERVER_PID" 2>/dev/null || true
exit 1

create-vinext-app:
name: create-vinext-app (${{ matrix.template }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
template: [app, pages]
steps:
- uses: actions/checkout@v6
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
- uses: ./.github/actions/setup
- name: Build create-vinext-app
run: vp pack
working-directory: packages/create-vinext-app

- name: Scaffold a fresh create-vinext-app project
run: |
node dist/index.mjs "${{ runner.temp }}/cva-test-${{ matrix.template }}" --yes --skip-install --no-git --template ${{ matrix.template }}
working-directory: packages/create-vinext-app

- name: Verify project structure
run: |
ls -la "${{ runner.temp }}/cva-test-${{ matrix.template }}"
cat "${{ runner.temp }}/cva-test-${{ matrix.template }}/package.json"
cat "${{ runner.temp }}/cva-test-${{ matrix.template }}/wrangler.jsonc"

- name: Run create-vinext-app unit tests
run: vp test run
working-directory: packages/create-vinext-app

e2e:
name: E2E (${{ matrix.project }})
runs-on: ubuntu-latest
Expand Down Expand Up @@ -185,7 +214,7 @@ jobs:
ci:
name: CI
if: ${{ always() }}
needs: [check, test-unit, test-integration-merge, create-next-app, e2e]
needs: [check, test-unit, test-integration-merge, create-next-app, create-vinext-app, e2e]
runs-on: ubuntu-latest
steps:
- name: All checks passed
Expand Down
169 changes: 168 additions & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
uses: ./.github/workflows/ci.yml

publish:
name: Publish
name: Publish vinext
needs: ci
if: github.repository_owner == 'cloudflare'
runs-on: ubuntu-latest
Expand Down Expand Up @@ -194,3 +194,170 @@ jobs:
-d "$PAYLOAD")

echo "$RESPONSE"

publish-create-vinext-app:
name: Publish create-vinext-app
needs: ci
if: github.repository_owner == 'cloudflare'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
with:
fetch-depth: 0
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed

- uses: ./.github/actions/setup

- name: Build
run: vp run build
working-directory: packages/create-vinext-app

- name: Bump version
id: version
working-directory: packages/create-vinext-app
env:
BUMP: ${{ inputs.bump }}
run: |
LATEST=$(npm view create-vinext-app version 2>/dev/null || echo "0.0.0")
IFS='.' read -r MAJOR MINOR PATCH <<< "$LATEST"

case "$BUMP" in
major)
MAJOR=$((MAJOR + 1))
MINOR=0
PATCH=0
;;
minor)
MINOR=$((MINOR + 1))
PATCH=0
;;
patch)
PATCH=$((PATCH + 1))
;;
esac

VERSION="${MAJOR}.${MINOR}.${PATCH}"
npm version "$VERSION" --no-git-tag-version
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "Publishing create-vinext-app@${VERSION} (was ${LATEST})"
echo "previous=${LATEST}" >> "$GITHUB_OUTPUT"

- name: Publish (OIDC trusted publishing)
working-directory: packages/create-vinext-app
env:
NPM_CONFIG_REGISTRY: https://registry.npmjs.org
run: vp pm publish --no-git-checks --access public -- --provenance

- name: Tag release
run: |
git tag "create-vinext-app-v${{ steps.version.outputs.version }}"
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
git push origin "create-vinext-app-v${{ steps.version.outputs.version }}"
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed

- name: Get changes since last version
env:
GH_TOKEN: ${{ github.token }}
run: |
PREV_TAG="create-vinext-app-v${{ steps.version.outputs.previous }}"
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
FORMAT="%H %s"
if git rev-parse "$PREV_TAG" >/dev/null 2>&1; then
git log "$PREV_TAG"..HEAD --format="$FORMAT" --no-merges -- packages/create-vinext-app/ > /tmp/cva-commits.txt
else
git log --format="$FORMAT" --no-merges -30 -- packages/create-vinext-app/ > /tmp/cva-commits.txt
fi

# Resolve GitHub @usernames for each commit via the API
while IFS= read -r line; do
SHA=$(echo "$line" | cut -d' ' -f1)
SUBJECT=$(echo "$line" | cut -d' ' -f2-)
LOGIN=$(gh api "repos/${{ github.repository }}/commits/${SHA}" --jq '.author.login // .commit.author.name' 2>/dev/null || echo "")
if [ -n "$LOGIN" ]; then
echo "${SHA:0:7} ${SUBJECT} (@${LOGIN})"
else
echo "${SHA:0:7} ${SUBJECT}"
fi
done < /tmp/cva-commits.txt > /tmp/cva-commits-with-authors.txt

- name: Generate release summary
id: summary
env:
CF_ACCOUNT_ID: ${{ secrets.CF_AI_GATEWAY_ACCOUNT_ID }}
CF_GATEWAY_NAME: ${{ secrets.CF_AI_GATEWAY_NAME }}
CF_API_TOKEN: ${{ secrets.CF_AI_GATEWAY_TOKEN }}
run: |
COMMITS=$(cat /tmp/cva-commits-with-authors.txt)
echo "::group::Commits since last release"
echo "$COMMITS"
echo "::endgroup::"

RESPONSE=$(curl -s --max-time 30 \
"https://gateway.ai.cloudflare.com/v1/${CF_ACCOUNT_ID}/${CF_GATEWAY_NAME}/anthropic/v1/messages" \
-H "Content-Type: application/json" \
-H "cf-aig-authorization: Bearer ${CF_API_TOKEN}" \
-H "anthropic-version: 2023-06-01" \
-d "$(jq -n --arg commits "$COMMITS" --arg version "${{ steps.version.outputs.version }}" '{
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
model: "claude-sonnet-4-20250514",
max_tokens: 1024,
messages: [{
role: "user",
content: ("You are writing GitHub release notes for create-vinext-app v" + $version + " — a CLI tool for scaffolding vinext projects on Cloudflare Workers.\n\nHere are the commits since the last release (format: hash subject (@github-username)):\n\n" + $commits + "\n\nWrite release notes in standard GitHub release format. Use these guidelines:\n- Group changes under markdown headings: ## What'\''s Changed, then subheadings like ### New Features, ### Bug Fixes, ### Performance, ### Internal / Chores — only include a subheading if there are relevant commits for it\n- Under each subheading, write bullet points. Each bullet should describe the change in plain English from a user'\''s perspective — not just repeat the commit message verbatim\n- Do NOT credit contributors inline in bullet points\n- At the very end, add a ## Contributors section listing each unique contributor as @username (keep the @ prefix so GitHub renders it as a mention), one per line\n- Omit noise like typo fixes, dependency bumps, and CI-only changes unless they are meaningful to users\n- No preamble or closing remarks — just the release notes")
}]
}')") || true

SUMMARY=""
if [ -n "$RESPONSE" ]; then
# Check for API errors
ERROR=$(echo "$RESPONSE" | jq -r '.error.message // empty' 2>/dev/null)
if [ -n "$ERROR" ]; then
echo "::warning::AI Gateway error: $ERROR"
else
SUMMARY=$(echo "$RESPONSE" | jq -r '.content[0].text // empty' 2>/dev/null)
fi
fi

if [ -z "$SUMMARY" ]; then
SUMMARY="See commits: https://github.com/${{ github.repository }}/commits/create-vinext-app-v${{ steps.version.outputs.version }}"
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
fi

echo "::group::Release summary"
echo "$SUMMARY"
echo "::endgroup::"

{
echo "text<<EOFMARKER"
echo "$SUMMARY"
echo "EOFMARKER"
} >> "$GITHUB_OUTPUT"

- name: Create GitHub Release
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ steps.version.outputs.version }}
SUMMARY: ${{ steps.summary.outputs.text }}
run: |
gh release create "create-vinext-app-v${VERSION}" \
--title "create-vinext-app v${VERSION}" \
--notes-file - \
--repo "${{ github.repository }}" <<< "${SUMMARY}"

- name: Notify Google Chat
if: success()
continue-on-error: true
env:
GOOGLE_CHAT_WEBHOOK: ${{ secrets.GOOGLE_CHAT_WEBHOOK }}
VERSION: ${{ steps.version.outputs.version }}
SUMMARY: ${{ steps.summary.outputs.text }}
run: |
PAYLOAD=$(jq -n \
--arg version "$VERSION" \
--arg summary "$SUMMARY" \
'{"text": ("*create-vinext-app v" + $version + " published to npm*\n\n" + $summary + "\n\nnpm: https://www.npmjs.com/package/create-vinext-app/v/" + $version)}')

echo "::group::Webhook payload"
echo "$PAYLOAD"
echo "::endgroup::"

RESPONSE=$(curl -sS -w "\nHTTP %{http_code}" -X POST "$GOOGLE_CHAT_WEBHOOK" \
-H "Content-Type: application/json; charset=UTF-8" \
-d "$PAYLOAD")

echo "$RESPONSE"
27 changes: 24 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,30 @@ Environment variables: `PORT` (default `3000`), `HOST` (default `0.0.0.0`).

### Starting a new vinext project

Run `npm create next-app@latest` to create a new Next.js project, and then follow these instructions to migrate it to vinext.
Use `create-vinext-app` to scaffold a new project:

In the future, we will have a proper `npm create vinext` new project workflow.
```bash
npm create vinext-app
```

This will prompt for a project name and template (App Router or Pages Router), then scaffold a complete project with TypeScript, Vite, and Cloudflare Workers configuration.

**Quick start with defaults:**

```bash
npm create vinext-app my-app --yes
```

**Choose your template:**

```bash
npm create vinext-app my-app --template pages # Pages Router
npm create vinext-app my-app --template app # App Router (default)
```

See [create-vinext-app documentation](packages/create-vinext-app/README.md) for all options.

Alternatively, you can start from an existing Next.js project and migrate it to vinext (see below).

### Migrating an existing Next.js project

Expand Down Expand Up @@ -551,7 +572,7 @@ These are intentional exclusions:
- **`next export` (legacy)** — Use `output: 'export'` in config instead.
- **Turbopack/webpack configuration** — This runs on Vite. Use Vite plugins instead of webpack loaders/plugins.
- **`next/jest`** — Use Vitest.
- **`create-next-app` scaffolding** — Not a goal.
- **`create-next-app` scaffolding** — Use `create-vinext-app` instead.
- **Bug-for-bug parity with undocumented behavior** — If it's not in the Next.js docs, we probably don't replicate it.

## Known limitations
Expand Down
Loading
Loading