Skip to content

Project Structure

The default structure of an Orionis application is designed to provide a solid starting point for both minimalist and enterprise-grade projects. You are free to organize your application however you prefer — Orionis imposes no restrictions on where classes are located, as long as the application is properly configured during the bootstrapping process.

The root directory of your project contains the directories and files that make up the base application structure. Below is the layout you will find in a fresh Orionis installation:

  • Directoryapp/ Main application code
    • Directoryconsole/ Commands and task scheduling
      • Directorycommands/ Custom commands
      • Directorylisteners/ Console event listeners
      • scheduler.py Scheduler configuration
    • Directorycontracts/ Interfaces and application contracts
    • Directoryexceptions/ Custom exception handler
      • handler.py
    • Directoryfacades/ Application facades
    • Directoryhttp/ HTTP layer
      • Directorycontrollers/ Request controllers
    • Directorymodels/ ORM models
    • Directorynotifications/ Notification system
    • Directoryjobs/ Queued jobs
    • Directoryproviders/ Service providers
      • app_service_provider.py
    • Directoryservices/ Business logic
  • Directorybootstrap/ Application startup
    • app.py
  • Directoryconfig/ Configuration files
    • app.py
    • auth.py
    • cache.py
    • cors.py
    • database.py
    • filesystems.py
    • logging.py
    • mail.py
    • queue.py
    • session.py
    • testing.py
  • Directorydatabase/ Migrations and seeders
  • Directoryresources/ Views, translations, and assets
  • Directoryroutes/ Route definitions
    • api.py
    • web.py
    • console.py
  • Directorystorage/ Generated storage
    • Directoryapp/
      • Directorypublic/ Publicly accessible files
      • Directoryprivate/ Private files
    • Directoryframework/
      • Directorybootstrap/ Compiled configuration cache
      • Directorycache/
        • Directorydata/ File-based cache
    • Directorylogs/ Application logs
  • Directorytests/ Automated test suite
  • Directory.venv/ Python virtual environment
  • .env Environment variables (not versioned)
  • .env.example Environment variables template
  • .gitignore Files ignored by Git
  • pyproject.toml Project metadata and dependencies
  • reactor Framework CLI
  • README.md Project documentation

The app directory contains the core code of your application. Nearly every class you write will reside here, organized into subdirectories that clearly separate responsibilities.

Contains custom command-line commands, console event listeners, and the task scheduler configuration. These components are executed through the reactor CLI.

console/
├── commands/ # Custom commands
├── listeners/ # Console event listeners
└── scheduler.py # Task scheduler configuration

Contains the interfaces and contracts that define agreements between your application’s components. This enables dependency inversion and simplifies testing with mocks.

Houses your application’s exception handler (handler.py). Here you can customize how uncaught exceptions are reported and rendered throughout the entire application.

Contains your application’s facades, which provide a convenient static interface for accessing services registered in the container.

Contains your application’s HTTP layer: controllers that handle incoming requests, middleware that filters requests, and request validation classes.

  • Controllers: Receive HTTP requests, delegate logic to services, and return responses.
  • Middleware: Filters that execute before or after requests (authentication, CORS, rate limiting).
  • Requests: Validation classes that encapsulate input rules.

Contains ORM model classes. Each model represents a table in your database and provides an expressive interface for interacting with data.

Contains transactional notification classes that your application sends through various channels (email, SMS, push notifications).

Contains your application’s queued jobs. Jobs can be executed asynchronously or synchronously within the request lifecycle.

Contains your application’s service providers. Providers bootstrap the application by binding services in the dependency injection container and executing initialization tasks.

A service provider implements two fundamental methods:

from orionis.container.providers.service_provider import ServiceProvider
class AppServiceProvider(ServiceProvider):
def register(self) -> None:
# Register services in the container
...
async def boot(self) -> None:
# Execute initialization tasks after registration
...

Contains classes that encapsulate complex business logic. This directory helps keep controllers thin and code reusable across different entry points (HTTP, CLI).

The bootstrap directory contains the app.py file, responsible for creating and initializing the application instance. This file configures routes, the task scheduler, the exception handler, service providers, and executes the framework startup.

from pathlib import Path
from app.console.scheduler import Scheduler
from app.exceptions.handler import ExceptionHandler
from app.providers.app_service_provider import AppServiceProvider
from orionis.foundation.application import Application
app = Application(
base_path=Path(__file__).parent.parent,
compiled=True,
compiled_path="storage/framework/bootstrap",
compiled_invalidation_paths=[
"app", "bootstrap", "config",
"resources", "routes", ".env"
],
)
app.withRouting(
console="routes/console.py",
web="routes/web.py",
api="routes/api.py",
health="/up",
)
app.withScheduler(Scheduler)
app.withExceptionHandler(ExceptionHandler)
app.withProviders(
AppServiceProvider,
)
app.create()

The compiled=True parameter enables configuration caching in storage/framework/bootstrap. The paths listed in compiled_invalidation_paths are monitored to automatically invalidate the cache when changes are detected. This improves performance in production without sacrificing the development experience.

The config directory contains all of your application’s configuration files. Each file is a frozen dataclass (frozen=True) that defines its default values and supports loading environment variables via Env.get().

FileDescription
app.pyName, environment, debug, host, port, workers, timezone, locale, encryption
auth.pyAuthentication system configuration
cache.pyCache drivers (default: file-based)
cors.pyAllowed origins, methods, headers, credentials, max age
database.pyDatabase connections (SQLite, PostgreSQL, MySQL, Oracle)
filesystems.pyStorage disks: local, public, and AWS S3
logging.pyLogging channels: stack, hourly, daily, weekly, monthly, chunked
mail.pyMail transports: SMTP and file
queue.pyBroker and job queue configuration
session.pySession cookie, duration, SameSite, HTTPS
testing.pyVerbosity, fail fast, test directory, file patterns

The database directory is intended to contain database migrations, seeders, and model factories for your application.

The resources directory stores views, email templates, localization files (translations), and uncompiled assets such as CSS, JavaScript, and images.

The routes directory contains your application’s route definitions. By default, Orionis includes three route files: web.py, api.py, and console.py.

Defines routes for your web application’s HTTP requests. Supports a fluent API with prefixes, route grouping, and typed parameters:

from app.http.controllers.home_controller import HomeController
from orionis.support.facades.router import Route
Route.prefix("/home").group(
Route.get("/{slug:str}/{id:int}", [HomeController, 'index'])
)

Contains routes for your REST API. These routes are designed to be stateless and generally return JSON responses:

from app.http.controllers.home_controller import HomeController
from orionis.support.facades.router import Route
Route.get("/api-route", [HomeController, "index"])

Registers console commands that are executed through the reactor CLI. Uses the Reactor facade with a fluent API to define commands with descriptions, arguments, and options:

from app.services.welcome_service import WelcomeService
from orionis.console.args.argument import Argument
from orionis.support.facades.reactor import Reactor
Reactor.command("app:test", [WelcomeService, "greetUser"])\
.timestamp()\
.description("Command Test Defined as Route")\
.arguments([
Argument(
name_or_flags=["--name", "-n"],
type_=str,
required=False
)
])

The storage directory contains files generated by your application and the framework. It is organized into subdirectories with specific purposes:

Stores files generated by your application, divided into two categories:

  • public/: Publicly accessible files through the web server (uploaded images, downloadable documents, generated assets). Served by default from the /static URL.
  • private/: Files that should not be publicly accessible (confidential documents, temporary processing files, backups).

Contains files automatically generated by the framework:

  • bootstrap/: Compiled configuration cache. Generated when compiled=True is set on the Application instance, speeding up application startup.
  • cache/data/: File-based cache system storage (FILE driver).

Contains your application’s log files. Depending on the logging configuration, you may have logs organized by different rotation strategies: stack, hourly, daily, weekly, monthly, or chunked.

The tests directory contains your automated test suite. Orionis includes its own testing microframework with configuration built into config/testing.py.

To run the tests, use the reactor CLI:

Terminal window
python -B reactor test

The testing configuration allows you to adjust output verbosity, enable fail-fast mode, specify the test directory, and define file and method patterns.

The .venv directory contains the Python virtual environment for your application. It provides dependency isolation, ensuring each project has its own package versions without conflicts with the global system.

.env — Contains environment variables specific to your local installation (database credentials, API keys, environment settings). This file must not be versioned.

.env.example — Example template of the .env file that should be versioned. It shows which environment variables the application requires without exposing actual values.

pyproject.toml — Defines project metadata, Python dependencies, and development tool configuration. Orionis uses pyproject.toml as the standard for dependency management.

reactor — Framework CLI entry point. Executes commands through the application’s CLI kernel in an asynchronous environment:

import sys
from bootstrap.app import app
from orionis.services.asynchrony.engine_cli import ReactorLoop
if __name__ == "__main__":
sys.exit(
ReactorLoop.run(
app.handleCommand(sys.argv)
)
)

.gitignore — Specifies files and directories that Git should ignore (.venv/, .env, __pycache__/, storage/logs/).

README.md — Main project documentation with installation and usage instructions.

The app directory follows an architecture based on separation of responsibilities:

LayerDirectoryResponsibility
HTTP Entryhttp/Controllers, middleware, request validation
CLI Entryconsole/Console commands, task scheduler
Business Logicservices/Domain operations and business rules
Persistencemodels/ORM models and data access
Infrastructureproviders/Service registration and configuration
Contractscontracts/Interfaces and abstractions
Facadesfacades/Static access to container services

Orionis implements the following design patterns:

  • MVC (Model-View-Controller): Organization of presentation and domain logic.
  • Service Layer: Encapsulation of complex business logic outside of controllers.
  • Provider Pattern: Service registration and configuration in the dependency injection container.
  • Facade Pattern: Simplified access to container services through static interfaces.