SPLENT

From feature model to production.

SPLENT is a Software Product Line toolkit for Python. Pick features from a validated variability model, derive a running product with one command, and release it to a server that deploys itself. The products of a line share the same released features, so a fix to one feature reaches every product that uses it.

~/splent_workspace
Built on Flask UVL feature models Docker-first LGPL v3 · open source DiversoLab · Universidad de Sevilla

48

features published in the marketplace

4

product lines on UVLHub, each with its DOI

5

products derived from them, one of them this site's marketplace

18

features the DiversoLab and InnoSoft sites share, released once

Capabilities

A product line, end to end.

Variability, composition, contracts, migrations and deployment usually live in tribal knowledge. SPLENT turns them into one pipeline you can read, check and repeat.

Variability you can check

Features and their constraints live in a UVL model. Every configuration is checked for satisfiability, and every combination for route, contract and refiner collisions, before anything is built.

Features are packages

Each feature is a versioned Python package with its routes, models, migrations, templates, assets and tests, and its own services such as Redis or Nginx when it needs them.

Extend without forking

A feature declares what others may extend. A refiner adds a column, a form field or a block of a page to another feature, and taking it out leaves that feature as it was.

One command to a running product

product:derive resolves the pinned features, merges their Docker Compose files and settings, applies migrations in the order the model gives and starts the product.

Releases that deploy themselves

product:release publishes the image to a stable channel. With the autodeploy feature the server follows it, backs up the database and rolls back a release that does not start.

A line that stays current

CI checks every push and pull request as a configuration of the line. A weekly job opens a pull request with the feature upgrades, checked like any other change, and merging it stays your call.

How it works

Model the line.
Configure, derive, release.

A product line is a UVL model published on UVLHub. A product is one configuration of it, and SPLENT takes that configuration all the way to a running server.

marketplace_spl.uvl
The line marketplace.splent.io is derived from
features
    marketplace_spl
        mandatory
            theme
            settings
            auth
            marketplace
            session
                alternative
                    session_filesystem
                    session_redis
        optional
            configurator
            admin
            signup
            apikeys
            spl_registry
            autodeploy
            ...
constraints
    spl_registry => apikeys
    session_redis => redis
    autodeploy => admin
terminal
From the tutorials
# 1. Choose a product line
splent spl:list

# 2. Create a product and configure it
splent product:create my_first_app
splent product:select my_first_app
splent product:configure
  Validating configuration... satisfiable

# 3. Derive it
splent product:derive --dev
  URL: http://localhost:5591

# 4. Release it
splent product:release 1.0.0
  my_first_app v1.0.0 released.
01

Choose

Pick a product line. Its model comes from UVLHub by DOI, so any clone resolves the same one.

02

Configure

Decide what the model leaves open. The configuration is checked before it is applied.

03

Derive

One command resolves the features, composes their services, migrates and starts the product.

04

Release

Publish the tag and the image. A server that follows the stable channel picks the release up.

Delivery

A release is a deployment.

Every product carries the bundle a server needs. The server has Git and Docker and nothing else, no workspace and no SPLENT. With the autodeploy feature it keeps itself up to date.

  • A self-contained bundle

    deploy/ holds the Compose file, an example environment and a README. The server clones the repository, copies the example and starts it.

  • An image you can rebuild

    Built from the release commit. The framework, the CLI and every feature are pinned in pyproject.toml, and every third-party package in a lock file.

  • Unprivileged at runtime

    The app runs as a user of its own. The container starts as root only to hand its volumes over.

  • Deploys and rolls back on its own

    With the autodeploy feature the server follows the stable channel. It backs up the database first and goes back when a release does not start.

  • How continuous delivery works in SPLENT
server and laptop
# On the server, once
git clone https://git.splent.io/my-org/my_first_app.git
cd my_first_app/deploy
cp .env.example .env   # fill in the required values
docker compose up -d

# On your laptop, for every release
splent product:release 1.1.0
  docker   git.splent.io/my-org/my_first_app:stable
  my_first_app v1.1.0 released.

# With autodeploy, the server sees the new
# :stable, backs up the database and swaps
# the container.
Built with SPLENT

Real lines, real products.

These product lines are published on UVLHub, and these products are derived from them. Products of one line run the same released features, so they improve together.

marketplace_spl

SPLENT Marketplace

12 features. Runs at marketplace.splent.io and deploys itself through the autodeploy feature its configuration includes.

In production autodeploy
cms_spl

DiversoLab and InnoSoft websites

Two sites from one line, with 26 and 23 features. 18 of them are the same features, released once.

2 products 18 shared features
openwiki_spl

EGC and ISIA course wikis

Wikis for two courses at the Universidad de Sevilla, with 11 and 10 features, 9 of them shared.

2 products 9 shared features

The tutorials use a fourth line, sample_splent_spl, to derive a first product in minutes.

Four pieces, one system

An ecosystem designed to compose.

The framework, the CLI, the product lines and the marketplace work as one toolkit. Each stands on its own, and together they take a variability model to production.

Runtime

SPLENT Framework

Feature discovery, composition, configuration layering and template resolution, inside Flask.

  • Blueprints, services, repositories, seeders
  • Signals, i18n, template hooks
  • Refinement between features
Operator

SPLENT CLI

Create, configure, derive, test, release and deploy. The surface you and your CI drive the line from.

  • Pinned, read-only feature cache
  • Releases to PyPI, the forge and image registries
  • A Claude Code plugin that drives it
Models

Product lines

UVL feature models published on UVLHub, each version with its DOI, so a clone of any product resolves the line it was derived from.

  • Versioned like features
  • Published with spl:publish
  • Checked for satisfiability before every derivation
Registry
marketplace.splent.io

SPLENT Marketplace

Where features and product lines are published and found. Browse the catalog, configure a product from its variability model, and publish your own.

  • Feature catalog with contracts
  • UVL configurator for every product line
  • A SPLENT product itself, deploying itself
Why SPLENT

Variability shouldn't be a maintenance tax.

Most teams reach for duplication, feature flags or microservices. SPLENT offers a fourth option, a variability model that drives the infrastructure.

The old trade-offs

  • Code duplication
    Forks per client turn into a maintenance nightmare. Every bug fix has to be re-applied across branches.
  • Feature-flag sprawl
    Conditionals grow everywhere. The real product behavior disappears into runtime toggles nobody fully tracks.
  • Microservice explosion
    Splitting every variation into its own service trades one problem for a distributed systems tax.

The SPLENT way

  • A formal model, not a folder of branches
    UVL defines features and constraints explicitly. The model is checked for satisfiability before a single container starts.
  • Composition is mechanical, not tribal
    Docker Compose files, environments and migrations are merged by the toolkit, the same way every time, so you can audit and reproduce them.
  • One pipeline, every environment
    product:derive validates, composes and launches, and product:release ships what was derived. Dev and prod share the same path, and problems surface before Docker.

Ship variability without the tax.

Follow the first tutorial to derive a product in minutes, then release it to a server that keeps itself up to date.