Documentation menu

Roadmap

Framework capabilities

Status: Capability map. This document connects Goldar’s current server runtime to the intended full-stack framework. A capability is not implemented until its acceptance scenarios are executable in the workspace.

Goldar must provide one coherent lifecycle across seven application concerns:

  1. Views
  2. Styling
  3. Routing
  4. Data fetching
  5. Forms
  6. Application state
  7. Page transitions

They are not seven independent packages. Views define what can be rendered, routing defines which view graph is active, data and state supply that graph, forms mutate it, styling describes its presentation, and page transitions enhance a completed navigation.

Current capability map

ConcernImplemented todayStill required
ViewsCallable compiled .hbs modules with exact frontmatter-derived prop types, safe blocking HTML rendering, explicit trusted HTML, lexical blocks and loops, imported template tags, fragments, one layout outlet, and deprecated defineView() compatibility.Streaming, route/head asset manifests, keyed client list patches, hydration, and client patch boundaries.
StylingTop-level scoped and global template styles compile through Vite.Route asset manifests, automatic server links, navigation loading, and scoped keyframes.
RoutingCompositional Router/Application, Hono GET and POST registration, params, duplicate-path validation, direct View/Response results, and explicit response metadata.A shared route manifest, nested matches, browser history, focus, scroll, and cancellation.
Data fetchingConcurrent request-scoped Data.load() execution and deduplication by route-owned instance.Explicit states, refresh, invalidation, cache policy, lazy resolution, and client navigation behavior.
FormsRoute-local POST dispatch, action references, form snapshots, preserved invalid values and field errors, redirects, successful rerendering with owned-data revalidation, enhanced-submit header support, and same-origin CSRF protection.Automatic template binding, client-enhanced submission, framework-owned pending/focus behavior, form-level errors, schema adapters, and streaming file uploads.
Application stateNamed route-owned stores plus typed router createStores() records attached to routes, fresh per server request.Reactive route state, shared browser lifetime, serialization rules, persistence, subscriptions, and teardown.
Page transitionsDesign intent only.A navigator, stable patch boundaries, transition naming, history direction, reduced-motion behavior, and interruption semantics.

The compiled-view foundation reconciles the original object-model split: routes own named resource instances and return a normalized result containing either a View or a raw Response escape hatch.

Views

Direction: A compiled .hbs module exports a typed function that returns an opaque View. Calling it must not require a browser DOM and must not return a Response.

The initial view contract must define:

  • Text escaping by default and an explicit trusted-HTML boundary.
  • Attributes, properties, events, children, and outlets as distinct operations.
  • Layout composition without filesystem semantics.
  • A server renderer that can produce a complete HTML response.
  • Stable region identity for later client patches.
  • Head contributions and referenced assets without allowing arbitrary order-dependent mutation.

Streaming and fine-grained client patches are later rendering strategies over the same view tree; they must not require authors to rewrite a route.

First executable acceptance scenario: compile a typed .hbs view, compose it inside a layout, escape untrusted text, render a complete HTML response, and test the result without a DOM.

Styling

Direction: Goldar uses CSS as the styling language and compiles top-level .hbs <style> blocks without a CSS-in-JS runtime.

Ownership is explicit:

  • A top-level <style> is removed from rendered markup and scoped to elements authored by that template with a zero-specificity marker.
  • <style is:global> opts an entire block out of scoping; :global(...) escapes one selector.
  • Vite parses and emits compiled styles as ordinary CSS assets. virtual:goldar/client imports the project style graph and discovered browser components.
  • The application may still import global CSS for document defaults, tokens, and shared utilities.
  • A custom element owns its Shadow DOM styles. Goldar may load its module, but it does not reach into the component and rewrite those styles.
  • Ordinary light-DOM CSS follows browser cascade rules. Scope attributes do not cross into child views or a custom element’s Shadow DOM.

The current browser entry emits styles in deterministic template and block order and supports Vite development updates. A route asset manifest and automatic server-rendered stylesheet links remain future work. Until that manifest exists, applications must include the CSS asset emitted by their browser build in the document shell. Enhanced navigation must eventually load the next route’s required styles before revealing patched content.

Scoped @keyframes currently produce a source-located error; global keyframes may be declared in <style is:global>. Handlebars interpolation in CSS is rejected in favor of CSS custom properties.

Next acceptance scenario: two routes share a global stylesheet, each contributes one route stylesheet, server output links the exact manifest in deterministic order, and simulated navigation never reveals the next route without its required CSS.

Routing

Direction: One inspectable route manifest drives both the Hono adapter and the browser navigator. Plain anchors remain the primary navigation API.

The manifest must describe:

  • Route identity, path pattern, parent relationship, and layout chain.
  • Parameter names and matched values.
  • The view, data, action, store, script, and stylesheet capabilities used by the route.
  • Not-found, redirect, and error-boundary ownership.

The server creates a fresh matched route graph for every request. The browser may preserve parent route graphs while their matches remain active. Search-parameter changes, trailing-slash policy, base paths, and nested route precedence must have deterministic matching rules.

Client interception is a later adapter over this contract. External links, downloads, modifier keys, non-default pointer buttons, explicit targets, hash-only links, and explicit reloads retain native browser behavior.

First executable acceptance scenario: the same manifest matches a nested server request and a simulated client navigation to the same route/layout chain, including params, not-found behavior, and an ordinary-anchor fallback.

Data fetching

Direction: A Data instance is a resource with identity and a state machine. Request deduplication is guaranteed; cross-request caching is an explicit policy.

The first complete resource lifecycle is:

idle -> loading -> data
               -> error

data -> revalidating -> data
                     -> error with stale data

Goldar must deduplicate reads of the same resource instance within a resolution scope. It must not assume that every instance of one Data subclass is the same resource. A refresh runs through the resource coordinator; authors do not implement it by calling load() directly.

Cache policy must define scope, key, freshness, identity boundaries, invalidation, and stale-data behavior before durable caching ships. Authenticated data must never cross identity boundaries. Abandoned requests and navigations propagate an AbortSignal without claiming that every underlying operation is cancellable.

First executable acceptance scenario: two views read one resource instance and cause one load; a second configured instance loads independently; failure, retry, refresh, abort, and stale-data revalidation produce deterministic view states.

Forms

Direction: Every mutation starts as a standard HTML form submission. Client enhancement uses the same action identity, validation, mutation, and result semantics.

The existing route-local dispatch and CSRF behavior are the transport foundation. Actions return one of the implemented branded results or use a raw Response as an explicit escape hatch:

  • invalid carries field errors and safe submitted values.
  • redirect carries a location and supported redirect status.
  • success reloads route-owned data and may validate a narrower owned-resource revalidation list.

Authors currently pass RouteContext.action() metadata to a view and render its route-local hidden field. Automatic template binding remains future work. Enhanced submissions add pending and interruption behavior, but do not create a separate mutation API. File uploads must preserve streaming and platform limits; the framework must not silently buffer arbitrary multipart bodies.

After an invalid submission, the renderer preserves accessible labels and errors and moves focus to a useful error summary or invalid field. Ambiguous mutations are not automatically retried.

First executable acceptance scenario: one form succeeds without JavaScript, fails validation with preserved values and accessible errors, redirects after success, and follows the same paths through an enhanced submission that revalidates a named resource.

Application state

Direction: Store is ordinary class state with explicit ownership. “Application state” is not one global lifetime.

Goldar distinguishes four scopes:

  • Request: server-only state shared by work within one HTTP request.
  • Route: interactive state owned by one active route graph and disposed when that match exits.
  • Application: explicitly shared browser state owned by the running application.
  • Persistent: state deliberately synchronized with a URL, cookie, server store, or browser storage mechanism.

Direct field reads and assignments are the authoring model. The compiler/runtime may instrument them, but observation, derived values, collection changes, subscription disposal, and method binding must remain understandable as ordinary TypeScript. Server stores are never process-global singletons. Serialization is opt-in and must define how sensitive values are excluded.

The implemented router store factory establishes typed this.stores access and request isolation for stores shared by routes in one graph. It does not retain state between separate server requests. Retaining an application store across browser navigation requires the future navigator lifecycle.

First executable acceptance scenario: assigning a route store field updates its dependent view; the state survives a child navigation, is disposed when the owning route exits, never leaks across server requests, and serializes only explicitly allowed fields.

Page transitions

Direction: Page transitions are a progressive enhancement applied to a navigation commit. They do not perform routing, data loading, or DOM patching themselves.

The navigator must work correctly before transitions are enabled. Once the next route’s critical data and styles are ready, Goldar may wrap the patch in document.startViewTransition(). When the API is unavailable or reduced motion is requested, the same navigation commits without animation.

The transition contract must define:

  • Which route or view owns a transition name.
  • How forward, back, replace, and redirect navigation select direction.
  • How duplicate shared-element names are diagnosed.
  • When focus, title, scroll restoration, and hash targeting occur.
  • What happens when a second navigation interrupts loading or animation.
  • How a failed navigation retains the current useful document.

Cross-document transitions may be supported later, but the first implementation should prove same-document navigation because Goldar controls that patch lifecycle.

First executable acceptance scenario: forward and back navigation patch the correct outlet, restore focus and scroll, respect reduced motion, fall back without the View Transition API, and cancel an interrupted navigation without exposing a half-updated document.

Delivery order

Each milestone promotes at least one sketch into a built, tested example.

  1. Compiled-view foundation (implemented): route-owned instances, normalized route results, View IR, Handlebars compilation, blocking SSR, layouts, and escaping.
  2. Styling and manifests: add route/head asset manifests and automatic document links to the existing deterministic CSS output and View program capability model.
  3. Server routing and data: share a manifest and matcher, add nested lifecycles, and implement instance-keyed data states with request deduplication.
  4. Server form results (implemented): add invalid, redirect, success, preserved-value, and owned-data revalidation outcomes to the existing secure dispatch.
  5. Form binding and enhancement: bind templates to action capabilities and add client pending, interruption, focus, and upload behavior without changing the native submission contract.
  6. Application state: add route and application store ownership, observation, serialization, and deterministic disposal.
  7. Enhanced routing: add anchor/form interception, history, preload, cancellation, outlet patching, focus, and scroll behavior.
  8. Page transitions: layer transition naming and animation over the completed navigator.

This order is a dependency graph, not a prohibition on design work. Styling, accessibility, failure behavior, and compiler diagnostics must be specified with the foundational capability they constrain rather than deferred to final polish.