Skip to content

Vicunia: from user feedback to shipped change

Last updated October 28, 2026

Vicunia turns a request into a pull request and ships it. Connected to Camelus, a theme your users asked for can go straight to Vicunia, and when the change is deployed, the people who asked hear about it.

Set it up

  1. In Vicunia, open the project, add a source with public trust (theme text comes from your end users, so Vicunia always asks for approval and never auto-merges it), and copy its key and signing secret (Show secret).
  2. In Camelus, go to Settings → Destinations → Add destination → Vicunia:
    • URL: Vicunia's requests endpoint, https://actions.vicunia.si/api/requests. A self-hosted Vicunia serves it on its HTTP actions origin (CONVEX_SITE_ORIGIN), not on the API origin.
    • Auth header value: Bearer <the source key>.
    • Vicunia signing secret: the source's signing secret.
  3. Camelus shows a callback URL once the destination is created: https://api.camelus.si/v1/callbacks/vicunia/<id>. Paste it into the Vicunia source's callback URL.

What happens

  • Send to… → Vicunia on a theme sends one Vicunia request: the theme's title, its summary, up to 5 representative summaries and the counts, with external_id: camelus_theme_<theme id>_<n>. Each send has its own number, so each gets its own Vicunia job. No requester emails are sent; Camelus emails requesters itself.
  • Vicunia reports every job change to the callback URL, signed with the source's secret. Camelus maps it:
Vicunia Camelus
queued, running, pr_open, awaiting_merge_approval, merged Theme → In progress
deployed Theme → Shipped, with the deploy URL, and a "shipped" email drafted for requesters
rejected A note, and the theme page asks whether to decline the theme
failed, deploy_failed, blocked_by_policy A note on the theme
pending_approval Nothing yet

The pull request link and deploy URL show under Linked work on the theme.

Locally

Both apps refuse private addresses by default. To connect two local stacks, set ALLOW_PRIVATE_DESTINATIONS=true in Camelus's .env and ALLOW_PRIVATE_CALLBACKS=true in Vicunia's (both only work when the site URL is local), and use http://host.docker.internal:<port> addresses between the containers.