Feature Injection Guide
Feature Injection Guide
Audience: Developers who want to add capabilities to a generated project
Goal: Understand how to enable Commerce, Auth, Admin, and Tunnel features at generation time and after
Version: Seed & Source CLI (sscli) v2.6.13+
Table of Contents
- What is Feature Injection?
- How the Injection System Works
- Quick Decision Tree
- Feature Reference
- Injection Modes: Flag-based vs AST-based
- Recipes by Template
- After Injection: What Changed?
- Verifying Injection
- Combining Features
- Troubleshooting Injection
- FAQ
1. What is Feature Injection?
Feature injection is the process of adding a capability to a generated project without manually writing boilerplate code. When you pass a flag like --with-commerce or --with-auth during project generation, sscli writes the necessary imports, wires up routes, and installs the right dependencies for that feature — automatically.
Think of it like installing a plugin, but instead of configuring it through a UI, the CLI does it surgically at the code level.
Key benefits:
- No manual copy-paste of boilerplate
- Feature-specific files land in the right folders
- Dependencies added to the right config file (
pyproject.toml,package.json,Gemfile) - Result is clean code that looks hand-written
2. How the Injection System Works
sscli supports two injection modes:
Standard Mode (default)
Copies pre-built feature stubs into your project and wires them via direct file manipulation. Fast and predictable.
AST Mode (experimental, --use-ast-injection)
Uses Abstract Syntax Tree (AST) codemods to insert imports, routes, and function calls at the correct locations in existing code. More precise — works on code that has already been modified.
Standard mode is recommended for most users.
Internal flow:
sscli new --template <template> --with-commerce --with-auth ↓Generator validates license tier ↓inject_features() runs per-feature ↓ • Copies feature stubs into project • Adds dependencies to config file • Sets up secrets strategy (.env or Doppler) ↓Project is ready3. Quick Decision Tree
Use this to figure out which flags you need:
What do I want to add?│├─ Online store / Shopify integration?│ └─ → Use --with-commerce│├─ User login / signup / sessions?│ └─ → Use --with-auth│├─ Staff-only admin panel?│ └─ → Use --admin│ (python-saas only; automatically adds NiceGUI admin routes)│├─ External webhook receiver / ngrok tunnel?│ └─ → Use --with-tunnel│ (opens a secure tunnel for local Shopify/Stripe dev)│├─ Local SQLite database for prototyping?│ └─ → Use --with-sqlite│ (python-saas only; configures SQLAlchemy to use SQLite)│├─ Data ingestion / ETL pipeline hooks?│ └─ → Use --ingestor│ (python-saas only; adds ingestor scaffold)│├─ Stripe subscription payments / checkout?│ └─ → Use --with-payment│ (python-saas + rails-api; injects Stripe checkout + webhook handler)│└─ Shopify merchant-facing dashboard? └─ → Use --merchant-dashboard (react-client only; adds merchant UI routes)Template compatibility at a glance:
| Feature Flag | python-saas | react-client | rails-api | rails-fullstack | static-landing |
|---|---|---|---|---|---|
--with-commerce | ✅ | ✅ | ✅ | ✅ | ❌ |
--with-auth | ✅ | ✅ | ✅ | ✅ | ❌ |
--admin | ✅ | ❌ | ❌ | ❌ | ❌ |
--with-tunnel | ✅ | ✅ | ✅ | ✅ | ❌ |
--with-sqlite | ✅ | ❌ | ❌ | ❌ | ❌ |
--ingestor | ✅ | ❌ | ❌ | ❌ | ❌ |
--merchant-dashboard | ❌ | ✅ | ❌ | ❌ | ❌ |
--landing | ✅ | ❌ | ❌ | ❌ | ❌ |
--with-payment | ✅ | ❌ | ✅ | ✅ | ❌ |
4. Feature Reference
Commerce (--with-commerce)
What it does: Integrates a Shopify-compatible commerce layer into your project.
- python-saas: Imports
init_commercefromfoundry_commerce, calls it duringinit_ui. Addsnicegui-commerce>=1.0.0topyproject.toml. - react-client: Adds
CommerceProviderimport and a/shoproute wired toShopPage. - rails-api: Adds commerce route scaffold and Stripe/Shopify webhook receiver.
When to use: You are building a store, marketplace, or any flow that takes payments or syncs inventory.
When NOT to use: Pure internal tooling or admin panels that don’t handle purchasing.
Auth (--with-auth)
What it does: Adds user authentication (login, session management, protected routes).
- python-saas: Imports
AuthManagerfromfoundry_auth, runsAuthManager.setup(ui)during startup. - react-client: Adds
AuthProviderimport and a/loginroute wired toLoginPage. - rails-api: Adds Devise-compatible auth scaffold with JWT support.
When to use: Any multi-user app or anything that requires login.
When NOT to use: Internal single-user scripts or public read-only sites.
Admin (--admin)
What it does: Adds an admin panel accessible to authenticated staff only.
- python-saas: Imports
AdminPanelfromnicegui_admin, registers it withAdminPanel.register(ui).
When to use: Internal dashboards (e.g., order management, user oversight).
When NOT to use: Public-facing user flows.
Tunnel (--with-tunnel)
What it does: Configures a secure ngrok-compatible tunnel for receiving webhooks in local development.
When to use: Working on Shopify/Stripe webhooks locally. You need a public HTTPS URL that points to localhost.
When NOT to use: Production environments (tunnels are development tools only).
SQLite (--with-sqlite)
What it does: Configures SQLAlchemy to use a local sqlite:///./dev.db instead of PostgreSQL.
When to use: Rapid local prototyping. You don’t want to spin up a Postgres container.
When NOT to use: Production or any multi-user workload.
Ingestor (--ingestor)
What it does: Adds an ingestion service scaffold (ETL pipeline hooks, queue consumer stub).
When to use: Data-heavy backends that receive external events (webhooks, file uploads, API pulls).
Merchant Dashboard (--merchant-dashboard)
What it does: Adds a Shopify merchant-facing React UI with product, order, and analytics views.
When to use: You are building a white-label merchant tool.
Payment (--with-payment)
What it does: Injects Stripe-hosted Checkout + webhook handler into your backend. You get:
- A
/payments/checkoutendpoint that creates a Stripe Checkout session (redirect flow — PCI compliant, no card data in your code) - A
/payments/webhooks/stripeendpoint that verifies Stripe-Signature and routes events StripePaymentAdapterimplementingPaymentGatewayPort(async, usesasyncio.to_thread()to avoid blocking)- All Stripe env var stubs added to
.env.example stripePython SDK added as a dependency
For python-saas layout (src/ui/main.py): Router is wired via the SS-FEATURE-ROUTER marker. Routes land at /api/payments/checkout and /api/payments/webhooks/stripe.
For app-rooted projects (app/main.py, e.g. license-server): Files are auto-relocated to app/routes/payments.py and app/payment/, imports fixed automatically, router wired at /api/v1.
When to use: Any backend that needs subscription or one-time payments.
When NOT to use: Free-only apps, or if you are building a custom payment form (this feature uses Stripe-hosted Checkout, not a custom form).
After injecting: Follow → Stripe Dashboard Setup Runbook to get your API keys, register webhook endpoint, and create products/prices in Stripe.
5. Injection Modes: Flag-based vs AST-based
Standard (flag-based, default)
sscli new --template python-saas --with-commerce --with-auth --name my-project- Copies stubs from the internal feature library
- Directly appends/prepends to config files
- Works on freshly generated projects
- No external tools needed
AST-based (experimental)
sscli new --template python-saas --with-commerce --with-auth --use-ast-injection --name my-project- Uses Python/JS/Ruby codemods to surgically modify existing code
- Understands code structure — inserts at the right location, not just appended
- Required if you have already modified generated code and want to inject a feature without overwrites
- Requires
ast-grepto be installed
Install ast-grep (for AST mode):
brew install ast-grep # macOScargo install ast-grep # any platform with Rust6. Recipes by Template
python-saas (FastAPI + NiceGUI)
Minimal API backend:
sscli new --template python-saas --name my-apiFull SaaS with commerce + auth + admin:
sscli new --template python-saas --with-commerce --with-auth --admin --name my-saasWebhook receiver (Shopify local dev):
sscli new --template python-saas --with-commerce --with-tunnel --name my-webhook-devData ingestor:
sscli new --template python-saas --ingestor --name my-pipelineLocal-only prototype (no Postgres needed):
sscli new --template python-saas --with-sqlite --name my-prototypeSaaS backend with Stripe subscriptions:
sscli new --template python-saas --name my-saas --with-paymentFull SaaS with auth + commerce + payments:
sscli new --template python-saas --name my-saas --with-commerce --with-paymentreact-client (React + Vite)
Plain admin UI:
sscli new --template react-client --name my-adminStore frontend with auth:
sscli new --template react-client --with-commerce --with-auth --name my-store-frontendMerchant dashboard:
sscli new --template react-client --merchant-dashboard --name my-merchant-uirails-api (Ruby on Rails)
API-only backend:
sscli new --template rails-api --name my-apiFull Rails with commerce + auth:
sscli new --template rails-api --with-commerce --with-auth --name my-rails-saasWebhook receiver:
sscli new --template rails-api --with-commerce --with-tunnel --name my-rails-webhooksRails API with Stripe payments:
sscli new --template rails-api --name my-api --with-paymentrails-fullstack (Rails API + React Client, paired)
Note (2026-03-08):
rails-fullstackis a fully validated injection target. It accepts the same flags asrails-apion the backend side.
API-only backend with commerce:
sscli new --template rails-fullstack --with-commerce --name my-fullstack-storeFull stack with commerce + auth:
sscli new --template rails-fullstack --with-commerce --with-auth --name my-rails-saasWebhook receiver:
sscli new --template rails-fullstack --with-commerce --with-tunnel --name my-rails-webhooksFull-stack with payment + auth:
sscli new --template rails-fullstack --name my-app --with-payment --with-authPairing a Frontend and Backend (Full Stack)
Generate both with matching features enabled:
sscli new --template python-saas --with-commerce --with-auth --name backendsscli new --template react-client --with-commerce --with-auth --name frontendOr use the stack CLI interactive mode to wire them together automatically:
sscli interactive7. After Injection: What Changed?
After running sscli new with feature flags, check these locations:
python-saas changes
| Area | What changed |
|---|---|
pyproject.toml | New dependency added (e.g., nicegui-commerce, foundry_auth) |
src/ui/main.py | Import + setup call added at init |
src/features/ | Feature-specific module stub added |
.env.example | New required variables added |
app/routes/payments.py (app/ layout) or src/ui/api/payments.py (saas layout) | Stripe checkout + webhook routes |
app/payment/stripe_payment_adapter.py | Stripe SDK adapter |
app/payment/payment_gateway.py | PaymentGatewayPort ABC |
react-client changes
| Area | What changed |
|---|---|
package.json | New dependency added |
src/App.jsx | Provider wrapper added |
src/routes/ | New route entry added |
src/components/ | Feature component stub added |
.env.example | VITE_* variables added |
rails-api changes
| Area | What changed |
|---|---|
Gemfile | New gem added |
config/routes.rb | New route block injected |
app/controllers/ | Feature controller added |
.env.example | New variables added |
After injecting --with-payment or --with-commerce
Your .env.example will contain Stripe variable stubs that must be filled in before the payment flow works. Follow the step-by-step setup guide:
→ Stripe Dashboard Setup Runbook
This guide covers: getting API keys, creating products and prices in Stripe, registering the webhook endpoint, choosing the correct integration mode (Checkout), and verifying everything end-to-end.
8. Verifying Injection
After generation, verify the feature was injected correctly:
# Check for the feature import in Pythongrep -r "foundry_commerce\|foundry_auth\|AdminPanel" backend/src/
# Check for the feature route in Reactgrep -r "CommerceProvider\|AuthProvider\|/shop\|/login" frontend/src/
# Check for the gem in Railsgrep "commerce\|devise" backend/Gemfile
# Run the testscd backend && poetry run pytestcd frontend && npm testYou can also run the full stack in Docker to confirm:
cd my-projectdocker compose up9. Combining Features
Features are additive — you can combine as many as make sense for your project.
Common valid combinations:
| Use Case | Flags |
|---|---|
| SaaS with billing | --with-commerce --with-auth |
| Internal admin only | --admin --with-auth |
| Shopify webhook receiver | --with-commerce --with-tunnel |
| Full merchant platform | --with-commerce --with-auth --admin --merchant-dashboard |
| Local data prototyping | --with-sqlite --ingestor |
Features that conflict or are redundant:
--with-sqliteand a PostgreSQL-configured production environment don’t mix. SQLite is for dev only.--with-tunnelis only meaningful during local development; remove it before production deploy.--merchant-dashboardrequires--with-commerceon the backend to have something to talk to.
10. Troubleshooting Injection
”Feature not found in generated project”
Symptom: You passed --with-commerce but don’t see any commerce-related files.
Fix:
- Confirm you are on a supported template:
python-saas,react-client,rails-api, orrails-fullstack. - Check your license tier — some features require ALPHA or PRO tier.
- Run with verbose output:
sscli new --template python-saas --with-commerce --name my-project --verbose.
”AST injection failed: ast-grep not found”
Symptom: Error when using --use-ast-injection.
Fix:
brew install ast-grep # macOScargo install ast-grep # Linux/Windows with Rustwhich ast-grep # confirm it's on PATH“Feature injected but import not resolving”
Symptom: The code was injected but running the project gives ModuleNotFoundError or similar.
Fix:
- Install dependencies first:
cd my-project && poetry install(Python) ornpm install(React). - The injected dependency may have a placeholder version — update it in
pyproject.tomlorpackage.json. - Re-build the Docker image:
docker compose build --no-cache.
”Duplicate imports or routes after re-injection”
Symptom: You ran sscli new again and ended up with duplicated code.
Fix: Standard injection is not idempotent on an already-modified project. Options:
- Delete and regenerate the project (cleanest).
- Switch to
--use-ast-injectionwhich has better idempotency checking viadelta_store. - Manually remove the duplicate.
”Commerce works locally but fails on Render/production”
Symptom: The feature functions locally but not after deploying.
Fix:
- Check that all
SHOPIFY_*/STRIPE_*environment variables are set in Render’s dashboard. - Verify
.env.examplefor all required keys and set them in the environment service. - Check logs:
render logs <service-id>.
11. FAQ
Q: Can I inject a feature into a project I already modified?
A: Yes, but use --use-ast-injection. Standard injection works best on fresh projects.
Q: Can I inject multiple features at once?
A: Yes. Pass all relevant flags in one sscli new command.
Q: What license tier do I need for Commerce? A: ALPHA or PRO tier. Free tier users can generate base templates only.
Q: Is the injected code mine to own and modify?
A: Yes. Injection creates real source files in your project. There is no runtime dependency on sscli after generation.
Q: How do I add a feature to an existing project (not during generation)?
A: Use sscli inject. For payment injection on an existing project:
sscli inject --path ./my-project --features payment --template python-saasThis works on both python-saas (src/ui/main.py) and app-rooted layouts (app/main.py). For other features, use the --with-* flags at generation time. Full inject support for all features is expanding in upcoming releases.
Q: How do I test the Stripe webhook locally after injecting --with-payment?
A: Use the Stripe CLI:
stripe listen --forward-to http://localhost:8000/webhooks/stripestripe trigger checkout.session.completed# Expect: POST /webhooks/stripe → 200 {"status":"ok"}The Stripe CLI forwards real test Stripe events to your local endpoint and handles all signature verification setup automatically.
Q: What happens if I pass a flag that is not supported for my template?
A: sscli silently skips unsupported flags. No error, no partial injection. Always verify with grep after generation (see Section 8).
Q: Where is AST injection configured?
A: In foundry/codemods/ — python_codemods.py, js_codemods.py, ruby_codemods.py.
Last updated: March 8, 2026 — Payment injection (—with-payment / Stripe) added; sscli inject command documented For issues or corrections, see TROUBLESHOOTING.md