Skip to content

feat: top-level router/api props on StackProvider with framework presets#134

Merged
olliethedev merged 2 commits into
mainfrom
feat/127-router-adapter
Jul 3, 2026
Merged

feat: top-level router/api props on StackProvider with framework presets#134
olliethedev merged 2 commits into
mainfrom
feat/127-router-adapter

Conversation

@olliethedev

Copy link
Copy Markdown
Collaborator

Closes #127

Summary

  • StackProvider now accepts optional router and api props. Resolution order in usePluginOverrides is per-plugin override → top-level router/api → hook defaults, so existing per-plugin Link/navigate/etc. overrides keep working as an escape hatch (fully non-breaking; overrides is now optional).
  • New framework preset entry points: nextRouter() from @btst/stack/next, reactRouter() from @btst/stack/react-router, tanstackRouter() from @btst/stack/tanstack. Presets are plain objects; fields needing framework hooks are produced by a useRouter hook the provider evaluates internally via a RouterBridge child (no conditional hook calls). The frameworks are optional peer dependencies and externalized in the build.
  • The StackRouter contract already includes getSearchParams/setSearchParams as required by URL-synced list state: filters, tabs, and pagination survive refresh, back button, and sharing #133, so the three framework bindings only need to be touched once. The Next.js getSearchParams reads window.location.search instead of useSearchParams() to avoid a Suspense/CSR bailout during SSG.
  • Rewrote the three codegen pages layouts (Next.js layout: 424 → ~200 lines, remaining bulk is genuinely plugin-specific demo config) plus all satellite directory/* and cms-example providers to use the presets.
  • Updated the installation guide's "Set Up Layout Provider" step for all three framework tabs, documenting the resolution order.
  • Added unit tests covering the full resolution precedence (10 tests).

Test plan

  • pnpm build, pnpm typecheck, pnpm lint, pnpm knip (stack) pass locally
  • pnpm vitest run in packages/stack — 235 tests pass, including new router-overrides.test.tsx
  • Codegen E2E suites for all three frameworks pass in CI

Made with Cursor

…presets (#127)

Promotes the repeated per-plugin Link/navigate/refresh/Image and
apiBaseURL/apiBasePath wiring to top-level `router` and `api` props on
StackProvider, with shipped presets at @btst/stack/next,
@btst/stack/react-router, and @btst/stack/tanstack. Resolution order is
plugin override -> top-level router/api -> plugin defaults, so existing
per-plugin overrides keep working as an escape hatch (non-breaking).
The StackRouter contract already includes the getSearchParams/
setSearchParams fields required by #133.

Co-authored-by: Cursor <cursoragent@cursor.com>
@vercel

vercel Bot commented Jul 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
better-stack-docs Ready Ready Preview, Comment Jul 3, 2026 10:24pm
better-stack-playground Ready Ready Preview, Comment Jul 3, 2026 10:24pm

Request Review

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

Security Review — No High-Confidence Vulnerabilities Found

Reviewed the full diff for PR #134 (feat/127-router-adapter). The changes introduce three new framework router presets (nextRouter, reactRouter, tanstackRouter) and a top-level router/api prop on StackProvider. Here is a threat-by-threat breakdown:

✅ Injection (SQL / Command / Path Traversal / Template)

No injection risks identified. The only URL construction in the new code is in setSearchParams, where the query string is built with URLSearchParams.toString(), which properly percent-encodes all key-value pairs. The pathname is sourced from trusted browser APIs (window.location.pathname or router.state.location.pathname), not from user input.

✅ Authentication / Authorization Bypasses

Not in scope for this PR. The changes are purely client-side routing abstractions. No auth gates, session tokens, or permission checks are touched.

✅ Secrets Handling / Token Leakage

No secrets are introduced, logged, or exposed. The api.baseURL / api.basePath values are plain configuration strings provided by the app developer. The documented process.env.BASE_URL pattern is conventional SSR config — not a secret and not logged.

✅ Unsafe Deserialization / SSRF

No deserialization occurs. The StackApiConfig.baseURL is developer-controlled (set in StackProvider props), not derived from user input, so there is no SSRF surface introduced by this PR.

✅ XSS / Open Redirect

All three link wrapper components spread extra props through to framework-native Link components (Next.js, React Router, TanStack). React's own attribute sanitization guards against javascript: hrefs in the rendered DOM. Framework Link components apply their own validation on top. No new XSS surface is opened.

The navigate function accepts an arbitrary string path and delegates to the framework router — the same trust model that existed before this PR. Plugins calling navigate(userInput) with unvalidated user data would be an application-level concern, not one introduced here.

✅ Supply-Chain / Dependency Risk

The new optional peer dependencies (next ≥15, react-router ≥7, @tanstack/react-router ≥1) are all widely-used, actively maintained packages with established security track records. Lock file entries use pinned integrity hashes. No suspicious or unknown packages are added.

Low-Severity Observations (not blocking)

  • href || "#" fallback in NextLinkWrapper — if a plugin renders a link without an href, it silently navigates to # instead of failing visibly. No security impact, but could mask missing-href bugs during development.
  • process.env.BASE_URL undocumented production requirement — the docs example falls back to http://localhost:3000 on the server when BASE_URL is unset. In a misconfigured production deploy, SSR-side API calls would silently target localhost. Worth a callout in the docs example, but not a vulnerability.

No action required from a security standpoint. The implementation is clean.

Open in Web View Automation 

Sent by Cursor Automation: Find vulnerabilities

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Shadcn registry validated — no registry changes detected.

Co-authored-by: Cursor <cursoragent@cursor.com>
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.

Top-level router adapter on StackProvider (framework presets for Link/navigate/refresh/Image)

1 participant