Reference document for scaffolding the p4n4 GitHub organisation and its constituent repositories. Version 0.1 | 2026
p4n4 is organised across 14 repositories under the raisga GitHub organisation (plus one under
jraleman). Each repository has a single, well-defined responsibility and can be developed,
versioned, and released independently. The p4n4 umbrella repo is a monorepo that aggregates
all sub-repos as Git submodules, grouped by concern.
raisga/
├── .github ← org profile, shared issue templates, org-wide Actions workflows
└── p4n4 ← umbrella (monorepo with submodules)
├── stacks/
│ ├── iot ← p4n4-iot: Mosquitto · Node-RED · InfluxDB · Grafana
│ ├── ai ← p4n4-ai: Ollama · Letta · n8n
│ └── edge ← p4n4-edge: Edge Impulse inference stack
├── core/
│ ├── lib ← p4n4-lib: shared library (stacks ↔ clients)
│ └── hw ← p4n4-hw: hardware designs + RPi5 GPIO scripts
├── clients/
│ ├── cli ← p4n4-cli: Python CLI (published to PyPI as `p4n4`)
│ ├── api ← p4n4-api: REST API gateway
│ └── dashboard ← p4n4-dashboard: web dashboard client
├── tools/
│ ├── templates ← p4n4-templates: community template registry & index
│ └── emu ← p4n4-emu: workstation hardware emulator
└── web/
├── docs ← p4n4-docs: full technical documentation site (this repo)
├── p4n4.com ← p4n4.com: public-facing website (jraleman/p4n4.com)
└── blog ← p4n4-blog: project blog
Naming note: The
p4n4umbrella repo and thep4n4PyPI package (fromp4n4-cli) share the same short name intentionally — the CLI is the primary user-facing product. The umbrella repo is the GitHub landing page and monorepo root, not the package source.
| Repo | Monorepo path | Type | Standalone? | PyPI / Registry | Description |
|---|---|---|---|---|---|
.github |
— | org meta | — | — | Org profile README, shared Actions, issue templates |
p4n4 |
— | meta / monorepo | — | — | Umbrella: architecture, ADRs, all sub-repos as submodules |
p4n4-iot |
stacks/iot |
stack | ✓ | — | Docker Compose IoT stack; owns p4n4-net bridge |
p4n4-ai |
stacks/ai |
stack | ✓ | — | Docker Compose GenAI stack; attaches to p4n4-net |
p4n4-edge |
stacks/edge |
stack | ✓ | — | Docker Compose Edge Impulse stack; attaches to p4n4-net |
p4n4-lib |
core/lib |
library | ✓ | — | Shared library mediating between stacks and clients |
p4n4-hw |
core/hw |
hardware | — | — | KiCad PCB designs and RPi5 GPIO scripts |
p4n4-templates |
tools/templates |
registry | — | Git-native | Community template index + example templates |
p4n4-cli |
clients/cli |
tool | ✓ | p4n4 on PyPI |
Python CLI for scaffolding and lifecycle management |
p4n4-api |
clients/api |
service | ✓ | — | REST API gateway (port 8000) |
p4n4-dashboard |
clients/dashboard |
frontend | ✓ | — | Web dashboard client |
p4n4-emu |
tools/emu |
tool | ✓ | — | Workstation hardware emulator (Docker resource constraints + QEMU) |
p4n4-docs |
web/docs |
docs | — | — | Full technical reference; deployable as a static site |
p4n4.com |
web/p4n4.com |
website | — | — | Public-facing website (jraleman/p4n4.com) |
p4n4-blog |
web/blog |
website | — | — | Project blog |
.github (org profile).github/
├── profile/
│ └── README.md ← shown on github.com/raisga
├── ISSUE_TEMPLATE/
│ ├── bug_report.yml
│ ├── feature_request.yml
│ └── template_submission.yml
├── PULL_REQUEST_TEMPLATE.md
└── workflows/
└── stale.yml ← org-wide stale issue/PR bot
p4n4 (umbrella)p4n4/
├── README.md ← project overview, quick links to all sub-repos
├── CONTRIBUTING.md
├── CODE_OF_CONDUCT.md
├── SECURITY.md
├── LICENSE
├── stacks/
│ ├── iot/ ← submodule: p4n4-iot
│ ├── ai/ ← submodule: p4n4-ai
│ └── edge/ ← submodule: p4n4-edge
├── core/
│ ├── lib/ ← submodule: p4n4-lib
│ └── hw/ ← submodule: p4n4-hw
├── clients/
│ ├── cli/ ← submodule: p4n4-cli
│ ├── api/ ← submodule: p4n4-api
│ └── dashboard/ ← submodule: p4n4-dashboard
├── tools/
│ ├── templates/ ← submodule: p4n4-templates
│ └── emu/ ← submodule: p4n4-emu
└── web/
├── docs/ ← submodule: p4n4-docs (ARCHITECTURE.md lives here)
├── p4n4.com/ ← submodule: jraleman/p4n4.com
└── blog/ ← submodule: p4n4-blog
p4n4-iot (IoT stack)Owns the p4n4-net Docker bridge network. All other stacks attach to it as an external network.
Note: The pre-existing
p4n4-iotrepo uses the network namep4n4-net. The newp4n4-aiandp4n4-edgestacks referencep4n4-netas an external network. When running all stacks together, ensure network names are aligned (the CLI handles this automatically viap4n4 up).
p4n4-iot/
├── docker-compose.yml ← primary compose file (services + network definition)
├── docker-compose.override.yml ← local dev overrides (bind mounts, debug ports)
├── .env.example ← standalone .env template
├── .gitignore
├── .dockerignore
├── Makefile ← convenience targets: up, down, status, test-mqtt
├── LICENSE
├── README.md
│
├── config/ ← all service config files under a single top-level dir
│ ├── mosquitto/
│ │ ├── mosquitto.conf
│ │ ├── passwd ← generated by p4n4-cli; placeholder in repo
│ │ └── acl
│ │
│ ├── node-red/
│ │ ├── flows.json ← version-controlled base flows (IoT only)
│ │ └── settings.js
│ │
│ └── grafana/
│ └── provisioning/
│ ├── datasources/
│ │ └── datasources.yml
│ └── dashboards/
│ ├── dashboards.yml
│ └── json/
│ └── iot-overview.json
│
├── scripts/
│ ├── init-sandbox.sh
│ └── selector.sh
│
└── .github/
└── workflows/
└── ci.yml
Network block in docker-compose.yml:
networks:
p4n4-net:
name: p4n4-net
driver: bridge
p4n4-ai (GenAI stack)Attaches to p4n4-net as an external network (must be created by p4n4-iot first, or via p4n4 up, which starts p4n4-iot first).
p4n4-ai/
├── docker-compose.yml
├── docker-compose.override.yml
├── .env.example
├── .gitignore
├── LICENSE
├── README.md
│
├── ollama/
│ └── pull-models.sh ← helper script: docker exec ollama ollama pull <model>
│
├── letta/
│ └── config/
│ └── letta.conf
│
└── n8n/
└── workflows/
├── alert-enrichment.json
├── scheduled-digest.json
├── device-onboarding.json
└── incident-escalation.json
Network block in docker-compose.yml:
networks:
p4n4-net:
external: true
name: p4n4-net
p4n4-edge (Edge Impulse stack)Fully independent. Attaches to p4n4-net as external when used with the IoT stack, but can also run standalone on a dedicated network.
p4n4-edge/
├── docker-compose.yml
├── docker-compose.override.yml
├── .env.example
├── .gitignore
├── README.md
│
└── edge-impulse/
└── models/
└── .gitkeep ← .eim binaries are NEVER committed; provided at deploy time
Network block in docker-compose.yml:
networks:
p4n4-net:
external: true
name: p4n4-net
p4n4-cli (Python CLI / PyPI package)The pip install p4n4 package. A thin Typer/Rich presentation layer: all shared,
framework-free logic lives in p4n4-lib (see the module table below). Scaffolding
fetches stack files from the canonical stack repos at init time (git clone --depth 1),
or from a local checkout via --source-iot / --source-ai for offline use.
p4n4-cli/
├── pyproject.toml ← build system, deps, version, PyPI metadata
├── README.md
├── CHANGELOG.md
├── .github/
│ └── workflows/
│ ├── ci.yml ← lint + test on every PR
│ └── publish.yml ← publish to PyPI on release
│
├── p4n4/
│ ├── __init__.py ← package version
│ ├── cli.py ← Typer app entrypoint; command registration
│ ├── project.py ← locate the current project's manifest / compose dirs
│ │
│ └── commands/
│ ├── __init__.py
│ ├── init.py ← `p4n4 init` interactive wizard
│ ├── add.py ← `p4n4 add`
│ ├── remove.py ← `p4n4 remove`
│ ├── lifecycle.py ← `p4n4 up / down / status / logs`
│ ├── ei.py ← `p4n4 ei` subcommands
│ ├── secret.py ← `p4n4 secret`
│ ├── validate.py ← `p4n4 validate`
│ ├── upgrade.py ← `p4n4 upgrade`
│ └── template.py ← `p4n4 template` subcommands
│
└── tests/
├── conftest.py
└── test_cli.py
Shared library (p4n4-lib, imported as p4n4_lib):
| Module | Purpose |
|---|---|
p4n4_lib.manifest |
.p4n4.json read / write / find (walk-up) |
p4n4_lib.env |
Dotenv read/write, template-preserving writes |
p4n4_lib.layers |
Layer registry: repo URLs, copy paths, required files/env keys |
p4n4_lib.layout |
Project layout: flat (single-layer) vs per-layer subdirectories |
p4n4_lib.scaffold |
Fetch stack sources and copy them into a project |
p4n4_lib.validate |
Pure project validation returning (passed, errors) |
p4n4_lib.secrets |
Token generation and rotatable-key policy |
p4n4_lib.compose |
Docker Compose subprocess wrappers |
Generated project layout: single-layer projects keep stack files at the project
root. Multi-layer projects give each layer its own subdirectory (<project>/iot/,
<project>/ai/) with its own docker-compose.yml, config/, scripts/, and .env,
so the stacks run as separate Compose projects sharing the p4n4-net network
(see §5.2).
pyproject.toml key fields:
[project]
name = "p4n4"
requires-python = ">=3.11"
dependencies = [
"p4n4-lib>=0.1.0",
"typer[all]>=0.12",
"rich>=13",
"questionary>=2",
"jinja2>=3",
]
[project.scripts]
p4n4 = "p4n4.cli:app"
[project.urls]
Homepage = "https://github.com/raisga/p4n4-cli"
Documentation = "https://github.com/raisga/p4n4-docs"
p4n4-templates (community template registry)Acts as the https://github.com/raisga/templates index resolved by p4n4 template search.
p4n4-templates/
├── index.json ← community template index (short-name → repo URL map)
├── README.md ← how to use and contribute templates
├── TEMPLATE_GUIDE.md ← full authoring guide (p4n4-template.toml spec)
├── .github/
│ └── workflows/
│ └── validate-index.yml ← CI: validate index.json schema on every PR
│
├── scripts/
│ ├── validate_index.py ← validates index.json schema
│ └── validate_templates.py ← validates all p4n4-template.toml files
│
└── examples/
├── factory-baseline/ ← full IoT + GenAI + EI starter (manufacturing)
│ ├── p4n4-template.toml
│ ├── docker-compose.iot.yml.j2
│ ├── docker-compose.ai.yml.j2
│ ├── docker-compose.edge.yml.j2
│ ├── mosquitto/config/mosquitto.conf.j2
│ ├── mosquitto/config/acl.j2
│ ├── node-red/flows.json
│ ├── grafana/provisioning/dashboards/factory-base.json
│ └── n8n/workflows/alert-enrichment.json
│
└── iot-minimal/ ← IoT-only starter (no AI, no Edge)
├── p4n4-template.toml
├── docker-compose.iot.yml.j2
├── mosquitto/config/mosquitto.conf.j2
├── node-red/flows.json
└── grafana/provisioning/dashboards/minimal.json
index.json schema:
{
"org": "community",
"index_version": "1",
"templates": {
"factory-baseline": {
"repo": "https://github.com/raisga/p4n4-templates.git",
"subdir": "examples/factory-baseline",
"description": "Full IoT + GenAI + EI stack for discrete manufacturing",
"tags": ["manufacturing", "vibration", "edge-impulse", "genai"],
"latest": "0.1.0"
},
"iot-minimal": {
"repo": "https://github.com/raisga/p4n4-templates.git",
"subdir": "examples/iot-minimal",
"description": "Minimal IoT-only stack for simple sensor monitoring",
"tags": ["minimal", "iot"],
"latest": "0.1.0"
}
}
}
p4n4-docs (documentation site)p4n4-docs/
├── README.md ← full technical reference
├── ARCHITECTURE.md ← this file
├── mkdocs.yml ← site config (deploy pending)
├── docs/ ← MkDocs source pages
│ ├── adr/
│ │ ├── ADR-001.md
│ │ └── ADR-002.md
│ ├── diagrams/
│ │ └── .gitkeep
│ ├── index.md
│ ├── getting-started.md
│ ├── iot-stack.md
│ ├── ai-stack.md
│ ├── edge-stack.md
│ ├── hardware.md
│ ├── emulator.md
│ ├── cli-reference.md
│ ├── template-registry.md
│ ├── security.md
│ ├── design.md
│ └── specs.md
└── .github/
└── workflows/
└── deploy-docs.yml ← publish to GitHub Pages on push to main
p4n4-hw (hardware designs and scripts)KiCad PCB projects and Raspberry Pi 5 GPIO scripts for the p4n4 platform reference hardware.
p4n4-hw/
├── README.md
├── LICENSE
├── dev-board/ ← KiCad project: main dev board (schematic + PCB)
├── prototypes/
│ └── leds-indicator/ ← KiCad project: LED indicator prototype board
└── scripts/
└── rpi5/
├── p4n4_common.py ← shared GPIO helpers, service catalogue, TCP probe
├── p4n4_boot_sim.py ← boot sequence simulator (LED blink patterns)
├── p4n4_shutdown_sim.py ← graceful shutdown simulator
├── p4n4_health_monitor.py ← service health monitor (TCP probe + GPIO LED)
├── p4n4_button_handler.py ← physical button (single / double / long press)
└── p4n4_mqtt_indicator.py ← MQTT traffic activity indicator
All RPi5 scripts share a common GPIO pin assignment (GPIO 17 = status LED, GPIO 27 = push button)
and depend on RPi.GPIO plus optionally paho-mqtt.
p4n4-emu (hardware emulator)Workstation emulator that applies Docker resource constraints per hardware profile so developers can test against realistic edge hardware limits without a physical board.
p4n4-emu/
├── README.md
├── guide.md ← step-by-step setup and LED toggle guide
├── pyproject.toml
├── uv.lock
├── LICENSE
├── p4n4_emu/
│ ├── cli.py ← Typer entrypoint (p4n4-emu command)
│ ├── profiles/ ← hardware profile definitions (rpi4, rpi5, nuc, mcu-class)
│ ├── overlay/ ← Compose overlay generator (deploy.resources.limits)
│ ├── sim/
│ │ └── sensor_sim.py ← synthetic MQTT sensor publisher
│ └── hw/
│ └── gpio_stub.py ← drop-in RPi.GPIO replacement for workstations
└── tests/
Hardware profiles:
| Profile | CPU | Memory | Disk R/W | Arch |
|---|---|---|---|---|
rpi4 |
4 cores | 3.5 GB | 50 MB/s | arm64 |
rpi5 |
4 cores | 7 GB | 100 MB/s | arm64 |
mcu-class |
1 core | 256 MB | 10 MB/s | x86_64 |
nuc |
4 cores | 14 GB | 200 MB/s | x86_64 |
┌─────────────┐
│ p4n4 │ (umbrella — no code deps)
└──────┬──────┘
│ links to
┌──────────────────┼──────────────────┐
│ │ │
┌──────▼──────┐ ┌───────▼──────┐ ┌──────▼──────┐
│ p4n4-iot │ │ p4n4-ai │ │ p4n4-edge │
│ (owns net) │ │ (ext: net) │ │ (ext: net) │
└──────┬──────┘ └──────────────┘ └─────────────┘
│ p4n4-net (bridge, created by p4n4-iot)
│ ← p4n4-ai/edge attach via p4n4-net (see §5.1)
│
┌──────▼──────────────────────────────────────────┐
│ p4n4-cli │
│ bundles Jinja2 templates for all three stacks │
│ reads p4n4-templates index for `template` cmds │
└──────────────────────────────────────────────────┘
│
┌──────▼──────┐
│p4n4-templates│ (Git-native; no code import)
└─────────────┘
1. p4n4-iot → creates p4n4-net + starts Mosquitto & InfluxDB first
2. p4n4-ai → attaches to p4n4-net; needs Mosquitto (optional) + InfluxDB healthy
3. p4n4-edge → attaches to p4n4-net; fully independent of ai stack
Running p4n4 up with no stack argument enforces this order: it starts each stack’s
Compose project in sequence (iot → ai → edge); p4n4 down stops them in reverse.
p4n4-iot creates a network named p4n4-net.p4n4-ai and p4n4-edge declare p4n4-net as external: true.p4n4 up) starts the stacks in dependency
order (iot first), so the IoT compose project creates p4n4-net before the other
stacks attach to it. Manual deployments must ensure the network name is consistent
across stacks.p4n4-net differently (owner vs external: true), their
compose files must not be merged into one Compose project — this is why multi-layer
projects scaffold each stack into its own directory (see 5.2)..env FilesManaged by CLI (recommended):
p4n4 init scaffolds each enabled stack with its own .env, generated with
cryptographically secure secrets. Single-layer projects keep everything at the project
root; multi-layer projects give each stack its own subdirectory and .env, and every
docker compose call runs inside that stack’s directory.
my-project/ ← multi-layer layout (`--layer iot,ai`)
├── .p4n4.json ← manifest: project name, enabled layers
├── iot/
│ ├── docker-compose.yml ← copied from p4n4-iot
│ ├── .env ← iot secrets, never committed
│ ├── config/ …
│ └── scripts/ …
└── ai/
├── docker-compose.yml ← copied from p4n4-ai
├── .env ← ai secrets + shared InfluxDB values
├── config/ …
└── scripts/ …
Cross-stack values (INFLUXDB_TOKEN, INFLUXDB_ORG, INFLUXDB_BUCKET) are written
identically to every stack’s .env at init time, and p4n4 secret rotate generates one
new value per key and writes it to every .env containing that key, so credentials
never drift between stacks.
Standalone (without CLI):
Each stack repo ships its own .env.example. Copy to .env and fill in values manually.
Cross-stack secrets (e.g. INFLUXDB_ADMIN_TOKEN used by both p4n4-iot and p4n4-ai) must be
kept consistent manually — document this prominently in each stack’s README.
| Variable | Owner stack | Consumed by |
|---|---|---|
MQTT_USER / MQTT_PASSWORD |
p4n4-iot |
Node-RED |
INFLUXDB_ADMIN_TOKEN |
p4n4-iot |
Node-RED, Grafana, n8n |
INFLUXDB_ORG / INFLUXDB_BUCKET |
p4n4-iot |
Node-RED, Grafana, n8n |
GF_SECURITY_ADMIN_PASSWORD |
p4n4-iot |
Grafana |
N8N_BASIC_AUTH_USER / _PASSWORD |
p4n4-ai |
n8n |
N8N_ENCRYPTION_KEY |
p4n4-ai |
n8n |
LETTA_SERVER_PASSWORD |
p4n4-ai |
Letta, Node-RED |
EI_API_KEY |
p4n4-edge |
Edge Impulse containers (optional) |
Each repository is versioned independently with MAJOR.MINOR.PATCH Git tags.
| Repo | Version bumps when… |
|---|---|
p4n4-iot |
compose/config changes, new service added, breaking config change |
p4n4-ai |
same as above for AI services |
p4n4-edge |
same for Edge Impulse services |
p4n4-cli |
new CLI command, flag changes, template schema change, bug fixes |
p4n4-templates |
new example template, index entry added/changed, guide updated |
p4n4-docs |
no formal releases; main is always current |
The CLI bundles its own Jinja2 templates for scaffolding. To track which bundled template
version is compatible with which stack config version, a compatibility table is maintained
in p4n4-cli/p4n4/compat.py:
STACK_COMPAT = {
"iot": ">=0.1.0",
"ai": ">=0.1.0",
"edge": ">=0.1.0",
}
When a breaking change is made to a stack repo, the CLI’s bundled templates are updated in the
same PR and the STACK_COMPAT table is bumped. The CLI warns if the running stack version is
outside the compatible range (detected via a VERSION file in each stack repo).
p4n4-cli)1. Bump version in p4n4/cli.py __version__ and pyproject.toml
2. Update CHANGELOG.md
3. Open PR → CI passes → merge to main
4. Tag: git tag v0.2.0 && git push origin v0.2.0
5. publish.yml workflow triggers → builds wheel → uploads to PyPI
p4n4-iot, p4n4-ai, p4n4-edge# .github/workflows/ci.yml
on: [push, pull_request]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Validate docker-compose
run: docker compose -f docker-compose.yml config --quiet
- name: Lint YAML/JSON configs
run: |
pip install yamllint
yamllint .
- name: Check .env.example completeness
run: python scripts/check_env_example.py
p4n4-cli# ci.yml
on: [push, pull_request]
jobs:
test:
strategy:
matrix:
python-version: ["3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: "$" }
- run: pip install -e ".[dev]"
- run: ruff check .
- run: pytest tests/ -v --cov=p4n4
# publish.yml
on:
push:
tags: ["v*"]
jobs:
publish:
steps:
- uses: actions/checkout@v4
- run: pip install build
- run: python -m build
- uses: pypa/gh-action-pypi-publish@release/v1
with:
password: $
p4n4-templates# validate-index.yml
on: [push, pull_request]
jobs:
validate:
steps:
- uses: actions/checkout@v4
- name: Validate index.json schema
run: python scripts/validate_index.py index.json
- name: Validate all example p4n4-template.toml files
run: python scripts/validate_templates.py examples/
p4n4-docs# deploy-docs.yml
on:
push:
branches: [main]
jobs:
deploy:
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
- run: pip install mkdocs-material
- run: mkdocs gh-deploy --force
Follow this order when scaffolding the repositories from scratch:
Step 1 — Create GitHub org
→ Create raisga on GitHub
→ Set org profile, billing, team permissions
Step 2 — Scaffold .github (org profile)
→ Create raisga/.github repo
→ Add profile/README.md, shared issue templates
Step 3 — Scaffold p4n4 (umbrella)
→ README, CONTRIBUTING, SECURITY, CODE_OF_CONDUCT
→ docs/decisions/adr/ directory with ADR-001 (this architecture decision)
Step 4 — Scaffold p4n4-docs (this repo)
→ Move/copy README.md (full technical reference)
→ Add ARCHITECTURE.md (this file)
→ Wire up mkdocs.yml + deploy workflow (stub, activate in Phase 2)
Step 5 — Scaffold p4n4-iot
→ docker-compose.yml with p4n4-net definition
→ All service configs with sane defaults
→ .env.example
→ CI workflow
Step 6 — Scaffold p4n4-ai
→ docker-compose.yml with external p4n4-net
→ n8n workflows (starter JSON exports)
→ .env.example
→ CI workflow
Step 7 — Scaffold p4n4-edge
→ docker-compose.yml with external p4n4-net
→ edge-impulse/models/.gitkeep
→ .env.example
→ CI workflow
Step 8 — Scaffold p4n4-cli
→ pyproject.toml + package skeleton
→ Copy Jinja2 templates from reference configs in steps 5–7
→ CI + publish workflows
→ Stub tests
Step 9 — Scaffold p4n4-templates
→ index.json with two starter entries
→ examples/factory-baseline/ and examples/iot-minimal/
→ TEMPLATE_GUIDE.md
→ index validation CI
| Label | Colour | Use |
|---|---|---|
stack: iot |
#e07b39 |
Relates to p4n4-iot |
stack: ai |
#7b39e0 |
Relates to p4n4-ai |
stack: edge |
#39b0e0 |
Relates to p4n4-edge |
stack: cli |
#3de05e |
Relates to p4n4-cli |
type: bug |
#d73a4a |
Something is broken |
type: feature |
#0075ca |
New feature request |
type: docs |
#cfd3d7 |
Documentation change |
type: security |
#b60205 |
Security issue |
good first issue |
#7057ff |
Good for newcomers |
mainmainApply to all stack repos: iot, docker-compose, docker, self-hosted
p4n4-iot also: mosquitto, node-red, influxdb, grafanap4n4-ai also: ollama, letta, n8n, llm, genaip4n4-edge also: edge-impulse, tinyml, edge-aip4n4-cli also: cli, python, typer, scaffoldingThese are not part of the initial scaffold. They are noted here to avoid architectural decisions that would make them harder to do later.
p4n4-flows (Phase 3)Extract Node-RED flows out of p4n4-iot into a standalone community flows library.
p4n4-flows/
├── index.json ← flow registry (analogous to template index)
├── flows/
│ ├── telemetry-ingest/
│ ├── anomaly-detection/
│ ├── ai-digest/
│ └── device-command/
Compatibility note: flows.json in p4n4-iot stays as the default base; p4n4-flows is an
opt-in extension library. The CLI would gain a p4n4 flows pull <name> subcommand.
Teams using the template system with private templates will create their own index repos
(e.g. acme/p4n4-index). The raisga/templates repo is the community default.
No changes to the core repos are needed — the CLI already supports p4n4 template org add.
Requires no new repos. Implemented as a new set of n8n workflows and Node-RED flows deployed
via the existing p4n4-ai + p4n4-iot repos, plus a multi-site example in p4n4-templates.
Document maintained in raisga/p4n4-docs (monorepo path: web/docs). Open issues or PRs there for changes.