Neutral TS Starter Py is a modular, opinionated starter kit for building Progressive Web Applications (PWA) using Python (Flask) on the backend and Neutral TS as a universal templating engine.
This project is designed to be extensible via a "plug-and-play" component architecture, allowing scalability from quick prototypes to complex applications while maintaining a clean and decoupled structure.
This starter is in active development.
- Stable base: component loading, routing, template rendering, security headers, auth/session foundations.
- Ongoing work: broader edge-case test coverage and hardening of optional modules for production use.
- Flask application factory with component-driven routing and blueprint registration.
- Modular component architecture in
src/component(manifest, schema, routes, templates, static assets). - Neutral TS templating (NTPL) with snippet composition and schema-driven data.
- Override model using
custom.jsonand optionalconfig/config.db(customtable) for per-component customization. - Security defaults: CSP, host allow-list validation, trusted proxy header guard, and security headers.
- Abuse protection: form/session token flows and request rate limiting via Flask-Limiter.
- PWA support: service worker, offline page, and web manifest component.
- Internationalization (i18n) through component locale files (
locale-*.json). - Multiple data backends configured from environment (SQLite by default).
- Automated tests for app bootstrap and component behavior (
pytest).
The project uses a layered architecture with clear responsibilities:
- NTPL templates, component CSS/JS, and static assets.
- Component routes/controllers plus request guards (security headers, host/proxy checks, access rules).
- JSON-backed models in
src/model/and DB connectivity configured fromsrc/app/config.py.
- Shared utilities, environment/config loading, and i18n locale resolution.
HTTP Client
↓
Security + Host/Proxy Guards
↓
Flask Router + Component Blueprint
↓
Component Route/RequestHandler
↓
Model/DB Access
↓
NTPL Render
↓
HTTP Response
- Python 3.10 to 3.14.
- pip (Python package manager).
- Recommended: Virtual environment (
venv).
The project includes interactive installers:
bin/install.shfor Linux/macOSbin/install.ps1for Windows PowerShell
Installer features:
- Fetches repository tags and lets you choose from the latest 15 versions.
- Asks for installation directory (current directory by default).
- Creates
.venvand installs dependencies. - Copies
config/.env.exampletoconfig/.env. - Generates a random
SECRET_KEY. - Generates randomized admin routes in:
src/component/cmp_7040_admin/custom.jsonas/admin-[random]src/component/cmp_8100_localdev/custom.jsonas/local-admin-[random]
- Randomized admin routes are generated during installation as an extra hardening measure against automated scraping/scanning of default admin URLs. This is not security by itself; core protection remains authentication/authorization and rate limiting.
- Bootstraps databases with
bin/bootstrap_db.py. - Creates an
adminrole user viabin/create_user.py(asks for user data). - Writes
DEV_ADMIN_*values intoconfig/.envfor isolatedlocaldevaccess.
Linux/macOS:
curl -fsSL https://raw.githubusercontent.com/FranBarInstance/neutral-starter-py/master/bin/install.sh | shWindows PowerShell:
powershell -ExecutionPolicy Bypass -NoProfile -Command "iwr -useb https://raw.githubusercontent.com/FranBarInstance/neutral-starter-py/master/bin/install.ps1 | iex"Important: first sign-in may require the PIN generated for the created user. Keep that PIN from the installer output.
# Create virtual environment
python -m venv .venv
# Activate environment (Linux/Mac)
source .venv/bin/activate
# Activate environment (Windows)
.venv\Scripts\activatecp config/.env.example config/.envAt minimum, set a strong value for SECRET_KEY in config/.env.
source .venv/bin/activate
pip install -r requirements.txtsource .venv/bin/activate
# Create/upgrade local DB schema (recommended first run)
python bin/bootstrap_db.py
# Optional debug guard (enabled only when all conditions are met)
# 1) set DEBUG_EXPIRE and DEBUG_FILE in config/.env
# e.g. DEBUG_EXPIRE=3600 and DEBUG_FILE=/tmp/neutral-debug.flag
export FLASK_DEBUG=1
touch /tmp/neutral-debug.flag
python src/run.pyThe application will be available at http://localhost:5000 (by default).
You can enable automatic schema bootstrap at app startup:
AUTO_BOOTSTRAP_DB=trueDefault is false to avoid implicit schema changes in production-like environments.
neutral-starter-py/
├── src/
│ ├── app/ # Flask application factory and core configuration
│ ├── component/ # MODULE COLLECTION (The most important part)
│ │ ├── cmp_7000_hellocomp/ # Example of a full component
│ │ └── ... # Other components (cmp_0100_*, cmp_0200_*, etc.)
│ ├── core/ # Core utilities (request handlers, helpers)
│ ├── model/ # Data models
│ ├── neutral/ # Template engine core
│ ├── utils/ # Utility modules
│ ├── run.py # Execution script for development
│ └── wsgi.py # Entry point for production (Gunicorn/uWSGI)
├── config/ # General configuration files
├── docs/ # Project documentation
├── public/ # Public static files
└── storage/ # Storage directory for runtime data
The strength of this starter lies in src/component. Each folder there is a self-sufficient module.
- Prefix: Components must start with
cmp_(e.g.,cmp_5000_login). - Order: They load alphabetically.
cmp_5005will overridecmp_5000if there are conflicts. - Content: A component can have:
manifest.json: Metadata and base path.schema.json: Configuration and customization settings.route/: Python logic (Flask Blueprints).neutral/: HTML templates and snippets.static/: Specific assets (JS/CSS).__init__.py: Component initialization.
Folders that do not start with cmp_ are skipped by the loader. This is used for disabled/optional components (for example _cmp_*).
Each component follows this structure:
cmp_component_name/
├── manifest.json # Component metadata
├── schema.json # Configuration and customization
├── route/ # Component-specific routes
│ ├── __init__.py
│ └── routes.py
├── neutral/ # Component templates
│ ├── component-init.ntpl
│ └── route/
│ └── root/
│ └── content-snippets.ntpl
├── static/ # Component static resources
│ ├── component.css
│ └── component.js
└── __init__.py # Component initialization
For a detailed example, see the Hello Component README. For complete technical documentation on the component architecture, refer to docs/component.md.
Configuration is handled in layers:
- Global: Environment variables and Flask configuration.
- Per Component:
schema.jsonwithin each component. - Customization:
custom.jsonallows overriding local configurations without affecting the codebase. It is ignored by git by default, with explicit repository exceptions such as the examplehellocompcomponent. - Central Override DB (optional):
config/config.dbcan store per-component JSON overrides by UUID. For overlapping keys, merge order is: base files ->custom.json->config.db.
Boolean environment variables follow a strict rule: only true (case-insensitive) enables the flag. Any other value (false, 0, no, empty, typo) is treated as False.
Security headers, CSP setup, host allow-list validation, and trusted proxy configuration are documented in:
The application provides comprehensive internationalization (i18n) support:
- Multi-language Support: Configurable per component
- Translation Files: JSON format in component
neutral/route/locale-*.jsonfiles - Automatic Detection: Based on browser headers or user preferences
- Language Switching: Built-in language selection mechanism
Components can define their own translations in neutral/route/locale-{lang}.json files, where {lang} is the language code (e.g., en, es, fr, de).
For production, use a WSGI server like Gunicorn pointing to src/wsgi.py:
source .venv/bin/activate
gunicorn --chdir src wsgi:applicationNotes:
- Keep
FLASK_DEBUGdisabled in production. - Configure
SECRET_KEY,SITE_DOMAIN,SITE_URL,ALLOWED_HOSTS, and trusted proxy CIDRs inconfig/.env. - For distributed deployments, configure a shared rate-limit backend (for example Redis) instead of
memory://.
Run test suite:
source .venv/bin/activate
pytest -qComponent tests are located under each component folder in src/component/*/tests/, with shared fixtures in src/component/conftest.py.
Test scope evolves with the component set. Use the repository as source of truth (src/component/*/tests/ and tests/), rather than a fixed list in this README.
Tests resolve blueprint names from the component directory at runtime (bp_{component_folder}), so they remain valid if a component changes numeric prefix (for example cmp_1200_backtotop to cmp_1300_backtotop).
For more detailed documentation, see the docs/ directory:
docs/component.md: Complete guide on component architecture and creation.docs/security-csp.md: Security headers, CSP configuration, host allow-list, and proxy trust boundaries.
The primary goal of this application is to provide developers with agentic, AI-powered capabilities:
- Component Creation: AI can generate new application components on demand. You can ask AI to create a specific component for a concrete task within the application ecosystem.
To support this workflow, the project includes:
- Skills: Agent skill definitions under
.agents/skills. - Technical Documentation: Detailed implementation guides in the
docs/directory.
By reading these skills and technical guides, AI can create components and related functionality on demand in a way that aligns with this project's architecture and conventions.
An effective example prompt:
Your task is to create the component component_name, which must [functional description].
Use route: /my-route
To complete this task, review:
- .agents/skills/manage-component/SKILL.md
- .agents/skills/manage-neutral-templates/SKILL.md
- src/component/component_name (as a component example)
Define routes dynamically if needed, following the pattern used by other components.
See the LICENSE file for details.