Architecture
Chapter 1: Understanding how sparQ works under the hood.
Now that you've built your first app, let's step back and understand how sparQ is structured. This knowledge will help you make better decisions as you build more complex applications.
Design Philosophy
sparQ is built on a foundation that prioritizes modularity and extensibility. The goal is a system that can grow and scale over time while remaining simple, intuitive, and efficient.
Everything in sparQ—including the core system itself—is a module. This means:
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).
- Consistency - Once you understand one module, you understand them all
- Isolation - Modules don't interfere with each other
- Extensibility - Add functionality without touching core code
- Simplicity - Each module does one thing well
Architectural Principles
Seven key pillars guide sparQ's architecture:
| Principle | What It Means |
|---|---|
| Modular Structure | Every component functions as an independent module with its own models, views, and controllers |
| Dynamic Loading | Only essential modules are required; additional features load on demand |
| Lightweight Database | SQLite as the primary data store for simplicity and portability |
| ORM Layer | SQLAlchemy handles all database interactions with clean Python code |
| Server-Side Rendering | Jinja2 templates with HTMX for dynamic updates without JavaScript complexity |
| Containerized Deployment | Docker-based deployment for consistent environments |
| Internationalization | JSON-based translation system enables global functionality |
The Big Picture
sparQ is a modular business platform built on Flask. Think of it as a foundation that handles all the common stuff—authentication, database, email, payments—so you can focus on building your specific business logic.
Here's what makes up a sparQ installation:
+-------------------------------------------------------------+
| Flask Application |
| (app.py) |
+-------------------------------------------------------------+
| |
| +-----------+ +-----------+ +---------------------+ |
| | Module | | Database | | i18n | |
| | Loader | |(SQLAlchemy)| | (JSON files) | |
| | (pluggy) | | SQLite | | | |
| +-----+-----+ +-----------+ +---------------------+ |
| | |
| v |
| +-----------------------------------------------------+ |
| | Modules | |
| | +-------+ +-------+ +-------+ +-------+ | |
| | | Core | | Team | |Dashbrd| | Apps | | |
| | +-------+ +-------+ +-------+ +-------+ | |
| +-----------------------------------------------------+ |
| |
+-------------------------------------------------------------+
Required Modules
Three modules are essential for sparQ to run:
| Module | Purpose |
|---|---|
| Core | Authentication, user administration, base templates, and foundational services |
| Dashboard (Home) | Business dashboard, pipeline view, and central landing page after login |
| Team | Employee management with roles, departments, and organizational structure |
Everything else—Sales, Billing, Service, and your custom apps—is optional and loads only when needed.
Technology Stack
sparQ uses a carefully chosen set of technologies:
| Layer | Technology | Why |
|---|---|---|
| Web Framework | Flask | Lightweight, flexible, extensive ecosystem |
| Database | SQLite | Zero configuration, portable, surprisingly powerful |
| ORM | SQLAlchemy | Python's most mature database toolkit |
| Templates | Jinja2 | Fast, secure, Flask's native templating |
| Interactivity | HTMX + Alpine.js | Dynamic UIs without JavaScript complexity |
| Styling | Bootstrap 5 | Responsive, well-documented, customizable |
| Plugin System | Pluggy | Python's standard for extensibility (used by pytest) |
| AI Integration | OpenAI / Anthropic | LLM-powered assistant with tool calling |
System Services
sparQ provides a set of system services that any module can use. These live in the system/ directory:
| Service | What It Does | Example Use |
|---|---|---|
| db | Database connection and ORM | from system.db import db |
| auth | Authentication decorators | @login_required |
| Send emails | EmailService.send() |
|
| Generate PDF documents | PDFService.generate() |
|
| i18n | Translations | _('Hello') |
| payments | Stripe integration | PaymentService.charge() |
| background | Background task processing | BackgroundTask.run() |
| marketplace | Install/manage apps | MarketplaceService.install() |
| ai | AI tools and LLM integration | from system.ai import Tool |
You'll use these services throughout your apps. For example, to require login on a route:
from system.auth import login_required
@bp.route('/dashboard')
@login_required
def dashboard():
return render_template('my_app/dashboard.html')
Request Lifecycle
When a user clicks something in your app, here's what happens:
1. Request arrives at Flask
↓
2. URL routing matches a controller
↓
3. Auth middleware checks permissions
↓
4. Your controller runs
↓
5. Controller calls models/services
↓
6. Template renders HTML
↓
7. Response sent to browser
Let's trace a real example. When a user visits /hello/ from your Hello sparQ app:
- Flask sees the URL matches
@bp.route('/')in yourmain.pycontroller - Your
index()function runs - It calls
render_template('hello/desktop/index.html') - Jinja2 processes the template
- HTML is sent back to the browser
The Frontend Stack
sparQ uses a server-rendered approach rather than a Single Page Application (SPA). This means:
- Jinja2 - Templates render HTML on the server
- HTMX - Makes pages feel dynamic without writing JavaScript
- Alpine.js - Handles small UI interactions (dropdowns, modals)
- Bootstrap 5 - Provides the CSS framework
This stack is simpler than React/Vue and perfect for business applications where SEO matters and you don't need complex client-side state.
Database Layer
sparQ uses SQLite as its primary database and SQLAlchemy as its ORM (Object-Relational Mapper). This lets you work with Python objects instead of writing raw SQL:
# Instead of: SELECT * FROM tasks WHERE user_id = 1
tasks = Task.query.filter_by(user_id=1).all()
# Instead of: INSERT INTO tasks (title, user_id) VALUES ('Buy milk', 1)
task = Task(title='Buy milk', user_id=1)
db.session.add(task)
db.session.commit()
SQLite might seem simple, but it's incredibly capable. It handles millions of records, supports concurrent reads, and requires zero configuration. For most business applications, it's more than enough.
The SDK
The sdk/ folder contains developer tooling for building apps:
# Create a new app with auto-generated mappid
cd sdk
make app name=myapp
# Package for marketplace
make release name=myapp
The SDK handles scaffolding, generates unique marketplace IDs (mappid), and packages apps for distribution.
The Module System
Everything in sparQ is a module. There are three types:
| Type | Location | Purpose |
|---|---|---|
| Base Modules | modules/base/ |
Core functionality shipped with sparQ |
| Apps | data/modules/apps/ |
Your custom applications |
| Plugins | data/addons/ |
Extensions that enhance other modules |
When sparQ starts, it automatically discovers and loads modules in this order:
- Core - Authentication, base templates
- Dashboard - Business dashboard (Home)
- Team - Employee management
- Other base modules - Alphabetically
- Your apps - Alphabetically
Modules can define dependencies on other modules, ensuring they load in the correct order.
We'll dive deeper into modules in the next chapter.
Key Takeaways
- sparQ prioritizes modularity—everything is a self-contained module
- Core, Dashboard, and Team modules are required; everything else is optional
- Flask + SQLite + SQLAlchemy provide the foundation
- Server-rendered HTML with HTMX gives you dynamic UIs without JavaScript complexity
- System services (auth, db, email, etc.) are available to all modules
- Modules are automatically discovered and loaded at startup