Your first product

Create a product from a Software Product Line, configure its features, and launch it in the browser.


Table of contents

  1. Prerequisites
  2. Step 1. Browse the SPL catalog
  3. Step 2. Create the product
  4. Step 3. Select the product
  5. Step 4. Configure features
  6. Step 5. Resolve features
  7. Step 6. Derive and launch the product
  8. Step 7. Open the browser
  9. Step 8. Stop the product
  10. What you learned
  11. Next

Prerequisites

You have completed Getting started and are inside the CLI container.

(detached) /workspace$

If not, enter the container now.

cd splent_cli
make cli

Step 1. Browse the SPL catalog

splent spl:list
  SPL models (1)

  sample_splent_spl  not fetched  v4
                     Sample SPLENT app, the product line the tutorials use

An SPL (Software Product Line) is a feature model for a family of applications. It says which features exist, which are mandatory or optional, and how they depend on each other.

sample_splent_spl is the line every tutorial uses. Its model is published on UVLHub, and not fetched means it is not downloaded yet. The next step downloads it.


Step 2. Create the product

splent product:create my_first_app

The command asks which SPL to derive from. Press Enter to accept sample_splent_spl.

  Available SPL models:
    1. sample_splent_spl

  Select SPL [1]:
  No local model for 'sample_splent_spl', fetching it from UVLHub...
  Downloading UVL from https://www.uvlhub.io/doi/10.5281/zenodo.23076870/files/raw/sample_splent_spl.uvl/
  UVL cached at /workspace/.splent_cache/spls/sample_splent_spl@v4/sample_splent_spl.uvl
✅ Product 'my_first_app' created successfully in /workspace/my_first_app

It writes the project at /workspace/my_first_app/.

Path Holds
pyproject.toml Project metadata, feature declarations and the SPL the product derives from, with its DOI on UVLHub
src/my_first_app/ The Flask application factory
scripts/ Numbered startup scripts (install dependencies, migrate, run the server)
docker/ Dockerfiles and Compose files for dev and prod
entrypoints/ Shell entrypoints for the dev and prod containers

product:create only scaffolds. The skeleton has no features, no dependencies, no database and no containers. The next steps add them.

What each step of this tutorial writes STEP 2 product:create the project skeleton, no features yet STEP 4 product:configure the feature selection in pyproject.toml STEP 5 product:resolve cached releases and the features/ links STEP 6 product:derive env files, containers, database and server
Each command adds one layer. Step 3, product:select, only makes the product the active one.

Step 3. Select the product

splent product:select my_first_app

The prompt shows the active product.

(my_first_app) /workspace$

Every splent command now targets it.


Step 4. Configure features

splent product:configure

The configurator walks the SPL’s feature tree. The mandatory features auth, public, theme and settings are selected and locked. Then comes session_type, an alternative group where you pick exactly one session backend, session_redis (Redis, requires redis) or session_filesystem (files). Then it asks about each optional feature (y or N).

Feature What it adds Requires
mail Email sending  
confirmemail Email verification mail, auth
profile User profile management  
reset Password reset mail, auth
admin Admin panel auth
mailhog Local email testing server mail
phpmyadmin Database admin UI  
nginx Reverse proxy  

Pick session_redis (option 1, the default), which selects redis for you. Enable only profile and answer N to the rest. Then answer y to Apply this configuration?, whose default N cancels.

  SPL Configurator — sample_splent_spl
  ───────────────────────────────────────────────────────

  Mandatory (auto-selected):
    ✓ auth
    ✓ public
    ✓ settings
    ✓ theme

    session_type  (pick exactly one)
      1) session_redis  (requires: redis)
      2) session_filesystem
      Select [1-2] [1]: 1
        ↳ redis  (auto-selected)
      → session_redis

    ✓ redis  (auto-selected by dependency)
    Optional features:

    Include mail? [y/N]: N
    Include confirmemail?  (requires: + mail) [y/N]: N
    Include profile? [y/N]: y
    Include reset?  (requires: + mail) [y/N]: N
    Include admin? [y/N]: N
    Include mailhog?  (requires: + mail) [y/N]: N
    Include phpmyadmin? [y/N]: N
    Include nginx? [y/N]: N

  ─── Configuration ───

    ✓ auth  (mandatory)
    ✓ public  (mandatory)
    ✓ redis
    · mail
    · confirmemail
    ✓ profile
    · reset
    · admin
    · mailhog
    · phpmyadmin
    · nginx
    ✓ theme  (mandatory)
    ✓ settings  (mandatory)
    ✓ session_type  (mandatory)
      ✓ session_redis
      · session_filesystem

  Validating configuration... satisfiable

  Apply this configuration? (attach features to product) [y/N]: y

    splent-io/splent_feature_auth@v1.19.4
    splent-io/splent_feature_profile@v1.5.7
    splent-io/splent_feature_public@v1.8.0
    splent-io/splent_feature_redis@v1.5.7
    splent-io/splent_feature_session_redis@v1.1.2
    splent-io/splent_feature_settings@v0.4.3
    splent-io/splent_feature_theme@v0.13.4

  Configuration applied.

  Next: download and link features with:
     splent product:resolve

  .forgejo/workflows/splent-validate.yml is updated once splent product:resolve fetches splent_feature_auth, splent_feature_profile and 5 more.

Picking session_redis selected redis, and answering y to confirmemail would pull in mail (the prompt says requires: + mail). These constraints come from the SPL’s UVL model, and the configuration is checked against all of them before anything is written.

Each feature is pinned to the newest version in your cache (.splent_cache/features/), or to its latest PyPI release when the cache has none. After you confirm, the selection goes into pyproject.toml.

The last line is about the product’s continuous integration, .forgejo/workflows/splent-validate.yml, whose test job runs the servers the features need. It is written again once the features are downloaded, in the next step.


Step 5. Resolve features

splent product:resolve
  product:resolve  my_first_app

  Editable features (0)
    (none)

  Pinned features (7)
⬇️ Cloning splent-io/splent_feature_auth@v1.19.4
✅ Feature 'splent-io/splent_feature_auth@v1.19.4' cloned successfully (ssh://git@git.splent.io:2223/splent-io/splent_feature_auth.git).
🔒 Cached (read-only) at: /workspace/.splent_cache/features/splent_io/splent_feature_auth@v1.19.4
    ✓  auth           v1.19.4  cloned
...
  Synced 7 features.

  Updated .forgejo/workflows/splent-validate.yml for the product's features.

It downloads each pinned feature into .splent_cache/ and creates the product’s features/ directory, with one link per feature (to the workspace root for an editable feature, to .splent_cache/ for a pinned one). The CI workflow now runs Redis next to the tests, as splent_feature_redis declares (see Keeping the workflows in step).

Network step. Pinned features are cloned from git.splent.io the first time, over SSH if your key is registered there and over HTTPS otherwise. The cloned successfully (...) line shows which URL was used, and both are fine. Cached versions resolve at once.


Step 6. Derive and launch the product

splent product:derive --dev

This can take several minutes the first time. It builds the web image, pulls MariaDB, Redis and a Selenium grid, installs every feature, runs migrations and starts the server. Later runs reuse the Docker cache. If the terminal looks stuck, it is still working.

product:derive runs these steps.

  1. Pre-flight. Validates the feature selection against the UVL model, checks feature contracts for conflicts and checks that the product’s ports are free
  2. Resolve. Makes sure every feature is downloaded and linked (Step 5)
  3. Environment. Generates the product’s .env files and merges in the variables each feature declares
  4. Containers. Builds the web image and starts the feature stacks (Redis) and the product containers (web, database, Selenium)
  5. Application. Inside the web container, installs the features, compiles their frontend assets, waits for the database, runs migrations in UVL order, seeds the database the first time, and starts Flask with auto-reload
  6. Port. Prints where the product is listening

At the end it prints the URL.

  Product:  my_first_app
  Env:      dev
  Port:     5591 -> 5000

  URL: http://localhost:5591

  my_first_app (dev) derived successfully.

The port is derived from the product name, so my_first_app is always on 5591.

If a derive is interrupted, for example by a network drop, run it again. It picks up where it left off.


Step 7. Open the browser

Open http://localhost:5591. The home page comes from splent_feature_public, drawn in the site shell of splent_feature_theme. Click Log in (/login, from splent_feature_auth) and sign in with the seeded test user.

  • Email is user1@example.com
  • Password is 1234

Login, the public pages, sessions and profile editing (/profile/edit) all work, each from its own feature.

The seed runs the first time the database is created. splent db:seed --reset -y wipes the data and seeds again.


Step 8. Stop the product

splent product:down --dev

It stops the product’s containers. Your data stays in the database volume. Run splent product:derive --dev to start it again, which is much faster now.


What you learned

Concept Summary
SPL A reusable feature model that defines features and their constraints
Product A concrete application derived from an SPL with a specific feature selection
Configure Interactive selection of features with automatic constraint propagation
Derive End-to-end build (infrastructure, dependencies, database, server)

Next

Continue with Tutorial 2, Exploring your product, to see how your product is composed.


Back to top

splent. Distributed by an LGPL license v3. Contact us: drorganvidez@us.es