Skip to content

Vite-plus adoption#20

Open
JohannesKonings wants to merge 2 commits intomainfrom
cursor/vite-plus-adoption-cf0d
Open

Vite-plus adoption#20
JohannesKonings wants to merge 2 commits intomainfrom
cursor/vite-plus-adoption-cf0d

Conversation

@JohannesKonings
Copy link
Copy Markdown
Owner

@JohannesKonings JohannesKonings commented Mar 14, 2026

Migrate repository tooling to Vite+ to centralize and streamline development workflows.

Open in Web Open in Cursor 

Summary by CodeRabbit

  • New Features

    • Adds TanStack AI integration for enhanced AI capabilities and assistant features.
    • Adds an intent workflow to manage repository skills.
  • Chores

    • Migrates development tooling and scripts to Vite+.
    • Updates dependencies and developer scripts to new tooling ecosystem.
    • Consolidates formatter/linter config into the new tooling setup.
  • CI

    • Adds a PR check workflow to run the new tooling checks, tests, and build.
  • Documentation

    • Updates docs and README to reflect Vite+ tooling and Intent usage.

Co-authored-by: Johannes Konings <JohannesKonings@users.noreply.github.com>
@cursor
Copy link
Copy Markdown

cursor Bot commented Mar 14, 2026

Cursor Agent can help with this pull request. Just @cursor in comments and I'll start working on changes in this branch.
Learn more about Cursor Agents

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 14, 2026

📝 Walkthrough

Walkthrough

Tooling and formatting overhaul: migrate Vite → vite-plus, add TanStack AI packages and vp scripts, introduce aiDevtools stub plugin and PR VP check workflow, remove separate oxfmt/oxlint configs, and apply widespread import/format cleanups across source, infra, and docs (no substantive runtime logic changes).

Changes

Cohort / File(s) Summary
Build & Tooling
vite.config.ts, package.json, .github/workflows/pr-vp-check.yml, intent.md, .vscode/settings.json, .vscode/extensions.json
Switch to vite-plus and vp-based scripts, add TanStack AI deps and pnpm config, introduce aiDevtoolsStubPlugin and static defineConfig, add PR VP check workflow and intent docs; update VS Code recommendations and formatter config path.
Formatter / Lint Cleanup
.oxfmtrc.json, .oxlintrc.json
Removed standalone Oxfmt/Oxlint config files (config consolidated into vite config).
Documentation
AGENTS.md, README.md, intent.md
Terminology and command updates to Vite+/vp, added intent instructions and agent/skill mappings; mostly wording/formatting edits.
Infrastructure / CDK
cdk.json, accountSetup/..., lib/constructs/..., bin/app.ts, accountSetup/cdk.json
Import reorders, single-line formatting of constructors/objects, minor syntax fixes (LogGroup), and test import changes to vite-plus/test; no signature/behavior changes.
Webapp Components & UI
src/webapp/components/..., src/webapp/components/ui/button.tsx, src/webapp/components/ui/badge.tsx, src/webapp/components/example-*.tsx
Widespread import reordering (type-only imports moved), small API export tidy (remove trailing commas), selector change in one component (useStore selector tightened), minor refactors (Number() vs +id). Mostly formatting; one store/selector change noted.
State, Store & Devtools
src/webapp/lib/demo-store.ts, src/webapp/lib/demo-store-devtools.tsx, src/webapp/routes/demo/store.tsx
Migrated from DerivedcreateStore, removed .mount(), adjusted subscriptions/cleanup pattern and component selector usage; changes affect reactivity implementation.
Integrations & Adapters
src/webapp/integrations/bedrock-adapter/index.ts, src/webapp/integrations/electrodb/*, src/webapp/integrations/tanstack-query/root-provider.tsx
Refactored formatting, deduped/reordered imports, destructured message handling in bedrock adapter; preserved API signatures and control flow.
Routes & Demo
src/webapp/routes/demo/*, src/webapp/routes/__root.tsx, src/webapp/routes/example.guitars/*
Consolidated imports, removed duplicate imports, small type/context change (removed trpc from MyRouterContext), and minor loader id parsing tweaks.
Scripts & Tools
scripts/*, .cta.json, components.json, knip.json, tsconfig.json, tsconfig.json
Formatting and import ordering changes, single-line JSON/array reflows, trailing newline adjustments; no behavioral changes.
Bedrock Budget & Utilities
src/webapp/lib/bedrock-budget.ts, src/webapp/lib/bedrock-budget-config.ts, src/webapp/utils/demo.tools.ts, scripts/test-bedrock-*.ts
Formatting refinements, expression compaction, small API formatting; no logic behavior changes.
Misc (minor edits)
src/lambda/stream-to-events.ts, src/webapp/components/SyncStatus.tsx, src/webapp/db-collections/*, src/webapp/data/fake-persons.ts, src/webapp/styles.css
Import repositioning, duplicate import removal (one duplicate import remains in SyncStatus), comment capitalization, lint pragma movement, CSS/font reflow; no functional changes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

Poem

🐰 A little rabbit hops, and says with cheer:
The config hopped over — vite-plus is here!
Imports aligned, small commas gone,
TanStack AI joins the dawn.
Hooray for tidy files — let's nibble a carrot near! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.70% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Vite-plus adoption' directly and clearly describes the main change: migrating the repository to use Vite+ tooling for development workflows.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/vite-plus-adoption-cf0d
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Tip

You can customize the tone of the review comments and chat replies.

Configure the tone_instructions setting to customize the tone of the review comments and chat replies. For example, you can set the tone to Act like a strict teacher, Act like a pirate and more.

@JohannesKonings JohannesKonings marked this pull request as ready for review March 14, 2026 20:35
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.vscode/settings.json:
- Line 3: Update the OXC formatter config path: replace the current
oxc.fmt.configPath value that points to "./vite.config.ts" with a valid Oxfmt
config file (e.g., ".oxfmtrc.json" or ".oxfmtrc.jsonc") or remove the
oxc.fmt.configPath setting to allow auto-discovery; ensure the target file
contains Oxfmt keys like printWidth, tabWidth, and semi so the formatter will be
applied correctly.

In `@lib/constructs/WebappApi.ts`:
- Around line 1-10: The import of the CDK class "Function" shadows a restricted
global name; change the import to an alias (e.g., import { Function as
LambdaFunction } from 'aws-cdk-lib/aws-lambda') and then update all usages in
this file (references to Function) to the alias (LambdaFunction) so the
noShadowRestrictedNames lint rule is satisfied.

In `@src/webapp/styles.css`:
- Around line 10-11: In the font-family declaration in styles.css (the
comma-separated list containing -apple-system, BlinkMacSystemFont, 'Segoe UI',
'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica
Neue', sans-serif), remove the unnecessary single quotes around single-word font
names (Roboto, Oxygen, Ubuntu, Cantarell) while keeping quotes for multi-word
names like 'Segoe UI' and 'Helvetica Neue' so the list complies with the
font-family-name-quotes stylelint rule.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c17c0bdb-aa3c-4059-a716-0b83f29613ff

📥 Commits

Reviewing files that changed from the base of the PR and between 53527cb and cff4097.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (68)
  • .cta.json
  • .cursor/skills/tanstack-use-mcp/SKILL.md
  • .oxfmtrc.json
  • .oxlintrc.json
  • .vscode/extensions.json
  • .vscode/settings.json
  • AGENTS.md
  • README.md
  • accountSetup/bin/app.ts
  • accountSetup/cdk.json
  • accountSetup/lib/account-setup-stack.test.ts
  • accountSetup/lib/account-setup-stack.ts
  • accountSetup/lib/app-config.ts
  • accountSetup/lib/constructs/GitHubActionsOidcSetup.test.ts
  • accountSetup/lib/constructs/GitHubActionsOidcSetup.ts
  • cdk.json
  • components.json
  • docs/PLAN-DB-PERSONS.md
  • knip.json
  • lib/constructs/WebappApi.ts
  • lib/constructs/WebappAssetsDeployment.ts
  • lib/constructs/WebappDistribution.ts
  • lib/constructs/WebappServer.ts
  • package.json
  • scripts/seed-persons.ts
  • scripts/test-bedrock-budget.ts
  • scripts/test-bedrock-chat.ts
  • src/lambda/stream-to-events.ts
  • src/webapp/components/SyncStatus.tsx
  • src/webapp/components/persons/AddressCard.tsx
  • src/webapp/components/persons/AddressForm.tsx
  • src/webapp/components/persons/AddressFormModal.tsx
  • src/webapp/components/persons/BankAccountCard.tsx
  • src/webapp/components/persons/BankAccountForm.tsx
  • src/webapp/components/persons/BankAccountFormModal.tsx
  • src/webapp/components/persons/ConfirmationModal.tsx
  • src/webapp/components/persons/ContactForm.tsx
  • src/webapp/components/persons/ContactFormModal.tsx
  • src/webapp/components/persons/ContactInfoCard.tsx
  • src/webapp/components/persons/CreatePersonModal.tsx
  • src/webapp/components/persons/EmploymentCard.tsx
  • src/webapp/components/persons/EmploymentForm.tsx
  • src/webapp/components/persons/EmploymentFormModal.tsx
  • src/webapp/components/persons/PersonDetailPanel.tsx
  • src/webapp/components/persons/PersonEditModal.tsx
  • src/webapp/components/persons/PersonForm.tsx
  • src/webapp/components/ui/badge.tsx
  • src/webapp/components/ui/button.tsx
  • src/webapp/data/fake-persons.ts
  • src/webapp/db-collections/persons.ts
  • src/webapp/hooks/useDbPersons.ts
  • src/webapp/hooks/useSseSync.ts
  • src/webapp/integrations/bedrock-adapter/index.ts
  • src/webapp/integrations/electrodb/entities.ts
  • src/webapp/integrations/electrodb/personsClient.ts
  • src/webapp/integrations/tanstack-query/root-provider.tsx
  • src/webapp/lib/bedrock-budget-config.ts
  • src/webapp/lib/bedrock-budget.ts
  • src/webapp/routes/__root.tsx
  • src/webapp/routes/demo/api.bedrock-budget.ts
  • src/webapp/routes/demo/api.tanchat.ts
  • src/webapp/routes/demo/db-person.tsx
  • src/webapp/routes/demo/start.server-funcs.tsx
  • src/webapp/routes/demo/tanchat.css
  • src/webapp/routes/demo/tanchat.tsx
  • src/webapp/styles.css
  • tsconfig.json
  • vite.config.ts
💤 Files with no reviewable changes (2)
  • .oxfmtrc.json
  • .oxlintrc.json

Comment thread .vscode/settings.json
Comment on lines +1 to +10
import {
AccessLogFormat,
EndpointType,
LambdaRestApi,
LogGroupLogDestination,
MethodLoggingLevel,
ResponseTransferMode,
} from 'aws-cdk-lib/aws-apigateway';
import { Function } from 'aws-cdk-lib/aws-lambda';
import { LogGroup } from 'aws-cdk-lib/aws-logs';
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 the lint rule and all `Function` imports/usages in this module
fd -HI 'biome*.{json,jsonc}'
rg -n "noShadowRestrictedNames" -S
rg -nP --type=ts "import\\s*\\{[^}]*\\bFunction\\b[^}]*\\}\\s*from 'aws-cdk-lib/aws-lambda'" -C2
rg -nP --type=ts "\\bwebappServer\\s*:\\s*Function\\b|\\breadonly\\s+webappApi\\b|\\bFunction\\b" lib/constructs/WebappApi.ts -C2

Repository: JohannesKonings/tanstack-aws

Length of output: 1938


🏁 Script executed:

#!/bin/bash
# Check for Biome configuration
find . -type f \( -name "biome.json" -o -name "biome.jsonc" -o -name "package.json" \) | head -20
# Check package.json for biome reference
rg -l "biome" . --type json

Repository: JohannesKonings/tanstack-aws

Length of output: 112


🏁 Script executed:

#!/bin/bash
# Check the content of Biome config to see if noShadowRestrictedNames is enabled
find . -type f -name "biome.json*" -exec cat -n {} \;

Repository: JohannesKonings/tanstack-aws

Length of output: 2357


🏁 Script executed:

#!/bin/bash
# Check WebappServer.ts and WebappFunctionUrl.ts to see if Function is used as type annotation
cat -n lib/constructs/WebappServer.ts | head -40

Repository: JohannesKonings/tanstack-aws

Length of output: 1805


🏁 Script executed:

#!/bin/bash
# Check WebappFunctionUrl.ts for Function usage
cat -n lib/constructs/WebappFunctionUrl.ts | head -40

Repository: JohannesKonings/tanstack-aws

Length of output: 826


Alias the Function import to avoid shadowing the restricted global name.

Biome's noShadowRestrictedNames rule (enabled via recommended ruleset) flags this pattern. Import the CDK Function class under an alias instead.

♻️ Proposed fix
-import { Function } from 'aws-cdk-lib/aws-lambda';
+import { Function as LambdaFunction } from 'aws-cdk-lib/aws-lambda';
@@
 type WebappApiProps = {
-  webappServer: Function;
+  webappServer: LambdaFunction;
 };
🧰 Tools
🪛 Biome (2.4.6)

[error] 9-9: Do not shadow the global "Function" property.

(lint/suspicious/noShadowRestrictedNames)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/constructs/WebappApi.ts` around lines 1 - 10, The import of the CDK class
"Function" shadows a restricted global name; change the import to an alias
(e.g., import { Function as LambdaFunction } from 'aws-cdk-lib/aws-lambda') and
then update all usages in this file (references to Function) to the alias
(LambdaFunction) so the noShadowRestrictedNames lint rule is satisfied.

Comment thread src/webapp/styles.css
Comment on lines +10 to +11
-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify stylelint rule/config and the affected declaration
fd -HI 'stylelint*.{json,js,cjs,mjs,yml,yaml}'
rg -n "font-family-name-quotes" -S
rg -n "Roboto|Oxygen|Ubuntu|Cantarell" src/webapp/styles.css -C2

Repository: JohannesKonings/tanstack-aws

Length of output: 660


🏁 Script executed:

#!/bin/bash
# Search for stylelint config files using corrected patterns
fd -HI -e json -e js -e cjs -e mjs -e yml -e yaml stylelint
# Also check for common config file locations
fd -HI -e json -e js -e yaml '(stylelint|lint|eslint).*config'
# Check if there are any package.json files with stylelint config
fd -HI package.json -x grep -l "stylelint" {}

Repository: JohannesKonings/tanstack-aws

Length of output: 89


🌐 Web query:

stylelint font-family-name-quotes rule CSS quotes single word font names

💡 Result:

  • font-family-name-quotes controls when font family names must/mustn’t be quoted; it does not choose single vs double quotes. Use string-quotes to enforce ' vs " instead. [1], [2]
  • For single-word font names like Arial (valid CSS identifiers), the usual “don’t quote unless needed” setups will reject quotes:
    • "always-where-required"font-family: Arial, sans-serif; OK, but "Arial" is a lint error. [1]
    • "always-where-recommended" → also allows Arial unquoted, but requires quotes for names where quotes are recommended (e.g., containing whitespace/digits/punctuation other than hyphens). [1]
  • If you want single quotes when quoting is needed, configure e.g.:
{
  "rules": {
    "font-family-name-quotes": "always-where-recommended",
    "string-quotes": "single"
  }
}

[1], [2]

Notes:

  • Generic/system keywords like serif, sans-serif, system-ui, monospace, etc. should never be quoted (the rule enforces that). [1]
  • "always-unless-keyword" is the option that forces quotes even on single-word names like Arial. [1]

Sources: [1] Stylelint rule docs (font-family-name-quotes), [2] Stylelint changelog (quote-style-specific options removed; use string-quotes).


🏁 Script executed:

#!/bin/bash
# Read the stylelint configuration
cat -n .stylelintrc.json

Repository: JohannesKonings/tanstack-aws

Length of output: 1288


Remove unnecessary quotes around single-word font family names.

'Roboto', 'Oxygen', 'Ubuntu', and 'Cantarell' violate the font-family-name-quotes rule enabled by the stylelint configuration. Single-word font names do not require quotes and must be unquoted; only multi-word names like 'Segoe UI' require quotes.

♻️ Proposed fix
-    -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
+    -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell,
📝 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
-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell,
'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
🧰 Tools
🪛 Stylelint (17.4.0)

[error] 9-11: Expected empty line before declaration (declaration-empty-line-before)

(declaration-empty-line-before)


[error] 10-10: Unexpected quotes around "Roboto" (font-family-name-quotes)

(font-family-name-quotes)


[error] 10-10: Unexpected quotes around "Oxygen" (font-family-name-quotes)

(font-family-name-quotes)


[error] 10-10: Unexpected quotes around "Ubuntu" (font-family-name-quotes)

(font-family-name-quotes)


[error] 10-10: Unexpected quotes around "Cantarell" (font-family-name-quotes)

(font-family-name-quotes)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/webapp/styles.css` around lines 10 - 11, In the font-family declaration
in styles.css (the comma-separated list containing -apple-system,
BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira
Sans', 'Droid Sans', 'Helvetica Neue', sans-serif), remove the unnecessary
single quotes around single-word font names (Roboto, Oxygen, Ubuntu, Cantarell)
while keeping quotes for multi-word names like 'Segoe UI' and 'Helvetica Neue'
so the list complies with the font-family-name-quotes stylelint rule.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

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

⚠️ Outside diff range comments (3)
src/webapp/routes/demo/tanchat.tsx (1)

307-364: ⚠️ Potential issue | 🟠 Major

Prevent stale budget responses from overwriting fresh state.

fetchBudget can run concurrently (initial load, RUN_FINISHED, manual retry). Older requests can resolve later and overwrite newer budget state.

🛠️ Proposed fix (request sequencing guard)
 function ChatPage() {
   const [runLog, setRunLog] = useState<RunLogEntry[]>([]);
   const [budget, setBudget] = useState<BudgetState>({
     overBudget: false,
     limit: DAILY_LIMIT_USD,
     loading: true,
   });

   const mountedRef = useRef(true);
+  const budgetRequestSeqRef = useRef(0);
   useEffect(
     () => () => {
       mountedRef.current = false;
     },
     [],
   );

   const fetchBudget = useCallback(async () => {
+    const requestSeq = ++budgetRequestSeqRef.current;
     const BUDGET_TIMEOUT_MS = 20_000;
     setBudget((prev) => ({ ...prev, loading: true, error: undefined }));
     const controller = new AbortController();
     const timeoutId = setTimeout(() => controller.abort(), BUDGET_TIMEOUT_MS);

@@
-      if (!mountedRef.current) {
+      if (!mountedRef.current || requestSeq !== budgetRequestSeqRef.current) {
         return;
       }
       setBudget(next);
     } catch (err) {
       clearTimeout(timeoutId);
-      if (!mountedRef.current) {
+      if (!mountedRef.current || requestSeq !== budgetRequestSeqRef.current) {
         return;
       }
       const message =
         err instanceof Error
           ? err.name === 'AbortError'
             ? 'Budget request timed out (20s)'
             : err.message
           : String(err);

Also applies to: 366-368, 392-392

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/webapp/routes/demo/tanchat.tsx` around lines 307 - 364, fetchBudget can
have out-of-order responses overwrite newer state; add a request-sequencing
guard using a ref counter (e.g., fetchBudgetRequestIdRef) that you increment
each time fetchBudget is called, capture the current id inside the async call,
and only call setBudget (and return early on error paths) if the captured id
matches the ref's latest value and mountedRef.current is true; apply the same
sequencing check to the other budget-related callers referenced (the manual
retry and RUN_FINISHED handlers around the other fetchBudget invocations) so
stale responses cannot overwrite fresh state.
lib/constructs/WebappDistribution.ts (1)

126-162: ⚠️ Potential issue | 🟠 Major

originBehaviorKind is validated but never used, causing Function URL mode to be silently broken.

The defaultBehavior always uses RestApiOrigin(webappServerApi) regardless of the originBehaviorKind parameter value. The webappServerFunctionUrl is never referenced in the logic. Currently, the only active call site (lib/constructs/Webapp.ts:67) uses 'apiGw' mode and works correctly, but the commented-out 'functionUrl' variant (lib/constructs/Webapp.ts:55) would fail silently, routing to API Gateway instead of the Function URL.

Restore the origin-selection logic in defaultBehavior or remove the 'functionUrl' option from DistributionProps until it can be properly supported.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/constructs/WebappDistribution.ts` around lines 126 - 162, The
defaultBehavior always constructs a RestApiOrigin and ignores the
originBehaviorKind flag, so restore the conditional origin selection: in the
defaultBehavior assignment inspect originBehaviorKind (or OriginBehaviorKind if
that's the used identifier) and when it's 'apiGw' use
RestApiOrigin(webappServerApi) with the existing properties, and when it's
'functionUrl' use
FunctionUrlOrigin.withOriginAccessControl(webappServerFunctionUrl) and include
the LambdaEdge entry using sigv4SignerEdgeFunction (EventType ORIGIN_REQUEST,
IncludeBody: true) plus the same AllowedMethods, CachePolicy,
OriginRequestPolicy,
ResponseHeadersPolicy/ResponseHeadersPolicy.SECURITY_HEADERS and
ViewerProtocolPolicy to match the commented logic; alternatively remove the
'functionUrl' option from DistributionProps if you prefer not to support it.
lib/constructs/WebappAssetsDeployment.ts (1)

32-36: ⚠️ Potential issue | 🟠 Major

Make the bootstrap KMS key lookup conditional.

The code unconditionally looks up alias/cdk-bootstrap-key and will fail during synthesis for any environment that doesn't have this alias (e.g., standard CDK bootstrap). The comment states this is only needed when the bucket uses a custom key, but the code doesn't honor that condition. Add an optional bootstrapKeyAlias?: string prop and only perform the Key.fromLookup() and grantDecrypt() if it's provided.

Suggested fix
 type WebappAssetsDeploymentProps = {
   assetsBucket: Bucket;
+  bootstrapKeyAlias?: string;
   distribution: Distribution;
 };
@@
-    const cdkBootstrapKey = Key.fromLookup(this, 'CdkBootstrapKey', {
-      aliasName: 'alias/cdk-bootstrap-key',
-    });
-    cdkBootstrapKey.grantDecrypt(bucketDeployment.handlerRole);
+    if (props.bootstrapKeyAlias) {
+      const cdkBootstrapKey = Key.fromLookup(this, 'CdkBootstrapKey', {
+        aliasName: props.bootstrapKeyAlias,
+      });
+      cdkBootstrapKey.grantDecrypt(bucketDeployment.handlerRole);
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/constructs/WebappAssetsDeployment.ts` around lines 32 - 36, The code
unconditionally looks up and grants decrypt on alias/cdk-bootstrap-key which
breaks synth in accounts without that alias; add an optional prop
bootstrapKeyAlias?: string to the WebappAssetsDeployment construct props and
only call Key.fromLookup(this, 'CdkBootstrapKey', { aliasName: bootstrapKeyAlias
}) and cdkBootstrapKey.grantDecrypt(bucketDeployment.handlerRole) when
bootstrapKeyAlias is provided; update the constructor signature to accept
props.bootstrapKeyAlias and guard the lookup/grant with an if
(props.bootstrapKeyAlias) check so environments without a custom bootstrap key
skip the lookup.
♻️ Duplicate comments (1)
.vscode/settings.json (1)

2-2: ⚠️ Potential issue | 🟠 Major

Use an actual Oxfmt config here.

Line 2 still points oxc.fmt.configPath at vite.config.ts, which is a Vite+ config, not an Oxfmt formatter config. That means VS Code formatting can drift from vp fmt even when the CLI is configured correctly.

For the VS Code OXC extension, what config files and schema does `oxc.fmt.configPath` support? Can it read formatter settings from a `vite.config.ts` / Vite+ config file?
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.vscode/settings.json at line 2, Update the VS Code setting
oxc.fmt.configPath to point to a real Oxfmt formatter config instead of
vite.config.ts (remove the Vite config reference); set it to your Oxfmt config
filename (for example .oxfmtrc or oxfmt.config.js / oxfmt.config.json) and
ensure the referenced file contains the Oxfmt formatter settings/schema the
extension expects (do not expect the extension to parse Vite/Vite+ config
files).
🧹 Nitpick comments (2)
src/webapp/routes/__root.tsx (1)

3-3: Scope the lint suppression to the single exception instead of the whole file.

A file-wide oxlint-disable can hide future violations outside the intended spot.

Suggested change
-// oxlint-disable func-style
+// Keep global linting enabled; suppress only where needed.

@@
+// oxlint-disable-next-line func-style
 function RootDocument({ children }: { children: React.ReactNode }) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/webapp/routes/__root.tsx` at line 3, Remove the file-wide "//
oxlint-disable func-style" and instead place a targeted suppression immediately
adjacent to the specific function that needs it (e.g., add "//
oxlint-disable-next-line func-style" or "// oxlint-disable-line func-style"
directly above/on the offending function declaration in
src/webapp/routes/__root.tsx), so the rule is only disabled for that single
exception rather than the entire file.
package.json (1)

21-23: Keep intent install explicit instead of running it from postinstall.

intent.md describes this as a sync step that updates AGENTS.md when skill-providing dependencies change. Wiring it into postinstall means every local install and the vp install step in .github/workflows/pr-vp-check.yml now performs repo-file generation as a dependency-install side effect.

Suggested change
     "intent:install": "vp exec intent install",
     "intent:list": "vp exec intent list",
-    "postinstall": "vp exec intent install",
     "knip": "knip",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` around lines 21 - 23, Remove the automatic postinstall hook
that runs "vp exec intent install" so repository files are not generated as a
side effect of every install; edit package.json to delete or disable the
"postinstall" script key and leave the explicit "intent:install" and
"intent:list" scripts intact so maintainers invoke intent install manually when
needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/pr-vp-check.yml:
- Around line 3-5: The pull_request trigger's types list currently contains only
opened, reopened, and synchronize so PRs marked ready_for_review won't run the
workflow; update the pull_request.types array in the workflow (the on:
pull_request types) to include "ready_for_review" alongside "opened",
"reopened", and "synchronize" so the workflow runs when a draft PR is marked
ready for review.

In `@AGENTS.md`:
- Around line 11-17: Update the documentation entries for the npm scripts named
"compile" and "webapp:build" to match the actual scripts: change the "compile"
description to indicate it runs plain "tsc" (not "tsc --noEmit"), and change the
"webapp:build" description to mention it first runs "node
scripts/generate-robots-txt.ts" to generate robots.txt and then runs "vp build"
(Vite/VuePress build), ensuring the AGENTS.md lines referencing compile and
webapp:build reflect these exact behaviors.
- Around line 31-47: The YAML under the intent-skills block has a mis-indented
mapping for the task "configure Nitro server build and deployment behavior" —
the `load:` key for that entry must be indented to match the other skill
mappings; update the `load:` line so it has two leading spaces (i.e., align ` 
load:` with the other entries) within the `skills:` block to restore valid YAML
parsing.

In `@lib/constructs/WebappAssetsDeployment.ts`:
- Line 1: The code currently converts import.meta.url with new
URL(import.meta.url).pathname which preserves URL-encoding and yields incorrect
Windows paths; update WebappAssetsDeployment (and any usage that derives the
current file directory) to import { fileURLToPath } from 'url' and replace new
URL(import.meta.url).pathname with fileURLToPath(import.meta.url), then use
path.dirname(...) or path.resolve(...) as needed so Source.asset(...) receives a
proper filesystem path across platforms.

In `@vite.config.ts`:
- Around line 24-39: The current aiDevtoolsStubPlugin.config computes
useAiDevtoolsStub using "isSsrBuild === true || command === 'build'", which
wrongly applies stub aliases to client production builds; change the condition
in the config for aiDevtoolsStubPlugin so useAiDevtoolsStub is only true when
isSsrBuild === true (remove the command === 'build' clause) so that
devtoolsStubAliases are applied only for SSR builds inside the config function.

---

Outside diff comments:
In `@lib/constructs/WebappAssetsDeployment.ts`:
- Around line 32-36: The code unconditionally looks up and grants decrypt on
alias/cdk-bootstrap-key which breaks synth in accounts without that alias; add
an optional prop bootstrapKeyAlias?: string to the WebappAssetsDeployment
construct props and only call Key.fromLookup(this, 'CdkBootstrapKey', {
aliasName: bootstrapKeyAlias }) and
cdkBootstrapKey.grantDecrypt(bucketDeployment.handlerRole) when
bootstrapKeyAlias is provided; update the constructor signature to accept
props.bootstrapKeyAlias and guard the lookup/grant with an if
(props.bootstrapKeyAlias) check so environments without a custom bootstrap key
skip the lookup.

In `@lib/constructs/WebappDistribution.ts`:
- Around line 126-162: The defaultBehavior always constructs a RestApiOrigin and
ignores the originBehaviorKind flag, so restore the conditional origin
selection: in the defaultBehavior assignment inspect originBehaviorKind (or
OriginBehaviorKind if that's the used identifier) and when it's 'apiGw' use
RestApiOrigin(webappServerApi) with the existing properties, and when it's
'functionUrl' use
FunctionUrlOrigin.withOriginAccessControl(webappServerFunctionUrl) and include
the LambdaEdge entry using sigv4SignerEdgeFunction (EventType ORIGIN_REQUEST,
IncludeBody: true) plus the same AllowedMethods, CachePolicy,
OriginRequestPolicy,
ResponseHeadersPolicy/ResponseHeadersPolicy.SECURITY_HEADERS and
ViewerProtocolPolicy to match the commented logic; alternatively remove the
'functionUrl' option from DistributionProps if you prefer not to support it.

In `@src/webapp/routes/demo/tanchat.tsx`:
- Around line 307-364: fetchBudget can have out-of-order responses overwrite
newer state; add a request-sequencing guard using a ref counter (e.g.,
fetchBudgetRequestIdRef) that you increment each time fetchBudget is called,
capture the current id inside the async call, and only call setBudget (and
return early on error paths) if the captured id matches the ref's latest value
and mountedRef.current is true; apply the same sequencing check to the other
budget-related callers referenced (the manual retry and RUN_FINISHED handlers
around the other fetchBudget invocations) so stale responses cannot overwrite
fresh state.

---

Duplicate comments:
In @.vscode/settings.json:
- Line 2: Update the VS Code setting oxc.fmt.configPath to point to a real Oxfmt
formatter config instead of vite.config.ts (remove the Vite config reference);
set it to your Oxfmt config filename (for example .oxfmtrc or oxfmt.config.js /
oxfmt.config.json) and ensure the referenced file contains the Oxfmt formatter
settings/schema the extension expects (do not expect the extension to parse
Vite/Vite+ config files).

---

Nitpick comments:
In `@package.json`:
- Around line 21-23: Remove the automatic postinstall hook that runs "vp exec
intent install" so repository files are not generated as a side effect of every
install; edit package.json to delete or disable the "postinstall" script key and
leave the explicit "intent:install" and "intent:list" scripts intact so
maintainers invoke intent install manually when needed.

In `@src/webapp/routes/__root.tsx`:
- Line 3: Remove the file-wide "// oxlint-disable func-style" and instead place
a targeted suppression immediately adjacent to the specific function that needs
it (e.g., add "// oxlint-disable-next-line func-style" or "//
oxlint-disable-line func-style" directly above/on the offending function
declaration in src/webapp/routes/__root.tsx), so the rule is only disabled for
that single exception rather than the entire file.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1f6b3b9c-239f-43be-92cc-8ebc22facee5

📥 Commits

Reviewing files that changed from the base of the PR and between cff4097 and c40e00a.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (27)
  • .github/workflows/pr-vp-check.yml
  • .vscode/settings.json
  • AGENTS.md
  • bin/app.ts
  • intent.md
  • lib/constructs/Webapp.ts
  • lib/constructs/WebappAssetsDeployment.ts
  • lib/constructs/WebappDistribution.ts
  • lib/constructs/WebappServer.ts
  • package.json
  • scripts/test-bedrock-budget.ts
  • scripts/test-bedrock-chat.ts
  • src/webapp/components/SyncStatus.tsx
  • src/webapp/components/example-AIAssistant.tsx
  • src/webapp/components/example-GuitarRecommendation.tsx
  • src/webapp/db-collections/todos.ts
  • src/webapp/integrations/bedrock-adapter/index.ts
  • src/webapp/lib/bedrock-budget.ts
  • src/webapp/lib/demo-store-devtools.tsx
  • src/webapp/lib/demo-store.ts
  • src/webapp/routes/__root.tsx
  • src/webapp/routes/demo/start.server-funcs.tsx
  • src/webapp/routes/demo/store.tsx
  • src/webapp/routes/demo/tanchat.tsx
  • src/webapp/routes/example.guitars/$guitarId.tsx
  • src/webapp/utils/demo.tools.ts
  • vite.config.ts
✅ Files skipped from review due to trivial changes (3)
  • lib/constructs/Webapp.ts
  • src/webapp/db-collections/todos.ts
  • src/webapp/lib/bedrock-budget.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/webapp/components/SyncStatus.tsx
  • lib/constructs/WebappServer.ts
  • scripts/test-bedrock-budget.ts
  • src/webapp/routes/demo/start.server-funcs.tsx
  • src/webapp/integrations/bedrock-adapter/index.ts

Comment on lines +3 to +5
on:
pull_request:
types: [opened, reopened, synchronize]
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

Include ready_for_review in the trigger list.

Draft PRs that are marked ready without a fresh commit will skip this workflow entirely, so the first VP run depends on someone manually rerunning it or pushing again.

Suggested change
 on:
   pull_request:
-    types: [opened, reopened, synchronize]
+    types: [opened, reopened, synchronize, ready_for_review]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/pr-vp-check.yml around lines 3 - 5, The pull_request
trigger's types list currently contains only opened, reopened, and synchronize
so PRs marked ready_for_review won't run the workflow; update the
pull_request.types array in the workflow (the on: pull_request types) to include
"ready_for_review" alongside "opened", "reopened", and "synchronize" so the
workflow runs when a draft PR is marked ready for review.

Comment thread AGENTS.md
Comment on lines +11 to +17
- **Dev server**: `pnpm webapp:dev` — starts the Vite+ dev server on port 3000
- **Lint**: `pnpm lint` (Vite+ / Oxlint) — pre-existing warnings/errors exist in the codebase
- **Format check**: `pnpm format:check` (Vite+ / Oxfmt)
- **Tests**: `pnpm test` (Vite+ / Vitest) — runs CDK infrastructure tests in `accountSetup/`
- **TypeScript check**: `pnpm compile` (tsc --noEmit)
- **Build**: `pnpm webapp:build`
- **Unified checks**: `pnpm check` (Vite+ format + lint)
- **Build**: `pnpm webapp:build` (Vite+ build, Nitro output)
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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Verify that documented commands match package.json scripts

# Check the actual script definitions
echo "=== Checking package.json scripts referenced in AGENTS.md ==="
jq -r '.scripts | {
  "webapp:dev": .["webapp:dev"],
  "lint": .lint,
  "format:check": .["format:check"],
  "test": .test,
  "compile": .compile,
  "check": .check,
  "webapp:build": .["webapp:build"]
}' package.json

Repository: JohannesKonings/tanstack-aws

Length of output: 352


Update documentation to match actual script implementations.

Two commands have inaccurate descriptions:

  • compile: Documented as tsc --noEmit, but actual script is just tsc (missing the --noEmit flag)
  • webapp:build: Documented as "Vite+ build, Nitro output", but the actual script runs node scripts/generate-robots-txt.ts && vp build (the robots.txt generation step is not mentioned)

Update AGENTS.md lines 11-17 to reflect the exact command behavior.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@AGENTS.md` around lines 11 - 17, Update the documentation entries for the npm
scripts named "compile" and "webapp:build" to match the actual scripts: change
the "compile" description to indicate it runs plain "tsc" (not "tsc --noEmit"),
and change the "webapp:build" description to mention it first runs "node
scripts/generate-robots-txt.ts" to generate robots.txt and then runs "vp build"
(Vite/VuePress build), ensuring the AGENTS.md lines referencing compile and
webapp:build reflect these exact behaviors.

Comment thread AGENTS.md
Comment on lines +31 to +47
<!-- intent-skills:start -->

# Skill mappings - when working in these areas, load the linked skill file into context.

skills:

- task: "configure TanStack DB collections and adapters"
load: "node_modules/.pnpm/@tanstack+db@0.5.33_typescript@5.9.3/node_modules/@tanstack/db/skills/db-core/collection-setup/SKILL.md"
- task: "build TanStack DB live queries and filtering"
load: "node_modules/.pnpm/@tanstack+db@0.5.33_typescript@5.9.3/node_modules/@tanstack/db/skills/db-core/live-queries/SKILL.md"
- task: "implement optimistic DB mutations and transactions"
load: "node_modules/.pnpm/@tanstack+db@0.5.33_typescript@5.9.3/node_modules/@tanstack/db/skills/db-core/mutations-optimistic/SKILL.md"
- task: "wire up Vite devtools plugin configuration"
load: "node_modules/@tanstack/devtools-vite/skills/devtools-vite-plugin/SKILL.md"
- task: "configure Nitro server build and deployment behavior"
load: "node_modules/nitro/skills/nitro/SKILL.md"
<!-- intent-skills:end -->
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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Verify that skill file paths in intent-skills block exist

echo "=== Checking if skill files exist ==="

# Check each skill file path from AGENTS.md
skill_paths=(
  "node_modules/.pnpm/@tanstack+db@0.5.33_typescript@5.9.3/node_modules/@tanstack/db/skills/db-core/collection-setup/SKILL.md"
  "node_modules/.pnpm/@tanstack+db@0.5.33_typescript@5.9.3/node_modules/@tanstack/db/skills/db-core/live-queries/SKILL.md"
  "node_modules/.pnpm/@tanstack+db@0.5.33_typescript@5.9.3/node_modules/@tanstack/db/skills/db-core/mutations-optimistic/SKILL.md"
  "node_modules/@tanstack/devtools-vite/skills/devtools-vite-plugin/SKILL.md"
  "node_modules/nitro/skills/nitro/SKILL.md"
)

for path in "${skill_paths[@]}"; do
  if [ -f "$path" ]; then
    echo "✓ Found: $path"
  else
    echo "✗ Missing: $path"
    # Try to find similar paths
    dir=$(dirname "$path")
    base=$(basename "$path")
    echo "  Searching for alternatives..."
    fd -t f "$base" "$(dirname "$dir")" 2>/dev/null | head -3
  fi
done

Repository: JohannesKonings/tanstack-aws

Length of output: 808


🏁 Script executed:

# Read AGENTS.md to verify the indentation issue and understand the context
cat -n AGENTS.md | sed -n '31,50p'

Repository: JohannesKonings/tanstack-aws

Length of output: 1167


Fix indentation on line 46 in intent-skills block.

The load: key on line 46 lacks proper indentation. All other entries have 2-space indentation ( load:), but this entry has none, which will break YAML parsing:

Indentation fix
 - task: "configure Nitro server build and deployment behavior"
-load: "node_modules/nitro/skills/nitro/SKILL.md"
+  load: "node_modules/nitro/skills/nitro/SKILL.md"
📝 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
<!-- intent-skills:start -->
# Skill mappings - when working in these areas, load the linked skill file into context.
skills:
- task: "configure TanStack DB collections and adapters"
load: "node_modules/.pnpm/@tanstack+db@0.5.33_typescript@5.9.3/node_modules/@tanstack/db/skills/db-core/collection-setup/SKILL.md"
- task: "build TanStack DB live queries and filtering"
load: "node_modules/.pnpm/@tanstack+db@0.5.33_typescript@5.9.3/node_modules/@tanstack/db/skills/db-core/live-queries/SKILL.md"
- task: "implement optimistic DB mutations and transactions"
load: "node_modules/.pnpm/@tanstack+db@0.5.33_typescript@5.9.3/node_modules/@tanstack/db/skills/db-core/mutations-optimistic/SKILL.md"
- task: "wire up Vite devtools plugin configuration"
load: "node_modules/@tanstack/devtools-vite/skills/devtools-vite-plugin/SKILL.md"
- task: "configure Nitro server build and deployment behavior"
load: "node_modules/nitro/skills/nitro/SKILL.md"
<!-- intent-skills:end -->
<!-- intent-skills:start -->
# Skill mappings - when working in these areas, load the linked skill file into context.
skills:
- task: "configure TanStack DB collections and adapters"
load: "node_modules/.pnpm/@tanstack+db@0.5.33_typescript@5.9.3/node_modules/@tanstack/db/skills/db-core/collection-setup/SKILL.md"
- task: "build TanStack DB live queries and filtering"
load: "node_modules/.pnpm/@tanstack+db@0.5.33_typescript@5.9.3/node_modules/@tanstack/db/skills/db-core/live-queries/SKILL.md"
- task: "implement optimistic DB mutations and transactions"
load: "node_modules/.pnpm/@tanstack+db@0.5.33_typescript@5.9.3/node_modules/@tanstack/db/skills/db-core/mutations-optimistic/SKILL.md"
- task: "wire up Vite devtools plugin configuration"
load: "node_modules/@tanstack/devtools-vite/skills/devtools-vite-plugin/SKILL.md"
- task: "configure Nitro server build and deployment behavior"
load: "node_modules/nitro/skills/nitro/SKILL.md"
<!-- intent-skills:end -->
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@AGENTS.md` around lines 31 - 47, The YAML under the intent-skills block has a
mis-indented mapping for the task "configure Nitro server build and deployment
behavior" — the `load:` key for that entry must be indented to match the other
skill mappings; update the `load:` line so it has two leading spaces (i.e.,
align `  load:` with the other entries) within the `skills:` block to restore
valid YAML parsing.

@@ -1,9 +1,9 @@
import path from 'node:path';
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:

# First, let's check the file exists and read the relevant lines
cat -n lib/constructs/WebappAssetsDeployment.ts | head -40

Repository: JohannesKonings/tanstack-aws

Length of output: 1620


🏁 Script executed:

# Also check if fileURLToPath is used elsewhere in the codebase
rg "fileURLToPath" --type ts

Repository: JohannesKonings/tanstack-aws

Length of output: 238


Use fileURLToPath() to properly convert import.meta.url to a filesystem path.

new URL(import.meta.url).pathname leaves URL-encoded characters intact and produces /C:/...-style paths on Windows, causing Source.asset(...) to point at non-existent directories.

🛠️ Suggested fix
 import path from 'node:path';
+import { fileURLToPath } from 'node:url';
@@
     const sourcePath = path.join(
-      path.dirname(new URL(import.meta.url).pathname),
+      path.dirname(fileURLToPath(import.meta.url)),
       '../../.output/public',
     );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/constructs/WebappAssetsDeployment.ts` at line 1, The code currently
converts import.meta.url with new URL(import.meta.url).pathname which preserves
URL-encoding and yields incorrect Windows paths; update WebappAssetsDeployment
(and any usage that derives the current file directory) to import {
fileURLToPath } from 'url' and replace new URL(import.meta.url).pathname with
fileURLToPath(import.meta.url), then use path.dirname(...) or path.resolve(...)
as needed so Source.asset(...) receives a proper filesystem path across
platforms.

Comment thread vite.config.ts
Comment on lines +24 to +39
const aiDevtoolsStubPlugin = {
config(_config: unknown, { command, isSsrBuild }: { command: string; isSsrBuild?: boolean }) {
// Nitro/build pulls in @tanstack/ai-devtools-core (Solid.js) whose server build
// Lacks setStyleProperty. Use stub for SSR and for production build (Nitro phase).
const useAiDevtoolsStub = isSsrBuild === true || command === 'build';

if (!useAiDevtoolsStub) {
return undefined;
}

return {
resolve: {
alias: devtoolsStubAliases,
},
};
},
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

🌐 Web query:

In Vite's plugin confighook, doescommand === "build"apply to both client and SSR builds, and isisSsrBuild the correct flag for SSR-only config?

💡 Result:

  • Yes. In a Vite plugin’s config hook, command === 'build' is true for both a normal client build (vite build) and an SSR build (vite build --ssr)—they’re both still the build command. Vite’s docs explicitly describe vite build vs vite build --ssr as building different environments, not different command values. [1]

  • Yes, isSsrBuild is the intended flag when you want SSR-build-only conditional config (i.e., distinguish vite build --ssr from vite build). Vite documents isSsrBuild (and isPreview) as optional flags specifically to differentiate build types. [2]

Practical implication: don’t use command === 'build' to mean “client build”; it means “some kind of build”. Use isSsrBuild === true for SSR-only config, and isSsrBuild === false (or not true) for client-only config. [2]

Sources

  1. Vite “Environment API for Frameworks” – “vite build and vite build --ssr … build the client only and ssr only environments …” [1]
  2. Vite “Configuring Vite” – conditional config mentions isSsrBuild to detect SSR builds [2]

Remove command === 'build' to limit stub aliases to SSR builds only.

Currently, line 28 applies the aliases to any build command, which affects both client and SSR builds. Since isSsrBuild is the correct flag to distinguish SSR builds, the condition should exclude the command check and apply stubs only when isSsrBuild === true, preventing the stubs from reaching the client-side bundle during production builds.

Suggested change
-    const useAiDevtoolsStub = isSsrBuild === true || command === 'build';
+    const useAiDevtoolsStub = isSsrBuild === true;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@vite.config.ts` around lines 24 - 39, The current aiDevtoolsStubPlugin.config
computes useAiDevtoolsStub using "isSsrBuild === true || command === 'build'",
which wrongly applies stub aliases to client production builds; change the
condition in the config for aiDevtoolsStubPlugin so useAiDevtoolsStub is only
true when isSsrBuild === true (remove the command === 'build' clause) so that
devtoolsStubAliases are applied only for SSR builds inside the config function.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants