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
63 changes: 63 additions & 0 deletions .github/workflows/deploy-site.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Deploy showcase site to GitHub Pages

# Builds the Next.js static export under `site/` (next build → ./out)
# and publishes it to GitHub Pages. The legacy `docs/index.html`
# showcase remains in the tree but is no longer the deploy target
# once the repo's Pages source is switched to "GitHub Actions" in
# repository Settings → Pages.
#
# For a PROJECT page deployed under user.github.io/<repo>, also
# uncomment `basePath` / `assetPrefix` in `site/next.config.mjs`
# so assets resolve under the sub-path.

on:
push:
branches: [main]
paths:
- "site/**"
- ".github/workflows/deploy-site.yml"
workflow_dispatch:

permissions:
contents: read
pages: write
id-token: write

concurrency:
group: pages
cancel-in-progress: true

jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
working-directory: site
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: site/package-lock.json

- run: npm ci --no-audit --no-fund

- run: npx next build

- uses: actions/configure-pages@v5

- uses: actions/upload-pages-artifact@v3
with:
path: site/out

deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v4
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,34 @@ changes are planned.
tutorial-style. README's "What can I do with this?" table row
now links to both.

### Web

- **New Next.js showcase site** under `site/` is now the official
GitHub Pages deploy target for v1.6.8 onwards. Fully static
one-page marketing / playground built with Next.js 14 App
Router + TypeScript + Tailwind. `next build` emits `./out` (4
static pages, 99.7 kB first-load JS) and the new
[`.github/workflows/deploy-site.yml`](.github/workflows/deploy-site.yml)
uploads it to Pages on every push to `main` that touches
`site/**`. **Repo Settings → Pages source must be flipped to
"GitHub Actions"** for the workflow to take over from the
legacy branch-based deploy of `docs/index.html`; both files
coexist in the tree for one more cycle as a rollback.
- Live code snippets in the Hero / Playground sections mirror
the canonical README hello-world, `examples/.../InvoiceFileExample`,
and `ModernProfessional.create()` paths, so a visitor copying
any snippet into a fresh Maven project pulled at
`io.github.demchaav:graph-compose:1.6.8` gets compiling code.
Gallery enumerates the full **16-preset cv/v2 lineup** (15
paired cover letters; `MinimalUnderlined` ships without a
paired letter by design).
- `scripts/cut-release.ps1` learns a new `Update-SiteDepsVersion`
step so the Maven / Gradle install snippets in
`site/lib/deps.ts` flip in lockstep with the README + pom
versions at cut time — no more silent drift between the site
and the real released coordinates. The same release commit
now also stages `site/lib/deps.ts`.

## v1.6.7 — 2026-06-01

**Transitive dependency cleanup.** v1.6.7 narrows the runtime
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ GraphCompose uses PDFBox under the hood as the rendering backend &mdash; the com
| Generate a CV / cover letter from data | Layered templates | `ModernProfessional.create().compose(session, cvDocument)` &mdash; see [layered templates](./docs/templates/v2-layered/README.md) |
| Add a custom visual primitive | Engine extension | `NodeDefinition` + `PdfFragmentRenderHandler` &mdash; see [extension guide](./docs/contributing/extension-guide.md) |
| Regression-test generated layouts | Layout snapshots | `DocumentSession#layoutSnapshot()` &mdash; quickstart at [Testing your document](./docs/operations/test-your-document.md); full reference at [snapshot testing](./docs/operations/layout-snapshot-testing.md) |
| See the live playground / gallery | Next.js showcase site | [Showcase](https://DemchaAV.github.io/GraphCompose/) &mdash; source under [`site/`](./site), built with `next build` and deployed via the [Pages workflow](./.github/workflows/deploy-site.yml) |

## Installation

Expand Down
180 changes: 178 additions & 2 deletions scripts/cut-release.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,100 @@ function Update-ReadmeInstallVersion($readmePath, $newVersion) {
}
}

function Update-SiteDepsVersion($depsPath, $newVersion) {
# The Next.js showcase site (site/) embeds the Maven Central
# coordinates in `site/lib/deps.ts`. The pom-bump pipeline never
# touched this file before v1.6.8 (legacy site lives under docs/),
# so without this helper the next release would silently ship the
# site with an outdated <version> in the install snippet.
if (-not (Test-Path $depsPath)) {
Note "skip (no file): $depsPath"
return
}
$content = Get-Content $depsPath -Raw
$changed = $false
$replacements = @(
@{ Regex = [regex]'(?<=<version>)v?[\w\.\-]+(?=</version>)'; Value = $newVersion; Label = 'site Maven snippet' },
@{ Regex = [regex]"(?<=io\.github\.demchaav:graph-compose:)v?[\w\.\-]+(?=`")"; Value = $newVersion; Label = 'site Gradle snippet' }
)
foreach ($r in $replacements) {
$after = $r.Regex.Replace($content, $r.Value, 1)
if ($content -ne $after) {
$content = $after
$changed = $true
Note "bumped site/lib/deps.ts $($r.Label) -> $($r.Value)"
}
}
if (-not $changed) {
Note "no change: site/lib/deps.ts (already $newVersion?)"
return
}
if ($DryRun) {
Write-Host " [DRY RUN] site/lib/deps.ts -> $newVersion" -ForegroundColor Yellow
} else {
[System.IO.File]::WriteAllText($depsPath, $content)
}
}

function Update-SiteHeroVersion($heroPath, $newVersion) {
# site/components/Hero.tsx shows the Maven Central coordinates in
# the right-hand card. Without this bump the hero would lag the
# actual install snippet for one release cycle.
if (-not (Test-Path $heroPath)) { Note "skip (no file): $heroPath"; return }
$content = Get-Content $heroPath -Raw
$regex = [regex]'(?<=io\.github\.demchaav:graph-compose:)v?[\w\.\-]+(?=</b>)'
$after = $regex.Replace($content, $newVersion, 1)
if ($content -eq $after) {
Note "no change: site/components/Hero.tsx (already $newVersion?)"
return
}
if ($DryRun) {
Write-Host " [DRY RUN] site/components/Hero.tsx -> $newVersion" -ForegroundColor Yellow
} else {
[System.IO.File]::WriteAllText($heroPath, $after)
Note "bumped site/components/Hero.tsx -> $newVersion"
}
}

function Update-SitePresetsVersion($presetsPath, $newVersion) {
# site/lib/presets.tsx mentions the coordinates in the file's
# leading docstring so copy-pasters land on the right artifact.
if (-not (Test-Path $presetsPath)) { Note "skip (no file): $presetsPath"; return }
$content = Get-Content $presetsPath -Raw
$regex = [regex]'(?<=io\.github\.demchaav:graph-compose:)v?[\w\.\-]+(?=`)'
$after = $regex.Replace($content, $newVersion, 1)
if ($content -eq $after) {
Note "no change: site/lib/presets.tsx (already $newVersion?)"
return
}
if ($DryRun) {
Write-Host " [DRY RUN] site/lib/presets.tsx -> $newVersion" -ForegroundColor Yellow
} else {
[System.IO.File]::WriteAllText($presetsPath, $after)
Note "bumped site/lib/presets.tsx -> $newVersion"
}
}

function Update-SiteExamplesJsonTag($jsonPath, $tag) {
# `site/public/examples.json` is a copy of `docs/examples.json` used
# by the Gallery. Re-pin its source links from `/blob/develop/...`
# to `/blob/<tag>/...` so deep links survive future develop drift.
if (-not (Test-Path $jsonPath)) { Note "skip (no file): $jsonPath"; return }
$content = Get-Content $jsonPath -Raw
$regex = [regex]'(?<=https://github\.com/DemchaAV/GraphCompose/blob/)develop(?=/)'
$after = $regex.Replace($content, $tag)
if ($content -eq $after) {
Note "no change: site/public/examples.json (no /blob/develop/ links to pin?)"
return
}
if ($DryRun) {
Write-Host " [DRY RUN] site/public/examples.json: blob/develop -> blob/$tag" -ForegroundColor Yellow
} else {
[System.IO.File]::WriteAllText($jsonPath, $after)
Note "pinned site/public/examples.json /blob/develop -> /blob/$tag"
}
}

function Update-IndexHtmlVersion($indexHtmlPath, $newVersion) {
if (-not (Test-Path $indexHtmlPath)) {
Note "skip (no file): $indexHtmlPath"
Expand Down Expand Up @@ -286,6 +380,75 @@ function Update-ShowcaseGhBase($newRef) {
return $true
}

function Sync-SiteShowcase {
# Mirrors freshly-regenerated showcase artefacts from docs/ into
# site/public/ so the Next.js site doesn't drift from the legacy
# docs/ catalogue. Run AFTER Run-ShowcaseSync so the freshly-built
# PDFs / screenshots / manifest are picked up.
#
# What gets mirrored:
# docs/showcase/pdf/** → site/public/showcase/pdf/**
# docs/showcase/screenshots/** → site/public/showcase/screenshots/**
# docs/examples.json → site/public/examples.json
# docs/showcase/screenshots/templates/cv/cv-*-v2.png
# → site/public/previews/cv-v2/
# docs/showcase/screenshots/templates/coverletter/cover-letter-*-v2.png
# → site/public/previews/coverletter-v2/
#
# Doesn't touch the 3 Playground PDFs (hello/invoice/cv) — those have
# no generator yet, see future-work note in site/public/previews/README.md.
$docsShowcase = Join-Path $repoRoot 'docs/showcase'
$siteShowcase = Join-Path $repoRoot 'site/public/showcase'
$docsJson = Join-Path $repoRoot 'docs/examples.json'
$siteJson = Join-Path $repoRoot 'site/public/examples.json'
$cvSrcDir = Join-Path $docsShowcase 'screenshots/templates/cv'
$letterSrcDir = Join-Path $docsShowcase 'screenshots/templates/coverletter'
$cvDstDir = Join-Path $repoRoot 'site/public/previews/cv-v2'
$letterDstDir = Join-Path $repoRoot 'site/public/previews/coverletter-v2'

if (-not (Test-Path $docsShowcase)) {
Note "skip Sync-SiteShowcase: no docs/showcase yet"
return
}

if ($DryRun) {
Write-Host " [DRY RUN] mirror docs/showcase/{pdf,screenshots} -> site/public/showcase/" -ForegroundColor Yellow
Write-Host " [DRY RUN] copy docs/examples.json -> site/public/examples.json" -ForegroundColor Yellow
Write-Host " [DRY RUN] copy cv/v2 + coverletter/v2 PNGs -> site/public/previews/{cv-v2,coverletter-v2}/" -ForegroundColor Yellow
return
}

# Mirror showcase tree (deletes orphans on the site side to keep parity)
New-Item -ItemType Directory -Force -Path $siteShowcase | Out-Null
Copy-Item -Recurse -Force "$docsShowcase/pdf" $siteShowcase
Copy-Item -Recurse -Force "$docsShowcase/screenshots" $siteShowcase
Note "synced docs/showcase -> site/public/showcase"

# Manifest
if (Test-Path $docsJson) {
Copy-Item -Force $docsJson $siteJson
Note "synced docs/examples.json -> site/public/examples.json"
# Re-apply the /blob/develop -> /blob/<tag> pin in case
# docs/examples.json itself still points at develop (ShowcaseSync
# writes whatever GH_BASE Step 3 set in ShowcaseMetadata.java).
if ($script:tag) {
Update-SiteExamplesJsonTag $siteJson $script:tag
}
}

# Per-preset CV + cover-letter PNGs used by the Gallery hover overlay
if (Test-Path $cvSrcDir) {
New-Item -ItemType Directory -Force -Path $cvDstDir | Out-Null
Copy-Item -Force "$cvSrcDir/cv-*-v2.png" $cvDstDir
Note "synced cv-v2 preset previews -> site/public/previews/cv-v2/"
}
if (Test-Path $letterSrcDir) {
New-Item -ItemType Directory -Force -Path $letterDstDir | Out-Null
Copy-Item -Force "$letterSrcDir/cover-letter-*-v2.png" $letterDstDir
Note "synced coverletter-v2 preset previews -> site/public/previews/coverletter-v2/"
}
}

function Run-ShowcaseSync {
# Quote the -D argument: PowerShell's call operator drops the leading
# '-D' on the way to mvnw.cmd, so Maven sees ".mainClass=..." as a
Expand Down Expand Up @@ -433,6 +596,10 @@ try {
Update-PomVersion (Join-Path $repoRoot 'benchmarks/pom.xml') $Version
Update-ReadmeInstallVersion (Join-Path $repoRoot 'README.md') $Version
Update-IndexHtmlVersion (Join-Path $repoRoot 'docs/index.html') $Version
Update-SiteDepsVersion (Join-Path $repoRoot 'site/lib/deps.ts') $Version
Update-SiteHeroVersion (Join-Path $repoRoot 'site/components/Hero.tsx') $Version
Update-SitePresetsVersion (Join-Path $repoRoot 'site/lib/presets.tsx') $Version
Update-SiteExamplesJsonTag (Join-Path $repoRoot 'site/public/examples.json') $tag

Step 2 "Update CHANGELOG date for v$Version"
$changelog = Join-Path $repoRoot 'CHANGELOG.md'
Expand All @@ -459,6 +626,7 @@ try {

Step 4 "Regenerate docs/examples.json with $tag links"
Run-ShowcaseSync
Sync-SiteShowcase

if (-not $SkipVerify) {
Step 5 "Run mvnw verify (sanity check)"
Expand All @@ -482,7 +650,7 @@ try {
Step 6 "Commit release"
$commitMsg = "Release v$Version"
if ($DryRun) {
Write-Host " [DRY RUN] git add pom.xml aggregator/pom.xml examples/pom.xml benchmarks/pom.xml README.md CHANGELOG.md examples/src/main/java/com/demcha/examples/support/ShowcaseMetadata.java docs/examples.json docs/index.html" -ForegroundColor Yellow
Write-Host " [DRY RUN] git add pom.xml aggregator/pom.xml examples/pom.xml benchmarks/pom.xml README.md CHANGELOG.md examples/src/main/java/com/demcha/examples/support/ShowcaseMetadata.java docs/examples.json docs/index.html docs/showcase site/lib/deps.ts site/components/Hero.tsx site/lib/presets.tsx site/public/examples.json site/public/showcase site/public/previews/cv-v2 site/public/previews/coverletter-v2" -ForegroundColor Yellow
Write-Host " [DRY RUN] git commit -m `"$commitMsg`"" -ForegroundColor Yellow
} else {
git add `
Expand All @@ -494,7 +662,15 @@ try {
CHANGELOG.md `
examples/src/main/java/com/demcha/examples/support/ShowcaseMetadata.java `
docs/examples.json `
docs/index.html
docs/index.html `
docs/showcase `
site/lib/deps.ts `
site/components/Hero.tsx `
site/lib/presets.tsx `
site/public/examples.json `
site/public/showcase `
site/public/previews/cv-v2 `
site/public/previews/coverletter-v2
git commit -m $commitMsg
Note "commit: $commitMsg"
}
Expand Down
25 changes: 25 additions & 0 deletions site/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# dependencies
/node_modules

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*

# typescript
*.tsbuildinfo

# env
.env*.local
Loading