Modules & Apps

Chapter 2: How sparQ organizes code into modules.

In the previous chapter, you learned that sparQ is built on modules. Now let's understand exactly what modules are, where they live, and how they work together.

What is a Module?

A sparQ module is NOT a Python module. When we say "module" in sparQ, we mean a self-contained feature unit—a folder with a specific structure. This is different from Python's concept of a module (any .py file).

A module is a self-contained piece of functionality with its own models, controllers, views, and translations. Your Hello sparQ app from the tutorial? That's a module.

Every module follows the same structure:

myapp/ ├── __init__.py # Module exports ├── __manifest__.py # App metadata (includes mappid) ├── module.py # Lifecycle hooks ├── controllers/ │ └── main.py # Flask routes ├── models/ │ └── item.py # Database models ├── views/ │ ├── templates/ │ │ └── myapp/ │ │ ├── desktop/ │ │ │ └── index.html # Desktop templates │ │ └── mobile/ │ │ └── index.html # Mobile templates │ └── assets/ │ └── css/ │ └── myapp.css # Styles ├── tools/ # Optional: AI tools │ └── widgets.py # Tool definitions └── lang/ └── en.json # Translations

This consistent structure means once you understand one module, you understand them all.

Module Types

sparQ has two types of modules, determined by where they live:

Image: Diagram showing Base Modules vs Apps with their locations
Type Location Purpose
Base Modules modules/base/ Core sparQ functionality (Sales, Billing, Team, etc.)
Apps data/modules/apps/ Your custom applications and marketplace installs

The folder determines the type. Put your code in data/modules/apps/ and sparQ automatically treats it as an app.

Base Modules vs Apps

The key difference is how they appear in the UI:

Base Modules

Apps

Image: Screenshot showing the Launch Pad with installed apps

Users can pin frequently-used apps to the main navigation, making them as accessible as base modules.

Where Your Apps Live

When you run the SDK scaffolding command:

cd sdk
make app name=myapp

It creates your app in:

data/modules/apps/myapp/

This location is important because:

The Directory Structure Explained

Let's look at each part of a module:

__manifest__.py

The identity card of your app. Contains name, version, mappid, and configuration:

# __manifest__.py
manifest = {
    # Required fields
    "name": "MyApp",             # Display name (PascalCase)
    "version": "1.0",            # Semantic version
    "mappid": "x7k2m9",          # Marketplace app ID (auto-generated)
    "main_route": "/myapp",      # URL slug (used in /m/{mappid}/{main_route})
    "type": "App",               # "App" (visible) or "System" (hidden)
    "depends": ["core"],         # Module dependencies
    # Display fields
    "icon_class": "fa-solid fa-cube",  # FontAwesome icon class
    "color": "#7c3aed",                # Theme color (purple)
    "description": "What my app does",
    "long_description": "Detailed description of the app's features.",
}

module.py

Contains lifecycle hooks that run when sparQ starts:

# module.py
def init_app(app):
    """Called when Flask app initializes."""
    pass

def init_database(db):
    """Called after database tables are created."""
    # Good place to seed initial data
    pass

controllers/

Flask blueprints that handle HTTP requests. Each file typically handles one area:

# controllers/main.py
from flask import Blueprint, render_template

bp = Blueprint('main', __name__, url_prefix='/myapp')

@bp.route('/')
def index():
    return render_template('myapp/desktop/index.html')

models/

SQLAlchemy models for your database tables:

# models/item.py
from system.db import db

class Item(db.Model):
    __tablename__ = 'myapp_items'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100))

views/

Contains templates and static assets. Templates go in a namespaced subfolder with desktop/ and mobile/ variants:

<!-- views/templates/myapp/desktop/index.html -->
{% extends "core/desktop/base.html" %}
{% block content %}
    <h1>Welcome to My App</h1>
{% endblock %}

CSS files go in views/assets/css/:

/* views/assets/css/myapp.css */
.myapp-app .content-card {
    /* Your custom styles */
}

lang/

JSON files with translations for each language:

// lang/en.json
{
    "welcome": "Welcome to My App",
    "save": "Save",
    "cancel": "Cancel"
}

App Navigation

Apps can define their own sidebar navigation using nav_sections in the manifest:

# __manifest__.py
{
    'name': 'Helpdesk',
    'nav_sections': [
        {
            'title': 'Tickets',
            'icon': 'ticket',
            'items': [
                {'route': 'helpdesk.tickets.list', 'label': 'All Tickets'},
                {'route': 'helpdesk.tickets.unassigned', 'label': 'Unassigned'}
            ]
        }
    ]
}

This creates a custom left sidebar when users are in your app.

Image: Example of an app with custom sidebar navigation

Module Loading Order

When sparQ starts, modules load in this order:

  1. Core - The foundation (authentication, base templates)
  2. Dashboard - Business dashboard (Home)
  3. Team - Employee management
  4. All other base modules - Alphabetically
  5. Apps - From data/modules/apps/, alphabetically

This order matters if your app depends on another module being loaded first.

Key Takeaways