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 an “HTMX + Go” integration starter with a demo page and server-rendered fragment endpoint.
    • Added the new starter to site integrations and starter listings.
  • Improvements

    • Updated Go and Go-HTMX starter docs and templates for a clearer dev/build workflow and PORT-based configuration.
    • Starters now stamp Elements CDN asset versions for more consistent loading.
  • Documentation

    • Added the HTMX + Go integration documentation page and refreshed the Go integration and starter README/AGENTS guidance.
    • Updated repository setup notes to require Go 1.26.x for CI runs.

@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

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: f2654651-e97c-4149-a1f8-6580718db99a

📥 Commits

Reviewing files that changed from the base of the PR and between 013d8af and 73e3dca.

⛔ 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 (32)
  • .github/actions/setup-ci/action.yml
  • .prettierignore
  • README.md
  • 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

📝 Walkthrough

Walkthrough

This PR adds a Go+HTMX starter with server-rendered fragments and HTMX integration, refactors the existing Go starter for environment-driven configuration, implements Elements CDN version stamping in starter outputs, updates ProjectService to conditionally skip dependency setup per-starter, and registers both starters with site documentation and CI pipelines.

Changes

Go and Go+HTMX Starters

Layer / File(s) Summary
CI and workspace setup
.github/actions/setup-ci/action.yml, package.json, pnpm-workspace.yaml, README.md, projects/starters/package.json
Go 1.26.x toolchain is added to CI setup, root package.json includes starters' CI tasks, pnpm workspace registers go-htmx, and the starters build task tracks Go starter source files with dependencies.
Starter data model and conditional orchestration
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
Starter metadata now includes setupElementsDependencies flag, ProjectService conditionally skips setupProject/updateProject based on that flag, starters data defines go and go-htmx with setup disabled, and tests verify conditional behavior and new starter metadata.
CDN versioning infrastructure for starters
projects/internals/tools/src/project/starters.ts, projects/internals/tools/src/project/starters.test.ts
Starter archiving copies projects into dist outputs and rewrites Elements CDN asset URLs by reading package versions from workspace and applying versioned URL replacements; two new exports expose version lookup and CDN URL construction helpers.
Go starter refactoring
projects/starters/go/.gitignore, projects/starters/go/README.md, projects/starters/go/AGENTS.md, projects/starters/go/main.go, projects/starters/go/package.json, projects/starters/go/src/index.html
Go starter now derives port from environment variable with default fallback, replaces generic Page wrapper with direct renderTemplate helper, updates wireit build configuration, refreshes template assets to cdn.jsdelivr.net, and updates documentation and template variable bindings.
Go+HTMX starter implementation
projects/starters/go-htmx/**, .prettierignore
New go-htmx starter adds a Go server with environment and template rendering helpers, defines PageData and TimeData types, provides full-page and fragment HTML templates, configures wireit build tasks, and includes AGENTS and README documentation; prettier ignore excludes the new template file.
Site documentation and integration
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
Go and Go+HTMX integration documentation pages are added, site navigation and integrations registry include both starters, logo support and legal notice add HTMX attribution, integration card rendering supports explicit icon dimensions, and skill documentation is updated.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested labels

scope(pages), 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 19.05% 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 captures the main objectives: adding a new HTMX+Go starter and fixing the existing Go starter. It is concise, specific, and directly reflects the primary changes in the changeset.
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"


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 thread projects/internals/tools/src/project/service.ts
Comment thread projects/internals/tools/src/project/starters.ts Outdated
Comment thread projects/internals/tools/src/project/starters.ts
<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).

Comment thread projects/site/src/docs/integrations/go-htmx.md Outdated
- 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.

@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 thread .github/actions/setup-ci/action.yml
Comment thread projects/starters/go-htmx/AGENTS.md Outdated
Comment thread projects/starters/go-htmx/main.go Outdated
Comment thread projects/starters/go-htmx/src/index.html Outdated
Comment thread projects/starters/go/main.go
Comment thread projects/starters/go/README.md
Comment thread projects/starters/go/src/index.html Outdated
• 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 013d8af to 73e3dca Compare June 18, 2026 17:43

@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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
projects/site/src/docs/integrations/go-htmx.md (1)

1-26: ⚠️ Potential issue | 🟡 Minor

Add HTMX to Vale vocabulary.

HTMX is referenced multiple times throughout the documentation but is not in config/vale/styles/config/vocabularies/Elements/accept.txt. Add HTMX to this file to comply with the coding guidelines for markdown documentation.

🤖 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` around lines 1 - 26, The
markdown documentation file references HTMX multiple times but the term is not
included in the Vale vocabulary configuration file. Add HTMX to the vocabulary
file located at config/vale/styles/config/vocabularies/Elements/accept.txt to
ensure compliance with the documentation coding guidelines and allow the linter
to recognize HTMX as a valid term throughout the documentation.

Source: Coding guidelines

projects/starters/go-htmx/README.md (1)

1-14: ⚠️ Potential issue | 🟡 Minor

Add HTMX to the Vale vocabulary file.

The README introduces the technical term HTMX, which is not currently in config/vale/styles/config/vocabularies/Elements/accept.txt. Wireit and Vite are already present in the vocabulary. Add HTMX as a new line in the vocabulary file to comply with the style guide.

🤖 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/README.md` around lines 1 - 14, The technical term
HTMX is used in the README but is missing from the Vale vocabulary configuration
file. Add HTMX as a new line entry in the file located at
config/vale/styles/config/vocabularies/Elements/accept.txt to match the pattern
of other technical terms like Wireit and Vite that are already listed there.

Source: Coding guidelines

🤖 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/starters.ts`:
- Around line 23-35: The REPO_WORKSPACE_DIR constant is being computed at module
import time by calling findWorkspaceRoot, which throws an error immediately if
pnpm-workspace.yaml cannot be found. This prevents the module from loading for
any use case, even those that don't require the workspace root. Move the
findWorkspaceRoot call from module load time to a lazy execution point where CDN
stamping actually occurs. Instead of assigning REPO_WORKSPACE_DIR as a
module-level constant, compute the workspace root only when it's needed within
the stamping logic. This allows the module to load successfully even if the
workspace root is not available, and only fails for code paths that actually
require workspace discovery.

In `@projects/internals/tools/src/skills/about.md`:
- Line 3: In the about.md file, update the phrase "high level overview" to use a
hyphen as a compound adjective before the noun. Change "high level" to
"high-level" in the sentence that describes the NVIDIA Elements Design System
overview. Compound adjectives that precede nouns require hyphens to maintain
proper grammar and readability.

In `@projects/starters/go-htmx/src/time.html`:
- Line 1: The `.htmlhintrc` configuration file has `doctype-first: true` which
requires a doctype declaration, but fragment templates like time.html
intentionally lack doctypes for HTMX swaps. Fix this by either updating the
`.htmlhintrc` file to add `allowFragments: true` to the `doctype-first` rule
configuration, or create a `.htmlhintignore` file at the project root and add an
exclusion pattern to ignore all HTML files in the src directory where fragment
templates are located.

In `@projects/starters/go/main.go`:
- Around line 49-64: The renderTemplate function sets the Content-Type header
before executing the template, which causes a problem when ExecuteTemplate fails
after writing partial output to the ResponseWriter. Once headers are sent, the
subsequent http.Error call cannot change the status code, resulting in a partial
HTML response with 200 OK instead of a 500 error. To fix this, execute the
template into a bytes.Buffer first instead of directly into the ResponseWriter,
check if the execution succeeds, set the Content-Type header only after
successful execution, and then write the buffer contents to the ResponseWriter.
This ensures the proper error response is sent when template execution fails.
Make sure to import the bytes package if not already present.

---

Outside diff comments:
In `@projects/site/src/docs/integrations/go-htmx.md`:
- Around line 1-26: The markdown documentation file references HTMX multiple
times but the term is not included in the Vale vocabulary configuration file.
Add HTMX to the vocabulary file located at
config/vale/styles/config/vocabularies/Elements/accept.txt to ensure compliance
with the documentation coding guidelines and allow the linter to recognize HTMX
as a valid term throughout the documentation.

In `@projects/starters/go-htmx/README.md`:
- Around line 1-14: The technical term HTMX is used in the README but is missing
from the Vale vocabulary configuration file. Add HTMX as a new line entry in the
file located at config/vale/styles/config/vocabularies/Elements/accept.txt to
match the pattern of other technical terms like Wireit and Vite that are already
listed there.
🪄 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: f2654651-e97c-4149-a1f8-6580718db99a

📥 Commits

Reviewing files that changed from the base of the PR and between 013d8af and 73e3dca.

⛔ 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 (32)
  • .github/actions/setup-ci/action.yml
  • .prettierignore
  • README.md
  • 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

@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.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
projects/site/src/docs/integrations/go-htmx.md (1)

1-26: ⚠️ Potential issue | 🟡 Minor

Add HTMX to Vale vocabulary.

HTMX is referenced multiple times throughout the documentation but is not in config/vale/styles/config/vocabularies/Elements/accept.txt. Add HTMX to this file to comply with the coding guidelines for markdown documentation.

🤖 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` around lines 1 - 26, The
markdown documentation file references HTMX multiple times but the term is not
included in the Vale vocabulary configuration file. Add HTMX to the vocabulary
file located at config/vale/styles/config/vocabularies/Elements/accept.txt to
ensure compliance with the documentation coding guidelines and allow the linter
to recognize HTMX as a valid term throughout the documentation.

Source: Coding guidelines

projects/starters/go-htmx/README.md (1)

1-14: ⚠️ Potential issue | 🟡 Minor

Add HTMX to the Vale vocabulary file.

The README introduces the technical term HTMX, which is not currently in config/vale/styles/config/vocabularies/Elements/accept.txt. Wireit and Vite are already present in the vocabulary. Add HTMX as a new line in the vocabulary file to comply with the style guide.

🤖 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/README.md` around lines 1 - 14, The technical term
HTMX is used in the README but is missing from the Vale vocabulary configuration
file. Add HTMX as a new line entry in the file located at
config/vale/styles/config/vocabularies/Elements/accept.txt to match the pattern
of other technical terms like Wireit and Vite that are already listed there.

Source: Coding guidelines

🤖 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/starters.ts`:
- Around line 23-35: The REPO_WORKSPACE_DIR constant is being computed at module
import time by calling findWorkspaceRoot, which throws an error immediately if
pnpm-workspace.yaml cannot be found. This prevents the module from loading for
any use case, even those that don't require the workspace root. Move the
findWorkspaceRoot call from module load time to a lazy execution point where CDN
stamping actually occurs. Instead of assigning REPO_WORKSPACE_DIR as a
module-level constant, compute the workspace root only when it's needed within
the stamping logic. This allows the module to load successfully even if the
workspace root is not available, and only fails for code paths that actually
require workspace discovery.

In `@projects/internals/tools/src/skills/about.md`:
- Line 3: In the about.md file, update the phrase "high level overview" to use a
hyphen as a compound adjective before the noun. Change "high level" to
"high-level" in the sentence that describes the NVIDIA Elements Design System
overview. Compound adjectives that precede nouns require hyphens to maintain
proper grammar and readability.

In `@projects/starters/go-htmx/src/time.html`:
- Line 1: The `.htmlhintrc` configuration file has `doctype-first: true` which
requires a doctype declaration, but fragment templates like time.html
intentionally lack doctypes for HTMX swaps. Fix this by either updating the
`.htmlhintrc` file to add `allowFragments: true` to the `doctype-first` rule
configuration, or create a `.htmlhintignore` file at the project root and add an
exclusion pattern to ignore all HTML files in the src directory where fragment
templates are located.

In `@projects/starters/go/main.go`:
- Around line 49-64: The renderTemplate function sets the Content-Type header
before executing the template, which causes a problem when ExecuteTemplate fails
after writing partial output to the ResponseWriter. Once headers are sent, the
subsequent http.Error call cannot change the status code, resulting in a partial
HTML response with 200 OK instead of a 500 error. To fix this, execute the
template into a bytes.Buffer first instead of directly into the ResponseWriter,
check if the execution succeeds, set the Content-Type header only after
successful execution, and then write the buffer contents to the ResponseWriter.
This ensures the proper error response is sent when template execution fails.
Make sure to import the bytes package if not already present.

---

Outside diff comments:
In `@projects/site/src/docs/integrations/go-htmx.md`:
- Around line 1-26: The markdown documentation file references HTMX multiple
times but the term is not included in the Vale vocabulary configuration file.
Add HTMX to the vocabulary file located at
config/vale/styles/config/vocabularies/Elements/accept.txt to ensure compliance
with the documentation coding guidelines and allow the linter to recognize HTMX
as a valid term throughout the documentation.

In `@projects/starters/go-htmx/README.md`:
- Around line 1-14: The technical term HTMX is used in the README but is missing
from the Vale vocabulary configuration file. Add HTMX as a new line entry in the
file located at config/vale/styles/config/vocabularies/Elements/accept.txt to
match the pattern of other technical terms like Wireit and Vite that are already
listed there.
🪄 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: f2654651-e97c-4149-a1f8-6580718db99a

📥 Commits

Reviewing files that changed from the base of the PR and between 013d8af and 73e3dca.

⛔ 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 (32)
  • .github/actions/setup-ci/action.yml
  • .prettierignore
  • README.md
  • 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
🛑 Comments failed to post (4)
projects/internals/tools/src/project/starters.ts (1)

23-35: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid import-time failure on workspace discovery.

Line 34 computes workspace root at module load. If pnpm-workspace.yaml is absent in the runtime tree, importing this module throws before any command runs (including flows that don’t need CDN stamping). Resolve the workspace root lazily where stamping is executed.

💡 Proposed fix
-const REPO_WORKSPACE_DIR = findWorkspaceRoot(dirname(fileURLToPath(import.meta.url)));
+let repoWorkspaceDir: string | undefined;
+function getRepoWorkspaceDir() {
+  repoWorkspaceDir ??= findWorkspaceRoot(dirname(fileURLToPath(import.meta.url)));
+  return repoWorkspaceDir;
+}
@@
-  const versions = getStarterCDNPackageVersions(REPO_WORKSPACE_DIR);
+  const versions = getStarterCDNPackageVersions(getRepoWorkspaceDir());

Also applies to: 232-232

🤖 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 23 - 35, The
REPO_WORKSPACE_DIR constant is being computed at module import time by calling
findWorkspaceRoot, which throws an error immediately if pnpm-workspace.yaml
cannot be found. This prevents the module from loading for any use case, even
those that don't require the workspace root. Move the findWorkspaceRoot call
from module load time to a lazy execution point where CDN stamping actually
occurs. Instead of assigning REPO_WORKSPACE_DIR as a module-level constant,
compute the workspace root only when it's needed within the stamping logic. This
allows the module to load successfully even if the workspace root is not
available, and only fails for code paths that actually require workspace
discovery.
projects/internals/tools/src/skills/about.md (1)

3-3: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use hyphen in compound adjective.

"High level" should be "high-level" when used as a compound adjective before a noun.

📝 Suggested fix
-Give a high level overview of the NVIDIA Elements Design System.
+Give a high-level overview of the NVIDIA Elements Design System.
📝 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.

Give a high-level overview of the NVIDIA Elements Design System.
🧰 Tools
🪛 LanguageTool

[grammar] ~3-~3: Use a hyphen to join words.
Context: ...IDIA Elements Design System Give a high level overview of the NVIDIA Elements De...

(QB_NEW_EN_HYPHEN)

🤖 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/skills/about.md` at line 3, In the about.md
file, update the phrase "high level overview" to use a hyphen as a compound
adjective before the noun. Change "high level" to "high-level" in the sentence
that describes the NVIDIA Elements Design System overview. Compound adjectives
that precede nouns require hyphens to maintain proper grammar and readability.
projects/starters/go-htmx/src/time.html (1)

1-1: ⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Locate potential HTMLHint configuration files:"
fd -HI 'htmlhint|\.htmlhintrc|\.htmlhint.*|package.json|*.config.*'

echo
echo "Search for doctype-first/htmlhint rules and ignore globs:"
rg -n -C2 --iglob '*{json,yml,yaml,js,cjs,mjs}' 'doctype-first|htmlhint|ignore|exclude|time\.html|go-htmx/src'

Repository: NVIDIA/elements

Length of output: 510


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Finding HTMLHint configuration files ==="
echo
echo "Searching for .htmlhintrc files:"
find . -name ".htmlhintrc" -o -name "htmlhint.config.*" 2>/dev/null || echo "No direct htmlhint config files found"

echo
echo "=== Checking package.json for htmlhint config ==="
fd -H 'package.json' --exec grep -l 'htmlhint' {} \; 2>/dev/null || echo "No htmlhint in package.json"

echo
echo "=== Listing configuration files in project root and go-htmx directory ==="
ls -la . 2>/dev/null | grep -E '\.html|lint|config|eslint|prettier' || echo "No matching files in root"

echo
echo "=== Checking go-htmx project directory structure ==="
find projects/starters/go-htmx -maxdepth 2 -type f \( -name ".*" -o -name "*.json" \) 2>/dev/null | head -20

echo
echo "=== Searching for doctype-first rule configuration ==="
rg -i 'doctype-first' --type json --type yaml --type javascript --type javascript 2>/dev/null || echo "No doctype-first rule found"

Repository: NVIDIA/elements

Length of output: 2109


🏁 Script executed:

cat .htmlhintrc

Repository: NVIDIA/elements

Length of output: 443


🏁 Script executed:

echo "=== Checking time.html content ==="
cat projects/starters/go-htmx/src/time.html

echo
echo "=== Listing all files in go-htmx/src/ ==="
find projects/starters/go-htmx/src -type f

echo
echo "=== Checking for other fragment templates ==="
find projects/starters/go-htmx -name "*.html" -type f | head -20

Repository: NVIDIA/elements

Length of output: 416


🏁 Script executed:

echo "=== Checking index.html content ==="
cat projects/starters/go-htmx/src/index.html

echo
echo "=== Checking if .htmlhintrc has any ignore/exclude patterns ==="
cat .htmlhintrc | grep -i 'ignore\|exclude' || echo "No ignore/exclude patterns found"

echo
echo "=== Checking for .htmlhintignore file ==="
find . -name ".htmlhintignore" -o -name "htmlhintignore" 2>/dev/null || echo "No .htmlhintignore file found"

echo
echo "=== Checking package.json in go-htmx for any lint config ==="
cat projects/starters/go-htmx/package.json 2>/dev/null || echo "No package.json"

Repository: NVIDIA/elements

Length of output: 4808


Configure HTMLHint to exclude fragment templates from doctype-first rule.

The .htmlhintrc configuration currently has doctype-first: true with no exclusion patterns for fragment templates. Since time.html is an intentional fragment (containing only a <span> element for HTMX swap), it will trigger a linting violation. Add an ignore pattern to exclude files in src/ from this rule, such as:

{
  "doctype-first": {
    "allowFragments": true
  }
}

Or use .htmlhintignore with entries like projects/starters/go-htmx/src/**/*.html to exclude fragment templates from linting.

🧰 Tools
🪛 HTMLHint (1.9.2)

[error] 1-1: Doctype must be declared before any non-comment content.

(doctype-first)

🤖 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/time.html` at line 1, The `.htmlhintrc`
configuration file has `doctype-first: true` which requires a doctype
declaration, but fragment templates like time.html intentionally lack doctypes
for HTMX swaps. Fix this by either updating the `.htmlhintrc` file to add
`allowFragments: true` to the `doctype-first` rule configuration, or create a
`.htmlhintignore` file at the project root and add an exclusion pattern to
ignore all HTML files in the src directory where fragment templates are located.

Sources: Coding guidelines, Linters/SAST tools

projects/starters/go/main.go (1)

49-64: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Potential partial response on template execution failure.

On line 58, Content-Type is set before ExecuteTemplate is called. If ExecuteTemplate writes partial output to the ResponseWriter and then fails, the HTTP status code will have already been implicitly committed as 200 OK. The subsequent http.Error call on line 62 cannot change the status code once headers are sent, resulting in a partial HTML response with a 200 status instead of a proper 500 error.

Consider executing the template into a bytes.Buffer first, then writing the buffer to w only if execution succeeds.

🛡️ Proposed fix using buffered template execution
 func renderTemplate(w http.ResponseWriter, templatePath string, data interface{}, templatePaths ...string) {
 	paths := append([]string{templatePath}, templatePaths...)
 	tmpl, templateError := template.ParseFiles(paths...)
 	if templateError != nil {
 		log.Printf("template parse error path=%s err=%v", templatePath, templateError)
 		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
 		return
 	}
 
+	var buf bytes.Buffer
+	templateError = tmpl.ExecuteTemplate(&buf, filepath.Base(templatePath), data)
-	w.Header().Set("Content-Type", "text/html; charset=utf-8")
-	templateError = tmpl.ExecuteTemplate(w, filepath.Base(templatePath), data)
 	if templateError != nil {
 		log.Printf("template execute error path=%s err=%v", templatePath, templateError)
 		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
+		return
 	}
+
+	w.Header().Set("Content-Type", "text/html; charset=utf-8")
+	w.Write(buf.Bytes())
 }

Note: Add "bytes" to imports if not already present.

🤖 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 49 - 64, The renderTemplate
function sets the Content-Type header before executing the template, which
causes a problem when ExecuteTemplate fails after writing partial output to the
ResponseWriter. Once headers are sent, the subsequent http.Error call cannot
change the status code, resulting in a partial HTML response with 200 OK instead
of a 500 error. To fix this, execute the template into a bytes.Buffer first
instead of directly into the ResponseWriter, check if the execution succeeds,
set the Content-Type header only after successful execution, and then write the
buffer contents to the ResponseWriter. This ensures the proper error response is
sent when template execution fails. Make sure to import the bytes package if not
already present.

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