Skip to content

[Feature]: File-based routing with typed loaders and actions #149

Description

@JosunLP

Pre-flight checklist

  • I searched existing issues and did not find a duplicate request.
  • I explained the problem or use case, not just the desired API.

Problem or use case
bQuery's router (Stable) is programmatic only, and the SSR router bridge matches against a hand-built route table (resolveSSRRoute/createSSRRouterContext) while merely recognizing a meta.loader. There is no file-based routing and no route-level data API comparable to SvelteKit's +page.(server).ts load/form actions or React Router/Remix loaders and actions. This is the biggest structural gap for building real applications: data-coupled routes, nested layouts, and server actions are the backbone of the competing meta-frameworks, and bQuery has the router, SSR, and server pieces but no convention tying them together.

Proposed solution
Add an opt-in, build-tool-agnostic file-route convention plus typed route-level load and action functions that flow data into views and accept mutations — bridging the existing router, ssr (the meta.loader hook), and server modules. Because zero-build is a core goal and a bundled build tool is a non-goal, this must be optional (programmatic routing stays fully supported) and must not ship bQuery's own bundler — a small directory-convention loader plus typed helpers, usable from any bundler or even a simple manifest. Loaders run on server and client navigation; actions post to the server (composing with #132 sessions/CSRF and #140 form actions).

Possible API or UX shape

// routes/users/[id]/+page.ts
import type { Load, Action } from "@bquery/bquery/router";

export const load: Load = async ({ params, ctx }) => {
  return { user: await getUser(params.id) }; // typed, available to the view
};

export const action: Action = async ({ request, ctx }) => {
  await updateUser(await request.formData());
  return { ok: true }; // progressive-enhancement target for <form> (#140)
};

Alternatives considered
Keeping programmatic routing only and documenting manual data-loading patterns — leaves bQuery a layer below SvelteKit/Remix/Nuxt for application structure, which is where adoption decisions are made. Building a full opinionated meta-framework with its own bundler — violates the zero-build and no-bundled-build-tool non-goals; the convention must be optional and bundler-agnostic.

Relevant area
router

Additional context
Cross-cutting: unblocks the data story for ssr (#127) and server (#131), and is the natural home for form actions (#140). This is the highest-leverage capability ticket for "real apps" parity, even though router itself is already Stable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    routerChanges to the router module

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions