TSone

Architecture Overview

This chapter introduces the layered architecture and runtime data flow of TSone, giving you a global picture before you dive into each subsystem.

Design Goals

  • Lightweight: the core package has zero runtime dependencies and relies only on standard browser DOM interfaces.
  • Object-oriented: the framework and application code are organized around class components with explicit object relationships.
  • Strategy-based rendering: render behavior is dispatched to dedicated strategies by VNode type, so new capabilities are added by extending strategies.
  • Bun-native: development, testing, building, and documentation are all driven by Bun.

Layered Architecture

The TSone runtime is organized from top to bottom into an app layer, a component layer, a render layer, and runtime infrastructure, accompanied by a dedicated Bun-native toolchain:

TSone layered architecture diagram
TSone runtime architecture: app layer → component layer → render layer → runtime infrastructure, with the Bun-native toolchain on the right

App Layer

The createApp() function creates a OneApp instance, the single entry point of an application. It is responsible for:

  • Mounting the root component and injecting AppContext (config, version, router) into it.
  • Installing plugins through use(plugin) and calling their hooks during the app lifecycle.
  • Providing global provide/inject, global state, and configuration.
  • Generating an HTML document shell through renderHtmlDocument() for the CLI dev/build pipeline.

Component Layer

All UI is expressed with class components that extend Component<Props, State>. Each component owns reactive state, a local styleManager, and a templateEngine, declares its structure in render(): VNode, and hooks into the full lifecycle, events (emit/on), dependency injection, and error boundaries.

Render Layer

The RendererContext dispatches VNodes to five render strategies (text, element, component, slot, and transition group) using the strategy pattern, and exposes a unified mount / patch / unmount interface. On component updates it diffs the old and new VNodes and converges changes into minimal DOM operations.

Runtime Infrastructure

  • ReactiveSystem: Proxy-based dependency tracking and dispatch, paired with ReactiveScheduler to merge a batch of state changes into a single re-render.
  • Router: route matching, history/hash modes, redirects, and navigation guards; RouterView renders the matched component.
  • StyleManager: one instance per component, compiling style rules into CSS text and injecting a <style> element.

Toolchain

@geektech/tsone-cli provides tsone dev, tsone build, and the development proxy, configured through tsone.config.ts. It reuses renderHtmlDocument() to produce entry pages and performs the first render of the component tree inside a DOM-like document.

Runtime Data Flow

Mount Flow

  • createApp builds a OneApp; mount() resolves the mount point and constructs the root component instance.
  • The root component initializes reactive state, styles, and the template engine, then calls render() to produce a VNode after beforeMount.
  • RendererContext mounts the VNode into the real DOM through its strategies, then onMounted fires.
  • Plugins and global state are injected at the app layer; components access global capabilities through getContext() and the router getter.

Update Flow

Component state is a reactive object; properties read during render become dependencies of the component updateEffect. When state changes, ReactiveScheduler enqueues updateEffect into the microtask queue for batched execution: render() runs again to produce a new VNode, and RendererContext applies DOM diffs. Use flushSync() to read the DOM synchronously, or await nextTick() in async code.

Unmount Flow

unmount walks the VNode tree recursively: beforeUnmount fires first, then child components are unmounted, events and slots are cleared, the styleManager and template bindings are destroyed, the updateEffect is stopped, and onUnmounted fires last.

Design Patterns and Object Relationships

The framework is organized around SOLID principles, with explicit relationships between classes and modules:

PatternLocationDescription
StrategyRendererContext → RenderStrategyRender behavior is dispatched by VNode type; new rendering capabilities only need a new strategy
SingletonReactiveSystem.getInstance()A single global dependency-tracking and dispatch center
Observereffect / updateEffect + ReactiveSchedulerState changes automatically schedule component re-renders
CompositionComponent holds StyleManager and TemplateEngineStyle and template capabilities are composed into components on demand
Dependency injectionapp.provide / component.provide + injectCapabilities resolve up the component parent chain, decoupling consumers from providers
ImplementationRenderStrategy interface + five strategy classesRender strategies depend on an abstraction rather than concrete implementations

Public Surface and Package Structure

The TSone public surface stays small and clear:

  • @geektech/tsone: core APIs (createApp, Component, the reactive family, VNode, renderHtmlDocument, StyleSheet, Transition, TransitionGroup, KeepAlive).
  • @geektech/tsone/router: createRouter, Router, RouterView, RouterLink, useRouter.
  • @geektech/tsone-cli: defineConfig, tsone dev, tsone build, and the development proxy.

Summary

TSone organizes its runtime with the vertical layering of app → component → render, supported horizontally by the reactive system, router, and style management. Continue with Core Concepts, Component System, Reactive System, Routing, and Style Management for the concrete implementations.