Exploring your product

Use SPLENT’s inspection tools to understand how features are composed, ordered, and validated.


Table of contents

  1. Prerequisites
  2. Feature status
  3. Feature load order
  4. Dependency impact
  5. Composition map (xray)
  6. Infrastructure check
  7. SPL validation
  8. SPL queries
  9. Full diagnostic
  10. Where things live
  11. What you learned
  12. Next

Prerequisites

You completed Tutorial 1 and have my_first_app running with auth, public, redis, session_redis, and profile.


Feature status

splent feature:status

This shows every feature and its current lifecycle state:

  Feature                                          Mode      Progress   State
  ──────────────────────────────────────────────────────────────────────────────
  splent_io/splent_feature_auth@v1.5.5             pinned    ●─●─●─●   active
  splent_io/splent_feature_profile@v1.5.4          pinned    ●─●─●─●   active
  splent_io/splent_feature_public@v1.5.3           pinned    ●─●─○─●   active
  splent_io/splent_feature_redis@v1.5.4            pinned    ●─●─○─●   active
  splent_io/splent_feature_session_redis@v1.0.5    pinned    ●─●─○─●   active

States progress through the lifecycle: declared (in pyproject.toml) → installed (pip-installed) → migrated (database tables created) → active (registered in Flask). All five features are active because product:derive ran the full pipeline.

Notice that public, redis, and session_redis show for the migrated step — they have no database tables, so that step is skipped. The progress bar reflects this accurately.


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_public              —

  UVL: sample_splent_spl.uvl

Load order matters because features depend on each other’s models and hooks. The order comes from UVL constraints: profile => auth means profile always loads after auth, and session_redis => redis means the session backend loads after Redis is available. This guarantees that dependencies are satisfied before the features that need them.


Dependency impact

Once you know the load order, the natural next question is: what happens if I add or 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
    ← confirmemail  (direct)
    ← notes  (direct)
      ← notes_tags  (transitive)
    ← profile  (direct)
    ← reset  (direct)

  Removing auth would break 5 feature(s).

The command reads the UVL constraints and builds a bidirectional dependency graph. Depends on shows what the feature needs to work; Depended on by shows what would break if you removed it. Dependencies are labelled as direct (declared in the UVL) or transitive (propagated through the graph).

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.

Profile depends on auth but nothing depends on profile — it can be safely removed. This is useful before running feature:remove or when planning which features to include in a new product.


Composition map (xray)

splent feature:xray

This prints the full composition of your product:

  • Product layout — which hooks are active in base_template.html and which features fill them
  • Extension points — what each feature declares as overridable (services, templates, models, hooks)
  • Refinements — what’s been overridden by refinement features (none yet)

To validate the composition is clean:

splent feature:xray --validate
  ✅ Services: no collisions (2 unique)
  ✅ Models: no collisions (2 unique)
  ✅ Routes: no collisions (5 unique)
  ✅ Blueprints: no collisions (5 unique)
  ✅ Commands: no collisions (0 unique)
  ✅ Signals: no collisions (1 unique)
  ℹ️  Hook 'layout.navbar.authenticated' — 2 contributors: splent_feature_auth, splent_feature_profile
  ℹ️  Hook 'layout.scripts' — 3 contributors: splent_feature_auth, splent_feature_profile, splent_feature_public
  ✅ Hooks: 2 shared slot(s) — additive, OK
  ℹ️  Layout: 3 unused hook(s): layout.head.css, layout.sidebar.top, layout.footer
  ✅ Layout: 6/9 hooks active

  ✅ All 8 checks passed.

If everything is green, your product is correctly composed. Shared hooks (like layout.navbar.authenticated used by both auth and profile) are OK — they’re additive by design.


Infrastructure check

splent check:infra

This validates Docker infrastructure without starting any containers: port conflicts between features, duplicate container names, and missing external networks. Useful when adding new features with Docker services.


SPL validation

splent product:validate

Checks your product’s feature selection against the SPL constraints:

  • All mandatory features present
  • All dependency constraints satisfied (profile => auth)
  • No conflicting features selected

SPL queries

These commands operate on the SPL itself (the feature model), not your product. They require detached mode:

splent product:deselect

List all features defined in the SPL:

splent spl:features sample_splent_spl
  - auth
  - confirmemail
  - mail
  - mailhog
  - notes
  - profile
  - public
  - redis
  - reset
  - sample_splent_app  (root)
  - session_filesystem
  - session_redis
  - session_type

The (root) entry is the SPL itself — it’s the top-level feature in the UVL hierarchy, not a real feature you install.

Check why a feature has dependencies:

splent spl:deps profile sample_splent_spl
  Dependencies of 'profile' (features it requires):
  - auth

See who depends on a feature (reverse lookup):

splent spl:deps auth sample_splent_spl --reverse
  Reverse dependencies of 'auth' (features that require it):
  - confirmemail
  - profile
  - reset

When you’re done, re-select the product:

splent product:select my_first_app

Full diagnostic

splent doctor --fast

Runs 14 checks in sequence: version, environment, pyproject, features, dependencies, product, feature status, outdated, Docker, infrastructure, containers, database, GitHub, and PyPI. Some checks are skipped with --fast. Use it whenever something feels off.


Where things live

File Purpose
my_first_app/pyproject.toml Feature declarations, SPL reference, layout hooks
splent_catalog/sample_splent_spl/ SPL metadata (UVL model downloaded on demand via spl:fetch)
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 against SPL constraints
spl:features / spl:deps Query the SPL catalog
doctor Comprehensive health check

Next

Tutorial 3: Create a feature — build a note-taking feature from scratch.


Back to top

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