neuron-explorer
Qwen3.5‑4B 전용 조향형 뉴런 탐색기, 모든 MLP 뉴런을 밀어 결과를 보관·탐색
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
A schema-driven CMS built in Rust. Define content types with JSON Schema, edit data through a web UI, store it as JSON files on disk, and serve it via a REST API.README 전문 보기 ↗JSON Schema --> UI form generation --> JSON file on disk --> served via API
format: "upload" extension handles file uploads.data/<app-slug>/content/<schema-slug>/. Entries are cached in memory on startup and kept in sync via a file watcher. Each entry has a draft/published status.data/<app-slug>/uploads/<prefix>/<hash>. Upload metadata is tracked in SQLite.audit.db asynchronously, tracking all create/update/delete operations.Requires Rust nightly (2026-01-05 or later).
git clone https://github.com/wavefunk/substrukt.git
cd substrukt
cargo build --release
./target/release/substrukt create-admin --email [email protected] --username admin --password 'change-me-now'
./target/release/substrukt serve
Open http://localhost:3000 and sign in with the admin account you created.
docker pull ghcr.io/wavefunk/substrukt
docker run --rm -v substrukt-data:/data ghcr.io/wavefunk/substrukt create-admin --email [email protected] --username admin --password 'change-me-now'
docker run -p 3000:3000 -v substrukt-data:/data ghcr.io/wavefunk/substrukt
Data persists in the /data volume (schemas, content, uploads, databases).
All options are passed as CLI flags:
| Flag | Default | Description |
|---|---|---|
--data-dir <PATH> | data | Root directory for schemas, content, and uploads |
--db-path <PATH> | <data-dir>/substrukt.db | SQLite database file |
-p, --port <PORT> | 3000 | HTTP listen port |
--secure-cookies | off | Set Secure flag on session cookies (enable for HTTPS) |
--api-rate-limit <N> | 100 | Max API requests per IP per minute |
--version-history-count <N> | 10 | Max content versions to keep per entry |
--max-body-size <MB> | 50 | Maximum request body size in megabytes |
--enable-registrations | off | Enable public browser registration; invite links still work when disabled |
--trust-proxy-headers | off | Trust X-Forwarded-For for rate limiting (enable behind a reverse proxy) |
Deployment webhooks are configured through the web UI per app (Settings > Deployments), not via CLI flags.
S3 backup credentials are configured via environment variables (S3_BUCKET, S3_REGION, S3_ENDPOINT, S3_ACCESS_KEY, S3_SECRET_KEY). Backup frequency and retention are managed through the web UI (Settings > Backups).
substrukt serve # Start the web server (default)
substrukt import <path> --app <slug> # Import a bundle tar.gz into an app
substrukt export <path> --app <slug> # Export an app's data as bundle tar.gz
substrukt create-token <name> --app <slug> # Create an API token for an app
substrukt create-admin --email <email> --username <name> --password <password>
substrukt prime # Output AI-optimized workflow context
substrukt onboard # Output a minimal snippet for AGENTS.md / CLAUDE.md
All app-scoped API endpoints require a bearer token in the Authorization header. Tokens are created through the app's Settings > API Tokens page or via substrukt create-token --app <slug>.
Authorization: Bearer <token>
App-scoped endpoints are prefixed with /api/v1/apps/:app_slug.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/apps/:app/schemas | List all schemas |
| GET | /api/v1/apps/:app/schemas/:slug | Get a single schema |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/apps/:app/content/:schema | List entries (published by default, ?status=all for all) |
| POST | /api/v1/apps/:app/content/:schema | Create an entry (JSON body) |
| GET | /api/v1/apps/:app/content/:schema/:id | Get a single entry |
| PUT | /api/v1/apps/:app/content/:schema/:id | Update an entry (JSON body) |
| DELETE | /api/v1/apps/:app/content/:schema/:id | Delete an entry |
| POST | /api/v1/apps/:app/content/:schema/:id/publish | Publish an entry |
| POST | /api/v1/apps/:app/content/:schema/:id/unpublish | Unpublish an entry (set to draft) |
| GET | /api/v1/apps/:app/content/:schema/:id/versions | List version history |
| GET | /api/v1/apps/:app/content/:schema/:id/versions/:ts | Get a specific version |
| POST | /api/v1/apps/:app/content/:schema/:id/versions/:ts/revert | Revert to a version |
| GET | /api/v1/apps/:app/content/:schema/single | Get a single-kind schema's entry |
| PUT | /api/v1/apps/:app/content/:schema/single | Upsert a single-kind schema's entry |
| DELETE | /api/v1/apps/:app/content/:schema/single | Delete a single-kind schema's entry |
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/apps/:app/content/:schema/_bulk/create | Create multiple entries |
| POST | /api/v1/apps/:app/content/:schema/_bulk/update | Update multiple entries |
| POST | /api/v1/apps/:app/content/:schema/_bulk/delete | Delete multiple entries |
| POST | /api/v1/apps/:app/content/:schema/_bulk/publish | Publish multiple entries |
| POST | /api/v1/apps/:app/content/:schema/_bulk/unpublish | Unpublish multiple entries |
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/apps/:app/uploads | Upload a file (multipart) |
| GET | /api/v1/apps/:app/uploads/:hash | Download a file by hash |
| GET | /api/v1/apps/:app/uploads/:hash/:filename | Download with original filename |
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/apps/:app/export | Export app data as tar.gz |
| POST | /api/v1/apps/:app/import | Import a tar.gz bundle (multipart) |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/apps/:app/deployments | List deployment targets |
| POST | /api/v1/apps/:app/deployments/:slug/fire | Trigger a deployment webhook |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/openapi.json | Auto-generated OpenAPI specification |
| GET | /api/v1/backups/status | S3 backup status (admin only) |
| POST | /api/v1/backups/trigger | Trigger a manual backup (admin only) |
| GET | /metrics | Prometheus metrics (unauthenticated) |
| GET | /healthz | Health check |
Schemas are standard JSON Schema with an x-substrukt extension:
{
"x-substrukt": {
"title": "Blog Posts",
"slug": "blog-posts",
"storage": "directory",
"kind": "collection"
},
"type": "object",
"properties": {
"title": { "type": "string", "title": "Title" },
"body": { "type": "string", "format": "textarea" },
"published": { "type": "boolean", "title": "Published" },
"cover": { "type": "string", "format": "upload", "title": "Cover Image" }
},
"required": ["title"]
}
directory -- one JSON file per entry in data/content/<slug>/<id>.jsonsingle-file -- all entries in data/content/<slug>.json as a JSON arraycollection (default) -- multiple entries, each with its own IDsingle -- exactly one entry per schema, ideal for site settings or configuration| JSON Schema type | Format | UI element |
|---|---|---|
string | (none) | Text input |
string | textarea | Textarea |
string | upload | File input |
string | enum | Select dropdown |
number / integer | Number input | |
boolean | Checkbox | |
object | Nested fieldset | |
array | Repeatable fields |
Export creates a tar.gz bundle containing all schemas, content, and uploads for an app. Import unpacks the bundle into the app's data directory and rebuilds the cache.
# CLI
substrukt export backup.tar.gz --app my-app
substrukt import backup.tar.gz --app my-app
# API
curl -X POST -H "Authorization: Bearer $TOKEN" http://localhost:3000/api/v1/apps/my-app/export -o backup.tar.gz
curl -X POST -H "Authorization: Bearer $TOKEN" -F "[email protected]" http://localhost:3000/api/v1/apps/my-app/import
This enables a workflow where content is edited locally and pushed to a production instance via CI.
data/
substrukt.db # Users, sessions, API tokens, apps
audit.db # Audit log, deployments, backup config
<app-slug>/ # Per-app data directory
schemas/ # JSON Schema files (<slug>.json)
content/ # Content entries
<slug>/ # Per-schema directories (directory mode)
<id>.json # Individual entries
<slug>.json # Single-file mode entries
uploads/ # Content-addressed files
<prefix>/ # First 2 hex chars of SHA-256
<rest> # Remaining hash chars (file data)
_history/ # Version history snapshots
MIT