What Is the jframe Repository? A Deep Dive into the Modular Go Framework

The jframe repository is a lightweight, modular Go framework that provides a plug-in architecture for building server-side applications, featuring a kernel-based dependency injection system and configurable module lifecycle management.

The jframe repository offers Go developers a structured approach to building scalable backend services through its modular design. This open-source framework centers around a kernel that orchestrates module lifecycles while handling dependency injection and graceful shutdown procedures. By implementing the Module interface, developers can create self-contained components that the kernel initializes, configures, and manages concurrently.

Core Architecture of the jframe Repository

The Kernel and Engine

At the heart of the jframe repository lies the Engine struct defined in core/kernel/kernel.go. This engine maintains a global context, a registry of modules, and a dependency injector (github.com/juanjiTech/inject/v2). The kernel orchestrates the entire application lifecycle through the StartModule method, which unmarshals per-module configuration, invokes lifecycle hooks, and launches each module's Start method in its own goroutine.

The Module interface, defined in core/kernel/module.go, establishes the contract between the kernel and business logic. Developers embed kernel.UnimplementedModule to inherit default no-op implementations for optional hooks.

Module Lifecycle Management

The jframe repository implements a sophisticated lifecycle system with six distinct hooks that the kernel executes sequentially:

  • PreInit – Early initialization before configuration loading
  • Init – Core initialization with access to the dependency hub
  • PostInit – Post-initialization cleanup and validation
  • Load – Service loading and dependency resolution
  • Start – Launch of concurrent goroutines for active services
  • Stop – Graceful shutdown handling with context and wait groups

Dependency Injection in jframe

The Hub Pattern

The jframe repository utilizes a Hub pattern for dependency injection, enabling modules to share resources and services without tight coupling. Modules interact with the hub through several key methods:

  • hub.Map(value) – Registers a value or service instance for global access
  • hub.Value(target) – Retrieves a previously mapped value by type
  • hub.Invoke(function) – Executes a function with injected dependencies
  • hub.Load(target) – Loads dependencies into a target struct or pointer

The example module in mod/example/mod.go demonstrates this pattern by registering a simple string and a jin HTTP engine, illustrating how services propagate across module boundaries.

Configuration Management with Viper

Each module in the jframe repository may expose a configuration struct via the Config() method. The kernel dynamically constructs a configuration structure keyed by module names, enabling Viper to unmarshal environment variables or YAML files into module-specific configurations.

This design maintains module encapsulation while supporting centralized configuration management. The kernel handles the complexity of mapping MODULE_NAME_ENABLED style environment variables to the appropriate struct fields.

Running a jframe Application

The Server Command

The jframe server CLI command, implemented in cmd/server/server.go, serves as the entry point for production deployments. This command:

  1. Loads application configuration from specified files
  2. Initializes optional observability tools (e.g., Sentry)
  3. Creates TCP listeners and registers them in the kernel hub
  4. Uses cmux for protocol multiplexing on shared ports
  5. Starts all registered modules concurrently
  6. Handles graceful shutdown on SIGINT/SIGTERM signals

Creating Custom Modules

To extend the jframe repository with custom functionality, developers create a package that implements the kernel.Module interface:

package mymod

import (
    "context"
    "sync"
    "github.com/juanjiTech/jframe/core/kernel"
)

var _ kernel.Module = (*Mod)(nil)

type Mod struct {
    kernel.UnimplementedModule
}

func (m *Mod) Name() string { return "mymod" }

type Config struct {
    Enabled bool `mapstructure:"enabled"`
}

func (m *Mod) Config() any { return &Config{} }

func (m *Mod) Init(h *kernel.Hub) error {
    h.Map(&MyService{})
    return nil
}

func (m *Mod) Load(h *kernel.Hub) error {
    var svc *MyService
    if err := h.Load(&svc); err != nil {
        return err
    }
    return nil
}

func (m *Mod) Stop(wg *sync.WaitGroup, ctx context.Context) error {
    defer wg.Done()
    return nil
}

Register the module in modList/modList.go and the kernel automatically handles initialization and lifecycle management.

Summary

  • The jframe repository provides a lightweight, modular framework for building Go server applications with a plug-in architecture.
  • The kernel in core/kernel/kernel.go orchestrates module lifecycles through six distinct hooks: PreInit, Init, PostInit, Load, Start, and Stop.
  • Dependency injection occurs via the Hub pattern using methods like hub.Map and hub.Load, enabling loose coupling between modules.
  • Configuration management leverages Viper for per-module config unmarshalling while maintaining encapsulation.
  • The jframe server command in cmd/server/server.go handles production deployment, protocol multiplexing with cmux, and graceful shutdown.

Frequently Asked Questions

What is the jframe repository used for?

The jframe repository is used for building server-side Go applications that require a modular, extensible architecture. It is particularly suited for microservices and backend systems where developers need clean separation of concerns, dependency injection, and managed lifecycle hooks for different components.

How does jframe handle dependency injection?

Jframe implements dependency injection through a Hub pattern where the kernel provides a Hub object to modules during initialization. Modules register services using hub.Map() and retrieve them using hub.Load(), hub.Value(), or hub.Invoke(). This system, backed by the github.com/juanjiTech/inject/v2 library, allows type-safe dependency resolution without tight coupling between modules.

What lifecycle hooks are available in jframe modules?

Jframe modules support six lifecycle hooks executed sequentially by the kernel: PreInit for early setup, Init for core initialization with hub access, PostInit for validation, Load for dependency resolution, Start for launching concurrent goroutines, and Stop for graceful shutdown. Developers embed kernel.UnimplementedModule to inherit default no-op implementations for hooks they don't need.

How do I configure modules in jframe?

Each module can expose a configuration struct by implementing the Config() method that returns a pointer to the struct. The kernel dynamically builds a configuration map keyed by module names, allowing Viper to unmarshal environment variables or YAML files into the appropriate module configs. This keeps configuration centralized while maintaining module encapsulation.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →