Exploring your product
Use SPLENT’s inspection tools to understand how features are composed, ordered, and validated.
Table of contents
- Prerequisites
- Feature status
- Feature load order
- Dependency impact
- Composition map (xray)
- Infrastructure check
- Product validation
- SPL queries
- Full diagnostic
- Where things live
- What you learned
- Next
Prerequisites
You completed Tutorial 1. my_first_app is selected and has auth, public, theme, settings, redis, session_redis and profile.
Tutorial 1 stopped the product. Start it again, which is much faster now that the images are built and the features cached.
splent product:select my_first_app
splent product:derive --dev
Feature status
splent feature:status
Every feature and its lifecycle state.
Feature status — my_first_app
──────────────────────────────────────────────────────────────────
Feature Mode Progress State
──────────────────────────────────────────────────────────────────────────────
splent_io/splent_feature_auth@v1.19.4 pinned ●─●─●─● active
splent_io/splent_feature_profile@v1.5.7 pinned ●─●─●─● active
splent_io/splent_feature_public@v1.8.0 pinned ●─●─○─● active
splent_io/splent_feature_redis@v1.5.7 pinned ●─●─○─● active
splent_io/splent_feature_session_redis@v1.1.2 pinned ●─●─○─● active
splent_io/splent_feature_settings@v0.4.3 pinned ●─●─●─● active
splent_io/splent_feature_theme@v0.13.4 pinned ●─●─○─● active
──────────────────────────────────────────────────────────────────────────────
Progress: declared → installed → migrated → active
Modes: pinned = versioned release editable = local development
Last updated: <timestamp>
The lifecycle runs declared (in pyproject.toml) → installed (pip-installed) → migrated (tables created) → active (registered in Flask). All seven features are active because product:derive ran the whole pipeline. public, redis, session_redis and theme show ○ for the migrated step because they have no tables.
Feature load order
splent feature:order --short
Feature load order — my_first_app
──────────────────────────────────────────────
# Feature Requires
──────────────────────────────────────────────
1 splent_feature_auth —
2 splent_feature_profile splent_feature_auth
3 splent_feature_redis —
4 splent_feature_session_redis splent_feature_redis
5 splent_feature_settings —
6 splent_feature_theme splent_feature_settings
7 splent_feature_public splent_feature_theme
UVL: sample_splent_spl.uvl
Features depend on each other’s models, templates and hooks, so the order comes from the constraints of the UVL model. profile => auth loads profile after auth, session_redis => redis loads the session backend after Redis, and public => theme => settings loads the public pages after the site shell they are drawn in. Migrations run in the same order, so a feature’s tables are created after the tables they reference.
Dependency impact
feature:impact answers what happens if you remove a feature.
splent feature:impact auth
feature:impact — auth
Product: my_first_app
UVL: sample_splent_spl.uvl
Depends on
(none) — this feature is independent
Depended on by
← profile (direct)
Removing auth would break 1 feature(s).
It reads the UVL constraints, but only for the features in this product. Depends on is what the feature needs, and Depended on by is what would break without it. Only profile depends on auth here. admin, confirmemail and reset also require auth, but they are not in this product. Each dependency is direct (declared in the UVL) or transitive (through another feature).
Try it with a leaf feature.
splent feature:impact profile
feature:impact — profile
Product: my_first_app
UVL: sample_splent_spl.uvl
Depends on
→ auth (direct)
Depended on by
(none) — safe to remove
Removing profile has no impact on other features.
Nothing depends on profile, so it can be removed safely. Run this before feature:remove, or when you plan a new product.
Composition map (xray)
splent feature:xray
It prints the composition of your product. Product layout lists which hooks of base_template.html are filled and by which features, Features lists the hooks each feature shares with others, and Refinements lists what refinement features override (none yet).
Feature X-Ray — my_first_app
my_first_app (product layout)
template: base_template.html
hook: layout.sidebar.top ← splent_feature_public
hook: layout.anonymous_sidebar ← splent_feature_auth
hook: layout.authenticated_sidebar ← splent_feature_auth, splent_feature_settings, splent_feature_theme
hook: layout.sidebar.authenticated.items ← splent_feature_profile
hook: layout.navbar.anonymous ← splent_feature_auth
hook: layout.navbar.authenticated ← splent_feature_auth, splent_feature_profile
hook: layout.footer ← splent_feature_auth
hook: layout.scripts ← splent_feature_auth, splent_feature_profile
1 unused: layout.head.css
splent_feature_auth
hook: layout.authenticated_sidebar ← splent_feature_settings, splent_feature_theme
hook: layout.navbar.authenticated ← splent_feature_profile
hook: layout.scripts ← splent_feature_profile
splent_feature_profile
hook: layout.navbar.authenticated ← splent_feature_auth
hook: layout.scripts ← splent_feature_auth
splent_feature_settings
hook: layout.authenticated_sidebar ← splent_feature_auth, splent_feature_theme
splent_feature_theme
hook: layout.authenticated_sidebar ← splent_feature_auth, splent_feature_settings
hook: layout.footer ← splent_feature_auth
hook: layout.nav.end ← splent_feature_auth
hook: layout.scripts ← splent_feature_auth, splent_feature_profile
splent_feature_public, splent_feature_redis, splent_feature_session_redis — no active refinements
No refinements declared.
--full also lists every service, model, template and hook each feature declares as overridable. --validate checks the composition.
splent feature:xray --validate
It prints the same tree, then a summary.
── Validation ──
✅ All 8 checks passed. (3 shared hook(s), 1 unused layout hook(s))
The eight checks cover service, model, route, blueprint, command and signal collisions, hook sharing and layout coverage. Shared hooks such as layout.navbar.authenticated, filled by both auth and profile, are fine, since hooks add up.
Infrastructure check
splent check:infra
Infrastructure check
Ports
[OK] No port conflicts (4 ports declared)
[OK] No conflicts with running containers
Services
[OK] No service name collisions (6 services)
[OK] No container name collisions (5 named containers)
Isolation
[OK] 1 feature stack(s) isolate per product
Networks
[OK] Network 'my_first_app_network' exists
Build contexts
[OK] my_first_app/my_first_app_web: Dockerfile found
Health checks
[OK] 2 service(s) with health checks
Volumes
[OK] No volume name conflicts (3 volumes)
All 9 checks passed.
It checks the product’s Docker setup without starting anything. It looks for port conflicts between the product and its features, ports taken by containers of other products, duplicate service and container names, networks, build contexts, health checks and volumes. Run it when you add a feature that brings Docker services of its own.
Product validation
splent product:validate
Validating my_first_app...
1. Configuration (UVL — splent product:validate --only config)
✅ Feature selection is satisfiable (9 features)
2. Compatibility (contracts — splent product:validate --only compat)
✅ No collisions detected
ℹ️ 4 informational note(s)
3. Dependencies (imports — splent product:validate --only deps)
✅ All imports respect UVL constraints (7 checks)
✅ Product is valid.
Each check can run alone with --only.
- Configuration. The selection satisfies every constraint of the SPL (mandatory features present,
profile => auth, exactly one session backend). The count of 9 includes the SPL root and thesession_typegroup - Compatibility. No two contracts claim the same route, model or service
- Dependencies. Every import from one feature into another is backed by a UVL constraint
- Refinement. No two features that modify another one (refiners, the topic of Tutorial 6) collide. Your product has none yet, so it reports
No refiners in this product
SPL queries
These commands work on the SPL’s model, not on your product, so they need detached mode.
splent product:deselect
List all features defined in the SPL.
splent spl:features sample_splent_spl
SPL features
SPL : sample_splent_spl
UVL : /workspace/.splent_cache/spls/sample_splent_spl@v4/sample_splent_spl.uvl
Features : 17
- admin
- auth
- confirmemail
- mail
- mailhog
- nginx
- phpmyadmin
- profile
- public
- redis
- reset
- sample_splent_spl (root)
- session_filesystem
- session_redis
- session_type
- settings
- theme
(root) is the SPL itself and session_type is the group of session backends. Neither is a feature you install.
Check what a feature depends on.
splent spl:deps profile sample_splent_spl
SPL deps
SPL : sample_splent_spl
UVL : /workspace/.splent_cache/spls/sample_splent_spl@v4/sample_splent_spl.uvl
Features : 17
Dependencies of 'profile' (features it requires):
- auth
See who depends on a feature (reverse lookup).
splent spl:deps auth sample_splent_spl --reverse
SPL deps
SPL : sample_splent_spl
UVL : /workspace/.splent_cache/spls/sample_splent_spl@v4/sample_splent_spl.uvl
Features : 17
Reverse dependencies of 'auth' (features that require it):
- admin
- confirmemail
- profile
- reset
spl:info sample_splent_spl tells you where the model is read from, its DOI and version on UVLHub, and which products pin it.
Select the product again.
splent product:select my_first_app
Full diagnostic
splent doctor --fast
It runs every health check in four groups and ends with a summary.
- Environment.
check:env(versions,.env, credentials),check:pyproject,check:docker,check:infra - Product.
check:product(environment variables, links, configuration overrides, blueprints),check:features,feature:status - Services.
product:containersanddb:status - Credentials.
check:forgeandcheck:pypi
--fast skips the database and credential checks, which need the network. The two credential warnings of check:env (forge and PyPI tokens not set) are expected until you publish a feature for real, which Tutorial 5 makes optional. Run doctor whenever something feels off.
Where things live
| File | Purpose |
|---|---|
my_first_app/pyproject.toml |
Feature declarations, SPL reference and its DOI, layout hooks |
.splent_cache/spls/ |
UVL models downloaded on demand from UVLHub by DOI |
splent_spl_sample_splent/ |
Your working copy of sample_splent_spl, which wins over the cache. The directory drops the _spl suffix of the model name. spl:add-feature creates it the first time you edit the model, in Tutorial 3, Step 7 |
my_first_app/splent.manifest.json |
Lifecycle state of every feature |
.splent_cache/features/ |
Read-only clones of pinned feature versions |
my_first_app/features/splent_io/ |
Symlinks to cached or editable features |
my_first_app/docker/ |
Docker Compose files, Dockerfiles, .env files |
What you learned
| Tool | Purpose |
|---|---|
feature:status |
Lifecycle state of every feature |
feature:order |
UVL-resolved load order |
feature:impact |
Dependency impact analysis (what breaks if removed) |
feature:xray |
Full composition map |
feature:xray --validate |
Validate extensibility (collisions, hooks, refinements) |
check:infra |
Docker port/container/network validation |
product:validate |
Check configuration, contracts and imports against the SPL |
spl:features / spl:deps / spl:info |
Query the SPL model |
doctor |
Comprehensive health check |
Next
Continue with Tutorial 3, Create a feature, to build a note-taking feature from scratch.