Skip to content

RevoTale/no-js

Repository files navigation

no-js

Status: Work in Progress

no-js is an opinionated Go framework for server-rendered web applications.

It is built around a strict web/* app tree, a generated App Bundle, and a convention-first runtime.

Start Here

For app developers using no-js:

For contributors developing no-js itself:

  • Developing no-js Repository boundaries, main implementation areas, and contributor rules.
  • AI Agents A framework-repo reading order and editing guide for agents.

Feature Guides

  • Routing and Generation Route tree conventions, generated handlers, resolver contracts, and the App Bundle.
  • HTTP Server and Runtime httpserver.NewApp(...), default runtime wiring, and Custom Config.
  • Metadata and Head MetaContext, <head> composition, alternates, and HTMX metadata patches.
  • i18n Localized routing, generated message keys, and request-scoped translation context.
  • Discovery robots.go, feed.go, sitemap.go, and generated sitemap chunks.
  • Static Assets Fingerprinted asset output, manifests, runtime prefixes, and public-file boundaries.
  • Site Resolution Site Resolver contracts and request-aware canonical roots.
  • Request Cache and Partials Request-scoped cache sharing and HTMX partial rendering behavior.

Using no-js In An App

Core Contract

The route generator is strict. The happy path assumes:

web/routes          route tree
web/generated       generated route modules and App Bundle boundary
web/resolvers       handwritten resolver methods
web/view            runtime contracts used by generated code
web/assets          source bundled static assets
web/assets-build    generated hashed static assets
web/public          fixed-path public files served by convention

See App Conventions for the full layout and route rules.

Happy Path

The preferred runtime integration is:

handler, err := httpserver.NewApp(httpserver.Config[*runtime.Context]{
	App:    generated.Bundle(appContext),
	Custom: customConfig,
})

Terminology:

Framework Config: generic runtime behavior only
App Bundle: generated route/runtime contract
Custom Config: isolated app-specific hooks
Site Resolver: shared domain and canonical URL policy
Advanced composition: any app-owned package, only when needed

Convention defaults:

Assets manifest: web/assets-build/manifest.json
Static prefix: /_assets/
Public files: web/public
Localization: auto-wired when built-in i18n is enabled and `web/i18n/messages` exists

Discovery Conventions

Reserved files under web/routes return structured discovery data. sitemap.go and feed.go may live at the route root or in nested route directories. The framework owns the transport, endpoint paths, and XML/text rendering:

  • robots.go returns discovery.Robots
  • sitemap.go returns []discovery.SitemapEntry, plus optional GenerateSitemaps and SitemapByID
  • feed.go returns discovery.FeedDocument

Use the exported structs in framework/discovery/discovery.go as the field-level source of truth.

Specification references:

Build Config

no-js supports an optional root config file named no-js.bundle.yaml.

This file is for build-time configuration only. It controls deterministic inputs such as project layout paths, feature flags used during layout resolution, and static asset build settings.

If no-js.bundle.yaml is missing, the CLI uses framework defaults. A missing config file is not an error.

If the file exists, version: 1 is required and unknown fields are rejected.

YAML values override defaults field by field. Unspecified fields keep their default values.

There are no globally required operational YAML fields. Requirements are resolved from the command and enabled features. For example, go.mod, web/routes, and web/view must exist, the resolved i18n directory must exist if i18n routing is enabled, and static asset paths must be valid when running static asset generation.

Invalid YAML is an error.

no-js.bundle.yaml must not contain runtime or environment-specific values. Keep process-time configuration such as listen address, site-resolution policy, API tokens, analytics IDs, cache overrides, advanced asset overrides, and service wiring in app-owned Go server code.

Example default-equivalent config:

version: 1

project:
  routes_dir: web/routes
  generated_dir: web/generated
  resolvers_dir: web/resolvers
  view_dir: web/view
  i18n_dir: web/i18n
  assets_dir: web/assets
  assets_build_dir: web/assets-build

server:
  features:
    i18n_routing: auto
    static_assets: auto
    health_endpoint: auto

i18n:
  mode: auto

static_assets:
  manifest_path: web/assets-build/manifest.json

manifest_path points to generated static-bundle metadata. It stores the asset hash used by the runtime to construct the final versioned asset prefix. The happy path uses runtime convention defaults instead of manual asset wiring.

Nuances

  • This framework is intentionally opinionated. The generator assumes the strict web/* layout and specific template signatures.
  • The preferred runtime integration is generated.Bundle(appContext) with httpserver.NewApp(...).
  • Generated code imports web/view, but current view contracts still use the package identifier runtime.
  • The generator is module-aware: framework imports point to github.com/RevoTale/no-js, but generated app imports are resolved from the consuming app's go.mod.
  • Localization is convention-first: built-in i18n is generated when enabled and web/i18n/messages exists.
  • Advanced composition is supported, but it is not tied to a reserved package or directory name.
  • Site and canonical-domain policy should be centralized through a Site Resolver.
  • i18n locales are currently normalized to two-letter lowercase codes.
  • HTMX support is request-driven. Partial requests are detected through HX-Request, and metadata patches are emitted through response headers.
  • Static assets and public files are separate concerns: /_assets/ is the default runtime prefix for fingerprinted build output, while public files are served as fixed request paths.

Origin

no-js originated as an extraction from RevoTale/blog.

About

No-JS is a front-end web framework built with Go, Templ and HTMX. Write a minimal code and gain the greatest performance. Directory-based router and strict data resolvers.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages