Singularity
Getting Started

Project Structure

How a Singularity project is organized and how the framework discovers your services, tasks, and middleware.

Your Project

Inside a freshly initialized project directory, running singularity new lays down the following layout (existing files are left untouched):

my-project/
├── app.py              # Entry point (4 lines)
├── settings.py         # Your settings (extends SingularitySettings)
├── .env                # Environment variables
├── services/           # Your services (auto-discovered)
│   └── users/
│       └── service.py
├── tasks/
│   └── executable/     # Your background tasks
├── models/             # SQLAlchemy models
├── schemas/            # Pydantic schemas
├── middlewares/         # Custom middleware (auto-discovered)
└── tests/

app.py

from singularity import Singularity
from settings import Settings

app = Singularity(settings=Settings())

The Singularity class handles everything: creates the FastAPI app, discovers your services, registers routes, sets up middleware, initializes the RPC registry, and manages the application lifecycle.

settings.py

from singularity import SingularitySettings

class Settings(SingularitySettings):
    stripe_api_key: str = ""

Extends the framework's base settings. All fields are loaded from environment variables and .env automatically via Pydantic.


How Discovery Works

The framework scans your project directories at startup:

  • services/ — Every directory containing a service.py with a class ending in Service becomes an API endpoint at /api/{directory_name}
  • middlewares/ — Every .py file containing a Middleware class is registered as ASGI middleware
  • tasks/executable/ — Every .py file with a @task decorator is registered as a background task

No manual registration needed. Drop files in the right place and they are discovered.


Framework Package

The singularity package (installed via pip install singularity-fm) contains:

ModulePurpose
singularity.coreManager, Acquire, hooks, discovery, generator, webhook
singularity.rpcRPC registry, proxy, client, service discovery
singularity.microservicesRemote microservice descriptor
singularity.commonLogger, cache, error, WebSocket, Celery
singularity.dbSQLAlchemy engine factories, CRUD mixin
singularity.securityJWT bearer, auth utilities
singularity.middlewareException handler, rate limiter
singularity.tasks@task decorator, TaskRunner, notifications
singularity.scriptsBaseScript, ScriptRunner
singularity.testingServiceTestClient, TestAcquire, mocks
singularity.cliCLI commands (new, generate, dev)

Import Conventions

from singularity.core.acquire import Acquire
from singularity.core.hooks import HookContext
from singularity.core.webhook import BaseWebhook
from singularity.rpc import rpc, get_registry
from singularity.rpc.proxy import RemoteServiceDescriptor
from singularity.rpc.exceptions import RPCServiceNotFound, RPCAccessDenied
from singularity.tasks import task, TaskRunner
from singularity.scripts.base_script import BaseScript
from singularity.config import get_settings
from singularity.common.logger import log
from singularity.common.cache import Cache, CacheInterface
from singularity.common.error import NotFoundError, BaseCustomError

CLI Commands

# pyproject.toml (in the singularity-fm package)
[project.scripts]
singularity = "singularity.cli:cli"
CommandPurpose
singularity new [name]Scaffold framework files into the current directory
singularity devStart dev server with hot reload
singularity generate service <name>Generate service boilerplate
singularity generate task <name>Generate task boilerplate

Next Steps

  • Configuration -- Understand the settings system and environment variables
  • Services -- Build your first service