Introduction

Customizing your fork

After forking stanza-go/standalone, there are a few things to change before you start building. This page covers each one.


Change the Go module path

The standalone repo uses github.com/stanza-go/standalone as its module path. Update it to match your fork:

cd api

# Update go.mod
sed -i '' 's|github.com/stanza-go/standalone|github.com/your-org/your-app|g' go.mod

# Update all imports across the codebase
find . -name '*.go' -exec sed -i '' 's|github.com/stanza-go/standalone|github.com/your-org/your-app|g' {} +

After renaming, verify it compiles:

go vet ./...

Change the data directory

By default, all application state lives in ~/.stanza/. The data directory name is defined in api/datadir/datadir.go:

const defaultName = ".stanza"

Change it to match your project:

const defaultName = ".my-app"

In production, override with the DATA_DIR environment variable — point it to your persistent volume:

DATA_DIR=/data ./my-app

The directory structure is created automatically on first boot:

~/.my-app/
├── database.sqlite      ← all data
├── logs/                ← structured logs
├── uploads/             ← user uploads
├── backups/             ← automatic backups
└── config.yaml          ← runtime config overrides

Multiple apps on one machine

Each forked app needs its own data directory. If you're running multiple experiments locally, either change defaultName for each or use DATA_DIR to point them to separate directories. Without this, they'll share the same database.


Change the app name and metadata

Update the app name in api/main.go — look for the health check and version info:

// In provideServer or wherever the health response is built:
"app": "my-app",

Also update the Makefile and Dockerfile if you've renamed the binary.


Environment variables

These environment variables control runtime behavior. Set them in your shell, .env file, or container platform:

VariableDefaultPurpose
DATA_DIR~/.stanzaWhere database, logs, uploads, and backups live
PORTIf set, server binds to 0.0.0.0:{PORT} (Railway, Cloud Run)
STANZA_SERVER_ADDR:23710Server listen address (ignored when PORT is set)
STANZA_AUTH_SIGNING_KEYrandomHex-encoded signing key (min 64 chars). Random = sessions don't survive restart
STANZA_AUTH_SECURE_COOKIEStrueSet to false for local HTTP development
STANZA_CORS_ORIGINShttp://localhost:23706,http://localhost:23700Comma-separated allowed origins
STANZA_EMAIL_RESEND_API_KEYResend API key for transactional email
STANZA_EMAIL_FROMFrom address for emails (e.g., App <noreply@example.com>)

For local development, the minimum is:

export STANZA_AUTH_SECURE_COOKIES=false

For production, set at minimum DATA_DIR and STANZA_AUTH_SIGNING_KEY.


Pre-built API routes

The standalone app ships with 33 modules. Here are all the endpoints, grouped by area.

Admin authentication

MethodPathPurpose
POST/api/admin/auth/loginAuthenticate admin (email + password)
GET/api/admin/authStatus check + access token refresh
POST/api/admin/auth/logoutRevoke session, clear cookies

User authentication

MethodPathPurpose
POST/api/auth/registerCreate new user account
POST/api/auth/loginAuthenticate user (email + password)
GET/api/authStatus check + access token refresh
POST/api/auth/logoutRevoke session, clear cookies

Password reset

MethodPathPurpose
POST/api/auth/forgot-passwordRequest reset email
POST/api/auth/reset-passwordReset with token

Admin panel endpoints

All admin endpoints require an authenticated admin session.

MethodPathPurpose
GET/api/admin/dashboard/statsSystem stats (uptime, memory, DB size, counts)
GET/api/admin/dashboard/chartsTime-series data for dashboard charts
GET/POST/api/admin/adminsList / create admin users
GET/PUT/DELETE/api/admin/admins/{id}Get / update / soft-delete admin
GET/POST/api/admin/rolesList / create roles
GET/PUT/DELETE/api/admin/roles/{id}Get / update / delete role
GET/api/admin/scopesList all available scopes
GET/api/admin/sessionsList active sessions
DELETE/api/admin/sessions/{id}Revoke a session
GET/POST/api/admin/usersList / create end-users
GET/PUT/DELETE/api/admin/users/{id}Get / update / soft-delete end-user
GET/api/admin/auditAudit log (paginated, filterable)
GET/api/admin/cronList cron jobs with status
POST/api/admin/cron/{name}/runTrigger a cron job manually
GET/api/admin/queue/statsQueue counts by status
GET/api/admin/queue/jobsList jobs (filterable by status/type)
GET/api/admin/queue/jobs/{id}Job detail (payload, attempts, errors)
POST/api/admin/queue/jobs/{id}/retryRetry a failed/dead job
POST/api/admin/queue/jobs/{id}/cancelCancel a pending job
GET/api/admin/logsQuery structured logs
GET/api/admin/logs/streamSSE stream of live logs
GET/api/admin/db/statsDatabase stats (size, WAL, page count)
POST/api/admin/db/backupCreate a backup
GET/api/admin/db/backupsList backups
GET/api/admin/db/backups/{name}Download a backup
DELETE/api/admin/db/backups/{name}Delete a backup
POST/api/admin/db/integrityRun integrity check
POST/api/admin/db/optimizeRun PRAGMA optimize
GET/PUT/api/admin/settingsGet / update app settings
GET/POST/api/admin/webhooksList / create webhooks
GET/PUT/DELETE/api/admin/webhooks/{id}Get / update / delete webhook
GET/api/admin/webhooks/{id}/deliveriesWebhook delivery log
POST/api/admin/webhooks/{id}/testSend test delivery
GET/POST/api/admin/api-keysList / create API keys
GET/DELETE/api/admin/api-keys/{id}Get / revoke API key
GET/api/admin/uploadsList uploaded files
DELETE/api/admin/uploads/{id}Delete an upload
GET/api/admin/notificationsList notifications
POST/api/admin/notificationsCreate a notification
GET/PUT/api/admin/profileGet / update own admin profile
PUT/api/admin/profile/passwordChange own password
GET/api/admin/routesList all registered routes
GET/api/admin/metricsPrometheus metrics
GET/api/healthHealth check (version, uptime, memory)

User endpoints

All user endpoints (except auth) require an authenticated user session.

MethodPathPurpose
GET/PUT/api/user/profileGet / update own profile
PUT/api/user/profile/passwordChange own password
GET/PUT/api/user/settingsGet / update user settings (key-value)
GET/api/user/activityOwn activity log
GET/POST/api/user/api-keysList / create personal API keys
DELETE/api/user/api-keys/{id}Revoke own API key
POST/api/user/uploadsUpload a file
GET/api/user/uploadsList own uploads
DELETE/api/user/uploads/{id}Delete own upload
GET/api/user/notificationsList own notifications
PUT/api/user/notifications/{id}/readMark notification as read

Local development with go.work

When you need to develop your app against a local copy of the framework (e.g., to add a framework feature or debug an issue), use a go.work file:

# From your project root (parent of api/)
cat > go.work << 'EOF'
go 1.26.1

use (
    ./api
    ../path/to/framework
)
EOF

With go.work in place, Go resolves github.com/stanza-go/framework from the local directory instead of the module cache. Changes to the framework are picked up immediately — no need to tag or publish.

go.work is local only

Add go.work and go.work.sum to .gitignore. The workspace file is for local development — CI and production use the published module version from go.mod.

When you're done and want to use the published framework version again, simply delete the go.work file.


What to change — checklist

  1. Module path in api/go.mod + all import statements
  2. Data directory name in api/datadir/datadir.go
  3. App name in health check and metadata
  4. Auth signing key — set STANZA_AUTH_SIGNING_KEY for persistent sessions
  5. CORS origins — update when your frontend runs on a different domain
  6. Email config — set Resend API key and from address when ready
Previous
Installation