Create a Module

Learn how to bootstrap, structure, and manage dependencies for a new JopiJS module.

Overview

In JopiJS, everything is a Module. Whether it's a simple set of pages or a complex authentication system, the structure remains the same. A module is essentially a self-contained "mini-app" that lives inside your project.

In this guide, you will learn how to:

  • Create a module manually or via the CLI.
  • Understand the purpose of each file and folder.
  • Initialize logic for both the Server and the Browser.
  • Manage dependencies and ensure module portability.

1. Quick Start: Creating a Module

The simplest way to create a module is to add a folder prefixed with mod_ inside the src/ directory. JopiJS automatically detects these folders.

Method A: Manual (The simplest way)

Simply create a folder:

src/
└── mod_my_feature/    # That's it! JopiJS now recognizes this as a module.

You can use the jopi toolkit to generate a module with a standard skeleton.

npx jopi mod-new my_module_name

Run this command at the root of your project. It will create src/mod_my_module_name/ with basic files.


2. Module Anatomy

Each folder and file in a module has a specific role. While all are optional, here is the standard structure:

ElementRole
@routes/Defines the URLs and pages exposed by the module.
@alias/Shared items of the module (components/logic shared with others).
uiInit.tsxInitialization code for the Browser (and SSR).
serverInit.tsInitialization code for the Server only.
package.jsonModule-specific dependencies and identity.

3. Initialization Logic

UI Initialization (uiInit.tsx)

This file is the entry point for your module's UI logic. It runs in the browser when the app loads and also on the server during SSR to ensure the initial HTML is consistent.

src/mod_my_feature/uiInit.tsx
import { JopiUiApplication } from "jopijs/ui";
import { EventPriority } from "jopi-toolkit/jk_events";

export default function(uiApp: JopiUiApplication) {
    // Register logic to run once everything is loaded
    uiApp.addUiInitializer(EventPriority.normal, () => {
        console.log("Module initialized in the browser!");
    });
}

Server Initialization (serverInit.ts)

This file runs only once when the server starts. It's the place to configure middlewares, authentication, or database connections.

src/mod_my_feature/serverInit.ts
import { JopiWebSiteBuilder } from "jopijs";

export default async function(webSite: JopiWebSiteBuilder) {
    console.log("Module initialized on the server!");
    
    // webSite.configure_something()...
}

4. Dependencies & Portability

One of JopiJS's core strengths is Isolation. A module should be able to be moved from one project to another with ease.

Local package.json

To achieve this, each module can have its own package.json.

Best Practice: Always add dependencies used by a module to its local package.json, not to the project root.
This makes the module truly portable.

src/mod_my_feature/package.json
{
  "name": "mod_my_feature",
  "version": "1.0.0",
  "dependencies": {
    "lucide-react": "latest",
    "jopimod_my_dependency": "latest" 
  }
}

Node.js Workspaces

JopiJS uses Node.js Workspaces to manage these nested dependencies.
When you run npm install (or bun install) at the root:

  1. JopiJS automatically registers your mod_* folders in the root package.json.
  2. All dependencies across all modules are installed in a single, optimized step.
  3. You get the benefit of a monorepo structure without the complexity.

Note: You may need to run npm install twice to ensure all dependencies are installed.


Summary

  • Prefix folders with mod_ to create a module.
  • Use uiInit.tsx for logic that impacts the UI (runs in Browser + SSR).
  • Use serverInit.ts for pure server configs.
  • Keep modules autonomous by declaring their own dependencies.