also looking at this
fix(views): tell route.serve where the components live
#5Two servers render stx here and only one of them was told where the components are.
The dev frontend renders through bun-plugin-stx, which loads config/ui.ts itself (componentsDir: 'resources/components') — components resolve, which is why the product looks fine in a browser during ./buddy dev. Everything that boots through route.serve() — the API server behind ./buddy dev, the whole e2e suite, a production boot — renders through bun-router's file-based routing instead, and that path never reads the config: renderStxFile falls back to join(viewsDir, 'components') = resources/views/components, which does not exist. Every <Component /> tag on those boots renders as a literal [Error loading component: ENOENT ...] line in the HTML. <CsrfField /> is one of those components, so any form served that way loses its token and submits into a 403. Layouts kept working by coincidence: the same fallback picks resources/views/layouts, which happens to be where they live (the config's layoutsDir: 'resources/layouts' doesn't exist and is ignored by the working pipeline too).
The fix is routes/views.ts: one route.bunRouter.views({ componentsDir }) call reading config/ui.ts, registered in app/Routes.ts so it loads with the route files — both boot paths run route.importRoutes() before serving, so the render config is set wherever rendering happens. It forwards componentsDir only, deliberately: forwarding the config's nonexistent layoutsDir would break every page while fixing nothing (worth fixing that config value separately, or teaching the Stacks facade to forward validated ui config into bun-router — the framework-side fix this works around; flagged for the stacks checkout).
Verified by booting exactly the way the e2e suite does and fetching /: before, errorLoadingComponent=true (MarketingNav renders as an error line); after, errorLoadingComponent=false marketingNavRendered=true. Full suite: no new failures (the remaining ones are #3's and #4's subjects, plus the LFS tests that need the private ts-git-lfs from #2's note).
🤖 Generated with Claude Code
2 changed files on the files tab, with 0 review threads.