nojs

module
v0.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 8, 2026 License: Apache-2.0

README ยถ

nojs

Go Version License Status

The Type-Safe Web Framework for Go Purists

nojs is a high-performance, AOT-compiled web framework that allows you to build sophisticated front-end applications entirely in Go. By treating the Go compiler as your "Inspector," nojs eliminates entire classes of runtime errors through strict type-safety and a familiar, idiomatic developer experience.

โš ๏ธ Project Status: This is an MVP (Minimum Viable Product) and is not production-ready. The API may change, and some features are still in active development. Use for experimentation and feedback.


โœจ Key Features

  • ๐Ÿ”’ Type-Safe Templates - Compile-time validation of props, methods, and expressions
  • โšก Virtual DOM - Efficient diffing and patching for minimal DOM operations
  • ๐Ÿงฉ Component Model - Reusable UI building blocks with Go structs and HTML templates
  • ๐Ÿ—บ๏ธ Built-in Router - SPA routing with layout support and nested routes
  • ๐Ÿ“‹ Optimized Lists - trackBy keys for efficient list updates and re-rendering
  • ๐ŸŽฏ Event Handling - Type-safe event binding validated at compile time
  • ๐Ÿš€ WebAssembly - Near-native performance in the browser via Go WASM
  • ๐Ÿ› ๏ธ AOT Compilation - Template parsing at build time, not runtime

๐Ÿ—๏ธ Core Philosophy

Every feature in nojs is guided by principles designed for developers who value stability and performance over "magic."

  • Type Safety Above All: We prefer compile-time safety over runtime flexibility. Our AOT compiler validates props, methods, and expressions before they ever reach the browser.

  • Go-Idiomatic by Default: Templates and component architectures feel like natural extensions of Go. Syntax patterns (like for...range) are modeled directly on Go semantics.

  • Explicit > Implicit: We favor clarity and control. Features like manual state updates (StateHasChanged()) and mandatory list keys (trackBy) make data flow predictable and easy to debug.

  • Simplicity Through Focus: A lean, focused API that avoids complexity for little practical benefit.

  • Unopinionated Foundation: We provide the core (rendering, lifecycle, type-safety) but leave state management and project structure to you.

For the full principles behind these decisions, read the NoJS Manifesto.


๐Ÿ•’ A Note on the Vibe

This is a "free time" project. Whether you're a senior dev or someone just starting with Go or WASM, there is zero pressure here.

We don't have a corporate roadmap or investors to answer to. We care about building the framework correctly, not quickly. Contributions are welcomed at whatever pace your life allows.


๐ŸŽฎ Live Demo

Want to see nojs in action? Check out the interactive demo at forgelogic.github.io/nojs/demo.

The demo showcases core framework featuresโ€”components, routing, event handling, and list renderingโ€”all running entirely in Go-compiled WebAssembly.


๐Ÿš€ Getting Started

Prerequisites
  • Go 1.25+
  • Make
  • Python 3 (required for make serve, or use any static file server of your choice)

Running the demo app

For detailed instructions on running the demo app, see the Getting Started Guide.


Starting your own project

See the Installation Guide for a step-by-step guide to creating a new project using the demo app as a scaffold.


Repository Structure

The repository is organized as a Go workspace:

  • nojs/ โ€” Core framework code (runtime, VDOM)
  • compiler/ โ€” AOT template compiler (nojsc), maintained as a separate module
  • router/ โ€” SPA routing engine, maintained as a separate module
  • app/ โ€” Example application demonstrating framework features (also the recommended project scaffold)
  • go.work โ€” Workspace configuration linking all modules

The framework (github.com/forgelogic/nojs), compiler (github.com/forgelogic/nojs/compiler), router (github.com/forgelogic/nojs/router), and app (github.com/forgelogic/app) are separate modules that work together during development.

Note: The compiler, router, and demo app are currently co-located in this repository for convenience during active development. Once each reaches a stable API, it will be moved to its own dedicated repository.

Build commands
Command Action
make full Compiles templates + WASM (Development)
make full-prod Compiles templates + WASM (Production/Optimized)
make wasm Rebuilds WASM only (Fast: ~1-2 seconds)
make serve Starts development server on port 9090
make clean Removes generated WASM binaries

Tip: Enable "Disable cache" in your browser's DevTools Network tab to ensure the WASM module reloads on every refresh.


๐Ÿ› ๏ธ The AOT Compiler

The heart of nojs is its Ahead-of-Time compiler. It transforms declarative HTML templates (.gt.html) into high-performance Go component code.

How It Works

The compiler scans directories for *.gt.html files and auto-generates corresponding .generated.go files with Render() methods.

Development Workflow
  1. Create your component:

    • MyComponent.gt.html - HTML template with Go expressions
    • mycomponent.go - Go struct with state and event handlers
  2. Compile templates:

    Bash

    # Compile all templates in the components directory
    make full
    
    # Or run the compiler directly
    go run github.com/forgelogic/nojs/cmd/nojs/compiler -in ./app/internal/app/components
    

    This generates MyComponent.generated.go with the Render() method.

  3. Use the component: Import and instantiate your component like any Go struct. The framework handles rendering, diffing, and updates.

CLI Options
  • -in <directory> - Source directory to scan for *.gt.html files
  • -dev - Enable development mode (verbose errors, warnings)

๐Ÿ“š Quick Example

Here's a simple counter component to illustrate the framework:

counter.go:

package components

import "github.com/forgelogic/nojs/runtime"

type Counter struct {
    runtime.ComponentBase
    Count int
}

func (c *Counter) Increment() {
    c.Count++
    c.StateHasChanged() // Trigger re-render
}

func (c *Counter) Decrement() {
    c.Count--
    c.StateHasChanged() // Trigger re-render
}

Counter.gt.html:

<div class="counter">
    <h2>Count: {Count}</h2>
    <button @onclick="Increment">+</button>
    <button @onclick="Decrement">-</button>
</div>

๐Ÿ“– Documentation

Full documentation is available at forgelogic.github.io/nojs.


๐Ÿค Contributing

nojs is an open-source project. We welcome contributions from developers who share our passion for type-safe, performant web tools.

For detailed contribution guidelines, see CONTRIBUTING.md.


๐Ÿ“œ License

Distributed under the Apache License 2.0. See LICENSE for more information.

Directories ยถ

Path Synopsis
compiler module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL