Skip to content

feat(starters): add htmx+go and fix go starter#132

Open
jguzanvidia wants to merge 1 commit into
mainfrom
topic/go-htmx-starter
Open

feat(starters): add htmx+go and fix go starter#132
jguzanvidia wants to merge 1 commit into
mainfrom
topic/go-htmx-starter

Conversation

@jguzanvidia

@jguzanvidia jguzanvidia commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

• Added the HTMX + Go starter with a Go-rendered page, HTMX fragment endpoint, refresh-button with swap, agent support, CLI metadata, starter archive wiring, docs updates, and HTMX logo • Fixed the existing Go starter by correcting bad Elements bundle URLs, loading CSS and JS from the right packages, removing the frontend dependency/setup path, fixing stale copy, updating source links, simplifying template data • More Go server functionality with PORT support, root-only routing, explicit HTML content type, and template execution error handling. • Go and HTMX+Go starters are freed from frontend build tooling by using browser CDN bundles, excluding local build/cache outputs, skipping Elements dependency setup, and stamping CDN bundle versions during archive generation. • Test updates including Elements version stamping logic

Summary by CodeRabbit

  • New Features

    • Added "HTMX + Go" integration starter with server-rendered fragment endpoint and demo page using Elements + HTMX
    • New starter available in site integrations and starter listings
  • Improvements

    • Updated Go starter and starter templates for clearer run/build workflow and environment-driven port
    • Site updates: docs, navigation entry, integration card, and new HTMX logo attribution
    • Starters now include stamped CDN asset versions for Elements bundles
  • Documentation

    • New and revised docs/README/AGENTS guidance for Go and HTMX starters

@jguzanvidia jguzanvidia requested a review from coryrylan June 11, 2026 17:07
@github-actions github-actions Bot added scope(ci) scope(internals) scope(docs) dependencies Pull requests that update a dependency file github_actions Pull requests that update GitHub Actions code scope(starters) labels Jun 11, 2026
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds a Go+HTMX starter, refactors the existing Go starter, implements Elements CDN version stamping for starters, updates ProjectService to conditionally run dependency setup based on starter metadata, and updates CI/workspace and site documentation to register the new starter.

Changes

Go and Go+HTMX Starters

Layer / File(s) Summary
Complete change set
(.github/actions/setup-ci/action.yml, package.json, pnpm-workspace.yaml, projects/internals/tools/src/project/service.ts, projects/internals/tools/src/project/service.test.ts, projects/internals/tools/src/project/starters.ts, projects/internals/tools/src/project/starters.test.ts, projects/starters/go/**, projects/starters/go-htmx/**, projects/site/**, .prettierignore, projects/starters/package.json)
Adds Go toolchain setup in CI, registers new go-htmx workspace and package tasks, updates ProjectService to skip element dependency setup per-starter, implements CDN version stamping for starters and exposes helpers, refactors Go starter runtime and build wiring, adds a new go-htmx starter (server, templates, docs, wireit config), and updates site docs, navigation, logos, and notice files.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested labels

scope(code), scope(cli), scope(media)

Suggested reviewers

  • jareddlc
  • johnyanarella
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main changes: adding a new HTMX+Go starter and fixing the existing Go starter with bundle URL corrections and simplified templating.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch topic/go-htmx-starter

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install timed out. The project may have too many dependencies for the sandbox.


Comment @coderabbitai help to get the list of available commands and usage tips.

@jguzanvidia jguzanvidia self-assigned this Jun 11, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@projects/internals/tools/src/project/service.ts`:
- Around line 64-67: The code mixes a synchronous call and an awaited async call
in a single reports.push(...) which reduces clarity; make the async sequencing
explicit by computing or awaiting the values before pushing: call
starterShouldSetupElementsDependencies(type) and then either (a) call const
setupReport = setupProject(projectDir); const updateReport = await
updateProject(projectDir); and push reports.push(setupReport, updateReport) or
(b) await both sequentially with const setupReport = await
setupProject(projectDir); const updateReport = await updateProject(projectDir);
then push; update the code referencing setupProject, updateProject,
starterShouldSetupElementsDependencies, and the reports array accordingly so
there is no mixing of awaited and non-awaited expressions inside reports.push.

In `@projects/internals/tools/src/project/starters.ts`:
- Around line 210-220: The function stampStarterCDNVersionFiles currently
hardcodes the index location via join(dist, 'src/index.html'), which will break
for starters with different layouts; update stampStarterCDNVersionFiles to
resolve the index path per-starter (e.g., add a mapping or config keyed by
projectDir/starter name that returns the relative index path) or implement a
small resolver that checks a list of candidate locations (like 'src/index.html',
'public/index.html', 'index.html') before failing; use the existing
starterDirsWithStampedCDNVersions key or augment it to include the
relativeIndexPath so stampStarterCDNVersionFiles can read the correct file, and
add a brief comment documenting the assumption/behavior.
- Around line 21-22: The REPO_WORKSPACE_DIR constant points two levels up but
must point five levels up from projects/internals/tools/src/project/starters.ts;
update REPO_WORKSPACE_DIR to the correct relative path (use '../../../../../')
so calls in getStarterCDNPackageVersions and readWorkspaceManifest resolve the
actual repository root and workspace manifest correctly.

In `@projects/site/src/_11ty/layouts/common.js`:
- Line 151: The "HTMX + Go" nve-tree-node (href "docs/integrations/go-htmx/") is
currently placed between Golang and Hugo and breaks strict alphabetical
ordering; decide whether the nav should be strictly alphabetical or
intentionally grouped by Go integrations, then either move this nve-tree-node so
its anchor label "HTMX + Go" is placed in the correct alphabetical position
among the other integration nodes, or keep its current position and add a short
code comment near the node indicating intentional grouping (so future editors
understand the choice).

In `@projects/site/src/docs/integrations/go-htmx.md`:
- Line 17: Split the long sentence into 2–3 shorter sentences that each state a
single fact: e.g., one sentence stating that the starter uses the pre-built
Elements CSS and JavaScript bundles, another that HTMX is loaded in the base
HTML page, and a final short sentence that explains the app renders “/” as the
full page and serves “/fragment/time” as a fragment response returning only the
refresh button's swap target; update the paragraph mentioning Elements, HTMX,
“/” and “/fragment/time” accordingly for clarity.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 4b46ca1a-0e23-4de2-ac00-98dce9cd5414

📥 Commits

Reviewing files that changed from the base of the PR and between 59d8349 and 524795b.

⛔ Files ignored due to path filters (2)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • projects/site/public/static/images/integrations/htmx.svg is excluded by !**/*.svg
📒 Files selected for processing (30)
  • .github/actions/setup-ci/action.yml
  • package.json
  • pnpm-workspace.yaml
  • projects/internals/tools/src/project/service.test.ts
  • projects/internals/tools/src/project/service.ts
  • projects/internals/tools/src/project/starters.test.ts
  • projects/internals/tools/src/project/starters.ts
  • projects/internals/tools/src/skills/about.md
  • projects/site/public/static/images/integrations/NOTICE
  • projects/site/src/_11ty/layouts/common.js
  • projects/site/src/_11ty/shortcodes/svg-logo.js
  • projects/site/src/docs/integrations/go-htmx.md
  • projects/site/src/docs/integrations/go.md
  • projects/site/src/docs/integrations/index.11ty.js
  • projects/site/src/index.11tydata.js
  • projects/starters/README.md
  • projects/starters/go-htmx/.gitignore
  • projects/starters/go-htmx/AGENTS.md
  • projects/starters/go-htmx/README.md
  • projects/starters/go-htmx/main.go
  • projects/starters/go-htmx/package.json
  • projects/starters/go-htmx/src/index.html
  • projects/starters/go-htmx/src/time.html
  • projects/starters/go/.gitignore
  • projects/starters/go/AGENTS.md
  • projects/starters/go/README.md
  • projects/starters/go/main.go
  • projects/starters/go/package.json
  • projects/starters/go/src/index.html
  • projects/starters/package.json

Comment on lines +64 to +67
const reports = [createReport, agentReport];
if (starterShouldSetupElementsDependencies(type)) {
reports.push(setupProject(projectDir), await updateProject(projectDir));
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial | 💤 Low value

Consider clarity: mixing sync and async calls in reports.push().

Line 66 pushes both a synchronous setupProject(projectDir) call and an awaited updateProject(projectDir) call to the reports array. While functionally correct (both resolve before being pushed), this pattern is subtle and may reduce readability for future maintainers.

♻️ Optional: Make the async sequencing explicit
   const reports = [createReport, agentReport];
   if (starterShouldSetupElementsDependencies(type)) {
-    reports.push(setupProject(projectDir), await updateProject(projectDir));
+    const setupProjectReport = setupProject(projectDir);
+    const updateProjectReport = await updateProject(projectDir);
+    reports.push(setupProjectReport, updateProjectReport);
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@projects/internals/tools/src/project/service.ts` around lines 64 - 67, The
code mixes a synchronous call and an awaited async call in a single
reports.push(...) which reduces clarity; make the async sequencing explicit by
computing or awaiting the values before pushing: call
starterShouldSetupElementsDependencies(type) and then either (a) call const
setupReport = setupProject(projectDir); const updateReport = await
updateProject(projectDir); and push reports.push(setupReport, updateReport) or
(b) await both sequentially with const setupReport = await
setupProject(projectDir); const updateReport = await updateProject(projectDir);
then push; update the code referencing setupProject, updateProject,
starterShouldSetupElementsDependencies, and the reports array accordingly so
there is no mixing of awaited and non-awaited expressions inside reports.push.

Comment on lines +21 to +22
const ELEMENTS_CDN_BASE_URL = 'https://esm.sh';
const REPO_WORKSPACE_DIR = '../../';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Critical: Incorrect relative path to repository root.

REPO_WORKSPACE_DIR = '../../' is incorrect for the location of this file. From projects/internals/tools/src/project/starters.ts, the repo root is 5 levels up, not 2.

This will cause getStarterCDNPackageVersions (line 216) and readWorkspaceManifest (line 224) to fail or use the wrong directory.

🐛 Proposed fix
-const REPO_WORKSPACE_DIR = '../../';
+const REPO_WORKSPACE_DIR = '../../../../../';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const ELEMENTS_CDN_BASE_URL = 'https://esm.sh';
const REPO_WORKSPACE_DIR = '../../';
const ELEMENTS_CDN_BASE_URL = 'https://esm.sh';
const REPO_WORKSPACE_DIR = '../../../../../';
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@projects/internals/tools/src/project/starters.ts` around lines 21 - 22, The
REPO_WORKSPACE_DIR constant points two levels up but must point five levels up
from projects/internals/tools/src/project/starters.ts; update REPO_WORKSPACE_DIR
to the correct relative path (use '../../../../../') so calls in
getStarterCDNPackageVersions and readWorkspaceManifest resolve the actual
repository root and workspace manifest correctly.

Comment on lines +210 to +220
async function stampStarterCDNVersionFiles(projectDir: string, dist: string) {
if (!starterDirsWithStampedCDNVersions.has(projectDir)) {
return;
}

const indexPath = join(dist, 'src/index.html');
const repoRoot = resolve(REPO_WORKSPACE_DIR);
const versions = getStarterCDNPackageVersions(repoRoot);
const content = await readFile(indexPath, 'utf8');
await writeFile(indexPath, stampStarterCDNVersions(content, versions));
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial | ⚖️ Poor tradeoff

Consider: Hardcoded index file path.

Line 215 hardcodes 'src/index.html' for all stamped starters. While this works for the current go and go-htmx starters, this assumption may break if future starters use a different template structure.

Consider adding a configurable path per starter if the structure is expected to vary, or document the assumption in a comment.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@projects/internals/tools/src/project/starters.ts` around lines 210 - 220, The
function stampStarterCDNVersionFiles currently hardcodes the index location via
join(dist, 'src/index.html'), which will break for starters with different
layouts; update stampStarterCDNVersionFiles to resolve the index path
per-starter (e.g., add a mapping or config keyed by projectDir/starter name that
returns the relative index path) or implement a small resolver that checks a
list of candidate locations (like 'src/index.html', 'public/index.html',
'index.html') before failing; use the existing starterDirsWithStampedCDNVersions
key or augment it to include the relativeIndexPath so
stampStarterCDNVersionFiles can read the correct file, and add a brief comment
documenting the assumption/behavior.

<nve-tree-node ${data.page.url.includes('/docs/integrations/bundles/') ? 'highlighted selected' : ''}><a href="docs/integrations/bundles/">Bundles</a></nve-tree-node>
<nve-tree-node ${data.page.url.includes('/docs/integrations/custom-elements/') ? 'highlighted selected' : ''}><a href="docs/integrations/custom-elements/">Custom Elements</a></nve-tree-node>
<nve-tree-node ${data.page.url.includes('/docs/integrations/go/') ? 'highlighted selected' : ''}><a href="docs/integrations/go/">Golang</a></nve-tree-node>
<nve-tree-node ${data.page.url.includes('/docs/integrations/go-htmx/') ? 'highlighted selected' : ''}><a href="docs/integrations/go-htmx/">HTMX + Go</a></nve-tree-node>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial | 💤 Low value

Consider navigation ordering.

The "HTMX + Go" entry is placed between "Golang" and "Hugo". While this groups Go-related integrations together, it breaks strict alphabetical ordering. Verify whether this intentional grouping is preferred over alphabetical consistency in the navigation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@projects/site/src/_11ty/layouts/common.js` at line 151, The "HTMX + Go"
nve-tree-node (href "docs/integrations/go-htmx/") is currently placed between
Golang and Hugo and breaks strict alphabetical ordering; decide whether the nav
should be strictly alphabetical or intentionally grouped by Go integrations,
then either move this nve-tree-node so its anchor label "HTMX + Go" is placed in
the correct alphabetical position among the other integration nodes, or keep its
current position and add a short code comment near the node indicating
intentional grouping (so future editors understand the choice).


The HTMX + Go starter extends the Go starter with one server-rendered fragment endpoint for HTMX swaps.

The starter uses the pre-built Elements CSS and JavaScript bundles, loads HTMX in the base HTML page, renders `/` as the full page, and serves `/fragment/time` as a fragment response that returns only the refresh button's swap target.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Consider breaking this long sentence into multiple sentences for readability.

This sentence contains multiple independent facts (uses pre-built bundles, loads HTMX, renders /, serves /fragment/time). Breaking it into 2-3 shorter sentences would improve clarity and align better with concise documentation style.

Suggested rewording
-The starter uses the pre-built Elements CSS and JavaScript bundles, loads HTMX in the base HTML page, renders `/` as the full page, and serves `/fragment/time` as a fragment response that returns only the refresh button's swap target.
+The starter uses the pre-built Elements CSS and JavaScript bundles. It loads HTMX in the base HTML page and renders `/` as the full page. The `/fragment/time` endpoint serves a fragment response that returns only the refresh button's swap target.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
The starter uses the pre-built Elements CSS and JavaScript bundles, loads HTMX in the base HTML page, renders `/` as the full page, and serves `/fragment/time` as a fragment response that returns only the refresh button's swap target.
The starter uses the pre-built Elements CSS and JavaScript bundles. It loads HTMX in the base HTML page and renders `/` as the full page. The `/fragment/time` endpoint serves a fragment response that returns only the refresh button's swap target.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@projects/site/src/docs/integrations/go-htmx.md` at line 17, Split the long
sentence into 2–3 shorter sentences that each state a single fact: e.g., one
sentence stating that the starter uses the pre-built Elements CSS and JavaScript
bundles, another that HTMX is loaded in the base HTML page, and a final short
sentence that explains the app renders “/” as the full page and serves
“/fragment/time” as a fragment response returning only the refresh button's swap
target; update the paragraph mentioning Elements, HTMX, “/” and “/fragment/time”
accordingly for clarity.

Source: Coding guidelines

- uses: actions/setup-go@v6
with:
go-version: 'stable'
cache: false

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are going to add Go as a runtime dependency for our CI we should update our dev env setup instructions to ensure the correct Go version is added as well. https://github.com/NVIDIA/elements#setup


const { ProjectService } = await import('./service.js');
const result = await ProjectService.create({ type: 'typescript', cwd: '/test', start: false });
const result = await ProjectService.create({ type: 'default', cwd: '/test', start: false });

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this likely should remain 'typescript' since 'default' is not a type option for the starters and would change the MCP schema as well.


const { ProjectService } = await import('./service.js');
await ProjectService.create({ type: 'typescript', cwd: '/test', start: true });
await ProjectService.create({ type: 'default', cwd: '/test', start: true });

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this likely should remain 'typescript' since 'default' is not a type option for the starters and would change the MCP schema as well.

<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="A simple starter using Elements, HTMX, and Go." />
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon" />
<!-- Starter archive generation stamps these Elements CDN URLs with current package versions. -->

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stamping the versions seems reasonable, if the comment is not used for matching where to match the stamping/regex I'd drop it. Otherwise it will be in the generated output which the user doesnt really need to know the implementation details of how its stamped out.

• Added the HTMX + Go starter with a Go-rendered page, HTMX fragment endpoint, refresh-button with swap, agent support, CLI metadata, starter archive wiring, docs updates, and HTMX logo
• Fixed the existing Go starter by correcting bad Elements bundle URLs, loading CSS and JS from the right packages, removing the frontend dependency/setup path, fixing stale copy, updating source links, simplifying template data
• More Go server functionality with PORT support, root-only routing, explicit HTML content type, and template execution error handling.
• Go and HTMX+Go starters are freed from frontend build tooling by using browser CDN bundles, excluding local build/cache outputs, skipping Elements dependency setup, and stamping CDN bundle versions during archive generation.
• Test updates including Elements version stamping logic

Signed-off-by: Jake Guza <jguza@nvidia.com>
@jguzanvidia jguzanvidia force-pushed the topic/go-htmx-starter branch from 524795b to 013d8af Compare June 12, 2026 12:32

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

♻️ Duplicate comments (2)
projects/internals/tools/src/project/service.test.ts (1)

15-19: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use real starter ids in this mock catalog.

These mocked keys (default, static, hidden) are not members of the real Starter union from projects/internals/tools/src/project/starters.ts, so the calls on Line 51, Line 72, Line 95, and Line 112 drift from the actual MCP schema and can fail type-checking. Use existing starters instead—e.g. typescript for the default path and go or go-htmx for the opt-out path this PR adds.

💡 Suggested update
 vi.mock('./starters.js', () => ({
   startersData: {
-    default: { cli: true, zip: 'default.zip' },
-    static: { cli: true, zip: 'static.zip', setupElementsDependencies: false },
-    hidden: { cli: false, zip: 'hidden.zip', setupElementsDependencies: false }
+    typescript: { cli: true, zip: 'typescript.zip' },
+    go: { cli: true, zip: 'go.zip', setupElementsDependencies: false },
+    lit: { cli: false, zip: null }
   },
   createStarter: vi.fn(),
   startStarter: vi.fn()
 }));

Then update the affected calls/assertions to use typescript and go.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@projects/internals/tools/src/project/service.test.ts` around lines 15 - 19,
The test mock uses invalid starter keys; replace the fake keys in the
startersData mock with real Starter ids (e.g., change the `default` key to
`typescript` and the opt-out key to `go` or `go-htmx`) so the mock shape matches
the real union from starters.ts; then update the related assertions/calls that
reference those starters (the tests that currently reference the old keys) to
use `typescript` and `go` (or `go-htmx`) so the tests align with the actual MCP
schema and type definitions.
projects/internals/tools/src/project/starters.ts (1)

21-22: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Anchor the workspace root to this module, not process.cwd().

REPO_WORKSPACE_DIR = '../../' is later fed into resolve() and readWorkspaceManifest(), so a repo-root invocation resolves outside the repository. That breaks both CDN version lookup in stampStarterCDNVersionFiles() (Line 216) and workspace manifest export in exportPackageFromWorkspace() (Line 224). Compute the repo root from import.meta.url here instead of keeping a cwd-relative string.

💡 Minimal fix
+import { fileURLToPath } from 'node:url';
 import { basename, dirname, join, parse, resolve } from 'node:path';
 ...
-const REPO_WORKSPACE_DIR = '../../';
+const REPO_WORKSPACE_DIR = resolve(dirname(fileURLToPath(import.meta.url)), '../../../../../');
...
-  const repoRoot = resolve(REPO_WORKSPACE_DIR);
+  const repoRoot = REPO_WORKSPACE_DIR;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@projects/internals/tools/src/project/starters.ts` around lines 21 - 22,
REPO_WORKSPACE_DIR currently uses a cwd-relative string which causes
resolve()/readWorkspaceManifest() to point outside the repo; change it to
compute the repository root from this module's location using import.meta.url
(e.g. derive a file:// path and resolve up to repo root) and replace the
'../../' constant; update any uses in stampStarterCDNVersionFiles and
exportPackageFromWorkspace (and calls to resolve()/readWorkspaceManifest) to use
the new repo-root constant so CDN version lookup and workspace manifest export
resolve inside the repository.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/actions/setup-ci/action.yml:
- Around line 16-19: The workflow uses actions/setup-go@v6 with go-version:
'stable', which is non-deterministic; replace the 'stable' value with a pinned
semantic version (e.g., '1.20.x' or a specific patch like '1.20.7') in the
action.yml go-version field so CI uses a fixed Go release; update the go-version
entry where actions/setup-go@v6 is declared to a specific version string and, if
desired, add a comment explaining the chosen pinned version.

In `@projects/starters/go-htmx/AGENTS.md`:
- Around line 7-9: Update the three bullets in the "Integration Points" section
so they don't all start with "Render"; pick at least one bullet to begin with a
different verb or preposition (e.g., "Use", "Serve", "Through", or "Via") while
keeping the same meaning for lines that mention "Elements markup through
`html/template` in `src/index.html`", "the full page through the root route",
and "HTMX swap content through fragment templates under `src/`". Ensure sentence
structure and punctuation remain consistent with the other bullets.

In `@projects/starters/go-htmx/main.go`:
- Around line 63-64: The code currently sends raw template errors
(templateError.Error()) in HTTP responses; change both occurrences to return a
generic client message (e.g., http.Error(w, "Internal Server Error",
http.StatusInternalServerError)) and log the full error server-side instead
(e.g., log.Printf or your app logger with the templateError value). Replace the
two http.Error calls that reference templateError with the generic message and
add a server-side log call immediately before each return to capture the full
templateError for debugging.

In `@projects/starters/go-htmx/src/index.html`:
- Around line 24-25: Update all anchor elements that use target="_blank" (e.g.,
the "Documentation" <a> element in index.html and the other external links
referenced at lines noted) to include rel="noopener noreferrer"; locate each
anchor with target="_blank" (instances near the "Documentation" link and the
other occurrences) and add the rel attribute to prevent window.opener access and
improve security.

In `@projects/starters/go/main.go`:
- Around line 51-53: Replace the direct exposure of templateError in HTTP
responses with server-side logging and a generic client message: where the code
currently calls http.Error(w, templateError.Error(),
http.StatusInternalServerError) (the occurrences using the templateError
variable in the request handler), change it to log the detailed error (e.g.,
log.Printf("template execution error: %v", templateError) or use the existing
logger) and call http.Error(w, "Internal Server Error",
http.StatusInternalServerError) so internal paths/details are not returned to
clients; apply this change to both occurrences handling templateError.

In `@projects/starters/go/README.md`:
- Around line 7-9: The README's "Commands / npm scripts" lines for `dev`,
`build`, and `preview` are inconsistent with the package.json scripts; update
the README so each listed npm script (`dev`, `build`, `preview`) documents the
actual commands defined in projects/starters/go/package.json (e.g., note that
`build` runs `wireit` rather than a direct `go build`), keeping the labels as
npm scripts and ensuring the `dev`, `build`, and `preview` entries match the
package.json script behavior and wording.

In `@projects/starters/go/src/index.html`:
- Line 22: The external anchor tags that use target="_blank" (e.g., the <a
href="https://nvidia.github.io/elements/docs/integrations/go/" target="_blank">
inside the <nve-button container="flat"> element and the other similar anchors)
are missing rel="noopener noreferrer"; update each anchor with target="_blank"
to include rel="noopener noreferrer" to prevent reverse-tabnabbing and ensure
safe external links.

---

Duplicate comments:
In `@projects/internals/tools/src/project/service.test.ts`:
- Around line 15-19: The test mock uses invalid starter keys; replace the fake
keys in the startersData mock with real Starter ids (e.g., change the `default`
key to `typescript` and the opt-out key to `go` or `go-htmx`) so the mock shape
matches the real union from starters.ts; then update the related
assertions/calls that reference those starters (the tests that currently
reference the old keys) to use `typescript` and `go` (or `go-htmx`) so the tests
align with the actual MCP schema and type definitions.

In `@projects/internals/tools/src/project/starters.ts`:
- Around line 21-22: REPO_WORKSPACE_DIR currently uses a cwd-relative string
which causes resolve()/readWorkspaceManifest() to point outside the repo; change
it to compute the repository root from this module's location using
import.meta.url (e.g. derive a file:// path and resolve up to repo root) and
replace the '../../' constant; update any uses in stampStarterCDNVersionFiles
and exportPackageFromWorkspace (and calls to resolve()/readWorkspaceManifest) to
use the new repo-root constant so CDN version lookup and workspace manifest
export resolve inside the repository.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: e1474610-8e10-46a4-9d23-48863b6f4597

📥 Commits

Reviewing files that changed from the base of the PR and between 524795b and 013d8af.

⛔ Files ignored due to path filters (2)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • projects/site/public/static/images/integrations/htmx.svg is excluded by !**/*.svg
📒 Files selected for processing (31)
  • .github/actions/setup-ci/action.yml
  • .prettierignore
  • package.json
  • pnpm-workspace.yaml
  • projects/internals/tools/src/project/service.test.ts
  • projects/internals/tools/src/project/service.ts
  • projects/internals/tools/src/project/starters.test.ts
  • projects/internals/tools/src/project/starters.ts
  • projects/internals/tools/src/skills/about.md
  • projects/site/public/static/images/integrations/NOTICE
  • projects/site/src/_11ty/layouts/common.js
  • projects/site/src/_11ty/shortcodes/svg-logo.js
  • projects/site/src/docs/integrations/go-htmx.md
  • projects/site/src/docs/integrations/go.md
  • projects/site/src/docs/integrations/index.11ty.js
  • projects/site/src/index.11tydata.js
  • projects/starters/README.md
  • projects/starters/go-htmx/.gitignore
  • projects/starters/go-htmx/AGENTS.md
  • projects/starters/go-htmx/README.md
  • projects/starters/go-htmx/main.go
  • projects/starters/go-htmx/package.json
  • projects/starters/go-htmx/src/index.html
  • projects/starters/go-htmx/src/time.html
  • projects/starters/go/.gitignore
  • projects/starters/go/AGENTS.md
  • projects/starters/go/README.md
  • projects/starters/go/main.go
  • projects/starters/go/package.json
  • projects/starters/go/src/index.html
  • projects/starters/package.json

Comment on lines +16 to +19
- uses: actions/setup-go@v6
with:
go-version: 'stable'
cache: false

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify whether the repo already declares a canonical Go version
# and where CI/docs should align.

set -euo pipefail

echo "== Go module files =="
fd -HI '^go\.mod$'

echo
echo "== Declared Go versions in go.mod files =="
fd -HI '^go\.mod$' -x sh -c '
  file="$1"
  ver=$(awk "/^go / { print \$2; exit }" "$file")
  toolchain=$(awk "/^toolchain / { print \$2; exit }" "$file")
  echo "$file :: go=${ver:-<none>} toolchain=${toolchain:-<none>}"
' sh {}

echo
echo "== CI setup-go declarations =="
rg -n -C2 "setup-go|go-version|go-version-file" .github/actions .github/workflows

echo
echo "== Dev/setup docs mentioning Go version =="
rg -n -C2 "Go version|go version|golang|setup.*go" README.md .github projects/starters --glob "*.md"

Repository: NVIDIA/elements

Length of output: 674


Pin Go to a deterministic version instead of stable

.github/actions/setup-ci/action.yml (lines 16-19) sets go-version: 'stable', which can drift over time and break CI reproducibility; no other Go version source (no go.mod, no other setup-go/go-version declarations in CI or docs) was found to align on.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/actions/setup-ci/action.yml around lines 16 - 19, The workflow uses
actions/setup-go@v6 with go-version: 'stable', which is non-deterministic;
replace the 'stable' value with a pinned semantic version (e.g., '1.20.x' or a
specific patch like '1.20.7') in the action.yml go-version field so CI uses a
fixed Go release; update the go-version entry where actions/setup-go@v6 is
declared to a specific version string and, if desired, add a comment explaining
the chosen pinned version.

Comment on lines +7 to +9
- Render Elements markup through `html/template` in `src/index.html`.
- Render the full page through the root route.
- Render HTMX swap content through fragment templates under `src/`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Vary sentence-start words in the Integration Points section.

Lines 7, 8, and 9 all begin with "Render," which violates write-good prose style rules about sentence variety. Restructure at least one bullet to start with a different verb or preposition.

✏️ Example rewording
 - Render Elements markup through `html/template` in `src/index.html`.
 - Render the full page through the root route.
-- Render HTMX swap content through fragment templates under `src/`.
+- Keep HTMX swap content in fragment templates under `src/` and return only the target fragment.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- Render Elements markup through `html/template` in `src/index.html`.
- Render the full page through the root route.
- Render HTMX swap content through fragment templates under `src/`.
- Render Elements markup through `html/template` in `src/index.html`.
- Render the full page through the root route.
- Keep HTMX swap content in fragment templates under `src/` and return only the target fragment.
🧰 Tools
🪛 LanguageTool

[style] ~9-~9: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...the full page through the root route. - Render HTMX swap content through fragment temp...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@projects/starters/go-htmx/AGENTS.md` around lines 7 - 9, Update the three
bullets in the "Integration Points" section so they don't all start with
"Render"; pick at least one bullet to begin with a different verb or preposition
(e.g., "Use", "Serve", "Through", or "Via") while keeping the same meaning for
lines that mention "Elements markup through `html/template` in
`src/index.html`", "the full page through the root route", and "HTMX swap
content through fragment templates under `src/`". Ensure sentence structure and
punctuation remain consistent with the other bullets.

Source: Coding guidelines

Comment on lines +63 to +64
http.Error(w, templateError.Error(), http.StatusInternalServerError)
return

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid returning raw template errors to clients.

Line 63 and Line 70 send internal template parse/execute errors directly in HTTP responses, which can leak filesystem paths and implementation details. Return a generic message to clients and log full details server-side.

Proposed fix
 func renderTemplate(w http.ResponseWriter, templatePath string, data interface{}, templatePaths ...string) {
   paths := append([]string{templatePath}, templatePaths...)
   tmpl, templateError := template.ParseFiles(paths...)
   if templateError != nil {
-    http.Error(w, templateError.Error(), http.StatusInternalServerError)
+    fmt.Printf("template parse error path=%s err=%v\n", templatePath, templateError)
+    http.Error(w, "Internal Server Error", http.StatusInternalServerError)
     return
   }

   w.Header().Set("Content-Type", "text/html; charset=utf-8")
   templateError = tmpl.ExecuteTemplate(w, filepath.Base(templatePath), data)
   if templateError != nil {
-    http.Error(w, templateError.Error(), http.StatusInternalServerError)
+    fmt.Printf("template render error path=%s err=%v\n", templatePath, templateError)
+    http.Error(w, "Internal Server Error", http.StatusInternalServerError)
   }
 }

Also applies to: 70-71

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@projects/starters/go-htmx/main.go` around lines 63 - 64, The code currently
sends raw template errors (templateError.Error()) in HTTP responses; change both
occurrences to return a generic client message (e.g., http.Error(w, "Internal
Server Error", http.StatusInternalServerError)) and log the full error
server-side instead (e.g., log.Printf or your app logger with the templateError
value). Replace the two http.Error calls that reference templateError with the
generic message and add a server-side log call immediately before each return to
capture the full templateError for debugging.

Comment on lines +24 to +25
><a href="https://nvidia.github.io/elements/docs/integrations/go-htmx/" target="_blank"
>Documentation</a

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add rel="noopener noreferrer" to all target="_blank" links.

These anchors open external pages with target="_blank" but no rel protection, enabling opener access.

Proposed fix
-<a href="https://nvidia.github.io/elements/docs/integrations/go-htmx/" target="_blank"
+<a href="https://nvidia.github.io/elements/docs/integrations/go-htmx/" target="_blank" rel="noopener noreferrer"
 ...
-<a href="https://github.com/NVIDIA/elements/" target="_blank">GitHub</a>
+<a href="https://github.com/NVIDIA/elements/" target="_blank" rel="noopener noreferrer">GitHub</a>
 ...
-<a target="_blank" href="https://nvidia.github.io/elements/docs/integrations/go-htmx/"
+<a target="_blank" rel="noopener noreferrer" href="https://nvidia.github.io/elements/docs/integrations/go-htmx/"
 ...
-<a target="_blank" href="https://github.com/NVIDIA/elements/tree/main/projects/starters/go-htmx"
+<a target="_blank" rel="noopener noreferrer" href="https://github.com/NVIDIA/elements/tree/main/projects/starters/go-htmx"
 ...
-<a nve-text="body sm" target="_blank" href="https://nvidia.github.io/elements/docs/integrations/go-htmx/"
+<a nve-text="body sm" target="_blank" rel="noopener noreferrer" href="https://nvidia.github.io/elements/docs/integrations/go-htmx/"
 ...
-<a nve-text="body sm" target="_blank" href="https://github.com/NVIDIA/elements/tree/main/projects/starters/go-htmx"
+<a nve-text="body sm" target="_blank" rel="noopener noreferrer" href="https://github.com/NVIDIA/elements/tree/main/projects/starters/go-htmx"

Also applies to: 30-30, 37-37, 42-42, 70-70, 75-75

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@projects/starters/go-htmx/src/index.html` around lines 24 - 25, Update all
anchor elements that use target="_blank" (e.g., the "Documentation" <a> element
in index.html and the other external links referenced at lines noted) to include
rel="noopener noreferrer"; locate each anchor with target="_blank" (instances
near the "Documentation" link and the other occurrences) and add the rel
attribute to prevent window.opener access and improve security.

Comment on lines 51 to 53
if templateError != nil {
http.Error(w, templateError.Error(), http.StatusInternalServerError)
return

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Avoid returning internal template errors to clients.

On Line 52 and Line 59, templateError.Error() is sent in the HTTP response. That can leak internal paths/template details. Return a generic message to the client and log the detailed error server-side instead.

Suggested patch
 	tmpl, templateError := template.ParseFiles(paths...)
 	if templateError != nil {
-		http.Error(w, templateError.Error(), http.StatusInternalServerError)
+		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
+		fmt.Println("template parse error:", templateError)
 		return
 	}
@@
 	templateError = tmpl.ExecuteTemplate(w, filepath.Base(templatePath), data)
 	if templateError != nil {
-		http.Error(w, templateError.Error(), http.StatusInternalServerError)
+		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
+		fmt.Println("template execute error:", templateError)
 	}

Also applies to: 57-60

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@projects/starters/go/main.go` around lines 51 - 53, Replace the direct
exposure of templateError in HTTP responses with server-side logging and a
generic client message: where the code currently calls http.Error(w,
templateError.Error(), http.StatusInternalServerError) (the occurrences using
the templateError variable in the request handler), change it to log the
detailed error (e.g., log.Printf("template execution error: %v", templateError)
or use the existing logger) and call http.Error(w, "Internal Server Error",
http.StatusInternalServerError) so internal paths/details are not returned to
clients; apply this change to both occurrences handling templateError.

Comment on lines +7 to +9
- `dev`: `go run main.go`
- `build`: `go build -o bin main.go`
- `preview`: `go build -o bin main.go && ./bin`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Keep README script docs consistent with package.json scripts.

This section is labeled “Commands / npm scripts”, but Line 8 documents a direct Go command while build in projects/starters/go/package.json now runs wireit. Please update this section so the documented npm script behavior matches the actual script contract.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@projects/starters/go/README.md` around lines 7 - 9, The README's "Commands /
npm scripts" lines for `dev`, `build`, and `preview` are inconsistent with the
package.json scripts; update the README so each listed npm script (`dev`,
`build`, `preview`) documents the actual commands defined in
projects/starters/go/package.json (e.g., note that `build` runs `wireit` rather
than a direct `go build`), keeping the labels as npm scripts and ensuring the
`dev`, `build`, and `preview` entries match the package.json script behavior and
wording.

<nve-button container="flat"><a href="https://NVIDIA.github.io/elements/docs/integrations/angular/" target="_blank">Catalog</a></nve-button>
<nve-button container="flat"><a href="https://NVIDIA.github.io/elements/starters/">Starters</a></nve-button>
<a slot="prefix" href="https://nvidia.github.io/elements/">Elements</a>
<nve-button container="flat"><a href="https://nvidia.github.io/elements/docs/integrations/go/" target="_blank">Documentation</a></nve-button>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add rel="noopener noreferrer" to external links opened in new tabs.

On Line 22, Line 29, and Line 43, anchors use target="_blank" without rel. Add rel="noopener noreferrer" to prevent reverse-tabnabbing.

Also applies to: 29-29, 43-43

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@projects/starters/go/src/index.html` at line 22, The external anchor tags
that use target="_blank" (e.g., the <a
href="https://nvidia.github.io/elements/docs/integrations/go/" target="_blank">
inside the <nve-button container="flat"> element and the other similar anchors)
are missing rel="noopener noreferrer"; update each anchor with target="_blank"
to include rel="noopener noreferrer" to prevent reverse-tabnabbing and ensure
safe external links.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file github_actions Pull requests that update GitHub Actions code scope(ci) scope(docs) scope(internals) scope(starters)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants