cicadel
Documentation

Extensions

Each integration has a deliberately small contract. Register dependencies explicitly in app constructors; do not rely on imports to register models, routes, jobs, or templates.

Ask your agent

text
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 and API

admin.Routes[T] creates list/create/edit/delete HTML routes for a GORM model with one integer primary key. Supply an explicit field allowlist, a request-specific query scope, an authorization callback, and a CSRF-token provider. Permissions are required and checked both before and after applying submitted fields. Unlisted fields cannot be assigned. The list is capped at 100 records in this initial version; it is not a general reporting interface. Do not expose credential fields. Wrap routes in session and CSRF middleware.

The catalog example demonstrates related products/categories and different editor/manager permissions. It accepts Basic authentication over HTTPS using an environment-supplied bcrypt hash; it is an integration example, not an account-management product. Run:

sh
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

Use editor or manager as the Basic-auth username with the supplied password. Both can edit, but only the manager can delete. The two roles share a demonstration password; real projects should use their user directory and independently managed credentials. Supply credentials through your HTTP client; the example deliberately returns 403 for denied access rather than issuing a browser authentication prompt. /admin/categories/ and /admin/products/ host the admin; / is a paginated public product API.

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/field errors. Explicit output structs prevent accidental model-field disclosure. Schema generation is not included; an optional schema layer can be added without changing handlers.

Mail, files, and cache

mail.Sender validates envelope/header inputs before calling a Transport. mail.Render uses separate text and escaped HTML engines. mail.Capture is concurrency-safe development storage. Built-in SMTP supports verified STARTTLS/implicit TLS and connection reuse for batches, MIME alternatives, attachments and CC/BCC. Console, file, capture and discard backends support development and tests. Configure the provider and verified destinations explicitly; see email.

storage.Local stores flat application-generated keys in a rooted directory. Writes are bounded and replace objects atomically after the whole upload succeeds. storage.HTTP supports object storage via a caller-provided signed-URL function. It requires HTTPS, refuses redirects, bounds uploads, and delegates credentials/bucket/signature policy to the trusted signer. It is a generic signed-URL adapter, not a bundled S3 credential/signing implementation. Test your provider’s signing and required headers before deployment. Configure a client timeout. Stored media must be served with appropriate content types and authorization; filename/content validation belongs at the upload boundary.

cache.Memory has a fixed entry capacity, per-value byte limit, key-length limit, TTL, copied values, and explicit deletion. It is process-local and evicts the oldest inserted entry when full. Use it for recomputable results only. Invalidate keys after committed writes, version key formats when output changes, and never treat cache presence as authorization. Shared/multi-instance invalidation requires a different application-provided cache implementation.

Jobs

Cicadel uses River’s PostgreSQL queue and exposes its native client/worker types. 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 and explicit worker registrations/concurrency. Start the worker once, call Stop with a shutdown deadline, then close its pool. River owns persistence, retry scheduling, job timeout configuration, and queue coordination. Set per-job attempt/timeout policies using River’s options. Workers must be idempotent: external side effects can happen again if completion acknowledgement fails. Network calls do not become atomic merely because enqueueing is transactional. 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 execute. It does not claim exactly-once external delivery.

Third-party localization, observability, and extension contracts

Cicadel has no native internationalization/localization engine. The experimental locale package was removed before release. Applications may 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 is not a guarantee that server-side localization requirements disappear. Accessible labels, validation errors and time-zone-correct timestamps remain application/framework concerns.

observability.Middleware generates request IDs, logs method/status/bytes/duration without bodies/query strings, and 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.

Public extension boundaries are ordinary Go interfaces/functions: HTTP handlers and middleware, explicit app constructors/dependencies, template.FuncMap, filesystem sources, native GORM, SCS stores, River workers, mail transports, storage stores, and observer callbacks. Extensions share the same version compatibility policy as the core. There is no dynamic plugin loading or stable binary ABI.

The installable-app foundation now supplies manifests, app compatibility/dependency checks, namespaced commands/checks/resources, PostgreSQL migrations and startup/cleanup. Typed component contributions are implemented. Broader model/settings contracts and additional 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.

UI packages export typed ui.Definition contracts through App.Components, with explicit children and named slots; see the component UI design. template.FuncMap and 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, filters, JSON/text handlers, file rotation, optional captured/SMTP error alerts, credential redaction, request IDs, panic stacks and private GORM query timing. Application configuration owns outputs and closes resources after request drain.

↑

Type to search this version.