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.Method B: Using the CLI (Recommended)
You can use the jopi toolkit to generate a module with a standard skeleton.
npx jopi mod-new my_module_nameRun 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:
| Element | Role |
|---|---|
@routes/ | Defines the URLs and pages exposed by the module. |
@alias/ | Shared items of the module (components/logic shared with others). |
uiInit.tsx | Initialization code for the Browser (and SSR). |
serverInit.ts | Initialization code for the Server only. |
package.json | Module-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.
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.
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.
{
"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:
- JopiJS automatically registers your
mod_*folders in the rootpackage.json. - All dependencies across all modules are installed in a single, optimized step.
- 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.tsxfor logic that impacts the UI (runs in Browser + SSR). - Use
serverInit.tsfor pure server configs. - Keep modules autonomous by declaring their own dependencies.