Your first product
Create a product from a Software Product Line, configure its features, and launch it in the browser.
Table of contents
- Prerequisites
- Step 1. Browse the SPL catalog
- Step 2. Create the product
- Step 3. Select the product
- Step 4. Configure features
- Step 5. Resolve features
- Step 6. Derive and launch the product
- Step 7. Open the browser
- Step 8. Stop the product
- What you learned
- 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:createonly scaffolds. The skeleton has no features, no dependencies, no database and no containers. The next steps add them.
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 |
|---|---|---|
| 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 | |
| phpmyadmin | Database admin UI | |
| nginx | Reverse proxy |
Pick session_redis (option 1, the default), which selects redis for you. Enable only profile and answer
Nto the rest. Then answeryto Apply this configuration?, whose defaultNcancels.
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.
- Pre-flight. Validates the feature selection against the UVL model, checks feature contracts for conflicts and checks that the product’s ports are free
- Resolve. Makes sure every feature is downloaded and linked (Step 5)
- Environment. Generates the product’s
.envfiles and merges in the variables each feature declares - Containers. Builds the web image and starts the feature stacks (Redis) and the product containers (web, database, Selenium)
- 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
- 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 -ywipes 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.