Extensions
Each integration has a small, deliberate contract. Pass dependencies explicitly in app constructors. Imports never register models, routes, jobs or templates.
#Ask your agent
Read https://cicadel.fauzaanu.com/en/dev/topics/extensions/index.md.
Integrate [admin, storage or background-job feature] into this application.
Read the relevant integration API before writing code. Pass explicit dependencies,
keep authorization in the application, and test the real success and failure paths.#Admin
admin.Routes[T] creates list, create, edit and delete HTML routes for a GORM
model with one integer primary key. You supply:
- an explicit field allowlist;
- a request-specific query scope;
- an authorization callback;
- a CSRF-token provider.
Permissions are required. They are checked both before and after applying submitted fields. Unlisted fields cannot be assigned. Wrap the routes in session and CSRF middleware.
Warning
Do not expose credential fields. The list is capped at 100 records in this initial version; it is not a general reporting interface.
#Run the catalog example
The catalog example shows related products and categories, with different editor and manager permissions. It accepts Basic authentication over HTTPS using a bcrypt hash from the environment. It is an integration example, not an account-management product.
export CICADEL_CATALOG_PASSWORD_HASH="$(CICADEL_USER_PASSWORD='your local test passphrase' go run ./examples/catalog hashpassword)"
export DATABASE_URL='postgres://USER:PASSWORD@localhost/cicadel_catalog?sslmode=disable'
export CICADEL_DEBUG=true
export CICADEL_SECURE_COOKIES=false
go run ./examples/catalog migrate
go run ./examples/catalog runserver- Sign in as
editorormanagerwith the supplied password. Both can edit; only the manager can delete. - The two roles share a demonstration password. Real projects should use their user directory and independently managed credentials.
- Send credentials from your HTTP client. Denied access returns 403, not a browser authentication prompt.
/admin/categories/and/admin/products/host the admin./is a paginated public product API.
#JSON APIs
| Helper | What it does |
|---|---|
api.Decode | Requires JSON, rejects unknown fields and trailing values, and relies on the application’s request-body limit. Validate required fields after decoding. |
api.Pagination | Bounds limit and offset. |
api.Fail | Returns consistent code, message and field errors. |
Use explicit output structs so model fields are never disclosed by accident. Schema generation is not included. An optional schema layer can be added without changing handlers.
mail.Sender validates envelope and header inputs before calling a Transport.
mail.Renderuses separate text and escaped HTML engines.mail.Captureis concurrency-safe development storage.- Built-in SMTP supports verified STARTTLS and implicit TLS, connection reuse for batches, MIME alternatives, attachments, and CC and BCC.
- Console, file, capture and discard backends support development and tests.
Configure the provider and verified destinations explicitly. See email.
#File storage
storage.Local stores flat, application-generated keys in a rooted directory.
Writes are bounded. An object is replaced atomically only after the whole upload
succeeds.
storage.HTTP supports object storage through a signed-URL function you provide.
- It requires HTTPS, refuses redirects and bounds uploads.
- The trusted signer owns credentials, buckets and signature policy.
- It is a generic signed-URL adapter, not a bundled S3 credential or signing implementation.
- Test your provider’s signing and required headers before deployment, and configure a client timeout.
Serve stored media with the right content types and authorization. Validate filenames and content at the upload boundary.
#Cache
cache.Memory has a fixed entry capacity, a per-value byte limit, a key-length
limit, a TTL, copied values and explicit deletion. It is process-local. When full,
it evicts the oldest inserted entry.
- Use it only for results you can recompute.
- Invalidate keys after committed writes.
- Version key formats when output changes.
- Never treat cache presence as authorization.
Shared, multi-instance invalidation needs a different, application-provided cache implementation.
#Jobs
Cicadel uses River’s PostgreSQL queue and exposes River’s own client and worker types.
| Function | Role |
|---|---|
jobs.Migrate | Runs River’s schema upgrades as an explicit deployment step. |
jobs.NewProducer | Uses the application’s SQL pool. |
jobs.InsertTx | Requires an active GORM transaction and enqueues atomically with its writes. Call it inside db.Transaction, passing tx, not the outer db. |
jobs.NewWorker | Uses a separate pgx pool, with explicit worker registrations and concurrency. |
Run a worker in three steps:
- Start the worker once.
- Call
Stopwith a shutdown deadline. - Close its pool.
River owns persistence, retry scheduling, job timeout configuration and queue coordination. Set per-job attempt and timeout policies with River’s options.
Warning
Workers must be idempotent. External side effects can happen again if completion acknowledgement fails. Transactional enqueueing does not make network calls atomic.
Prepared-statement transaction wrappers are not supported by the initial GORM enqueue helper. The integration test proves that rolled-back jobs disappear and committed jobs run. It does not claim exactly-once external delivery.
#Localization
Cicadel has no native internationalization or localization engine. The
experimental locale package was removed before release.
- Use third-party Go libraries through explicit middleware and template helpers.
- There is no bundled catalog, translation command, locale negotiation or humanization API.
- Browser translation does not remove server-side localization requirements.
- Accessible labels, validation errors and time-zone-correct timestamps remain application and framework concerns.
#Observability
observability.Middleware generates request IDs. It logs method, status, bytes
and duration, without bodies or query strings. It exposes a synchronous callback
for metrics or tracing adapters.
- Keep callbacks fast, concurrency-safe and non-panicking.
- Full distributed trace propagation is an application integration.
- Health handlers support optional, bounded readiness checks.
#Extension contracts
Public extension points are ordinary Go interfaces and functions:
- HTTP handlers and middleware;
- explicit app constructors and dependencies;
template.FuncMapand filesystem sources;- native GORM, SCS stores and River workers;
- mail transports, storage stores and observer callbacks.
Extensions share the core’s version compatibility policy. There is no dynamic plugin loading and no stable binary ABI.
#Installable apps
The installable-app foundation supplies manifests, compatibility and dependency checks, namespaced commands, checks and resources, PostgreSQL migrations, and startup and cleanup. Typed component contributions are implemented.
Broader model and settings contracts and more module extraction remain open in the package acceptance checklist. Accounts, formsets, migrations and query generation already have independent modules. Other integrations remain in the main module.
#Component packages
UI packages export typed ui.Definition contracts through App.Components, with
explicit children and named slots. See the component UI design.
template.FuncMapand legacy template filesystems are compatibility-only.- The starter and both application examples use compiled components.
- A completed component package must not depend on Django template syntax or hidden request context.
#Accounts and logging
The accounts starter uses compiled HTML and PostgreSQL cookie sessions. The JSON bearer adapter remains available for API clients. Both use one account service, shared revocation and explicit object authorization. Administration remains a separate, limited integration.
Logging provides:
- named configuration, propagation and filters;
- JSON and text handlers, and file rotation;
- optional captured or SMTP error alerts;
- credential redaction, request IDs and panic stacks;
- private GORM query timing.
Application configuration owns outputs and closes resources after requests drain.