{"id":50495576,"url":"https://github.com/aboutcircles/CirclesMiniapps","last_synced_at":"2026-06-19T00:00:53.340Z","repository":{"id":340137612,"uuid":"1160832027","full_name":"aboutcircles/CirclesMiniapps","owner":"aboutcircles","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-17T13:44:17.000Z","size":18744,"stargazers_count":2,"open_issues_count":5,"forks_count":14,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-06-17T14:27:28.762Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Svelte","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aboutcircles.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-02-18T12:28:07.000Z","updated_at":"2026-06-17T12:53:19.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/aboutcircles/CirclesMiniapps","commit_stats":null,"previous_names":["aboutcircles/circlesminiapps"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/aboutcircles/CirclesMiniapps","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aboutcircles%2FCirclesMiniapps","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aboutcircles%2FCirclesMiniapps/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aboutcircles%2FCirclesMiniapps/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aboutcircles%2FCirclesMiniapps/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aboutcircles","download_url":"https://codeload.github.com/aboutcircles/CirclesMiniapps/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aboutcircles%2FCirclesMiniapps/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34511617,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-18T02:00:06.871Z","response_time":128,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-02T07:00:22.844Z","updated_at":"2026-06-19T00:00:53.333Z","avatar_url":"https://github.com/aboutcircles.png","language":"Svelte","funding_links":[],"categories":["Build a Mini App"],"sub_categories":[],"readme":"# Circles Mini App Host\n\nA SvelteKit app that hosts mini apps in iframes at `https://\u003cVITE_BASE_URL\u003e/miniapps`. Mini apps can request wallet transactions and message signing via a postMessage protocol.\n\n---\n\n## Submitting a Garage Mini App\n\nThis guide is for adding an app to **Circles Garage** — the section of the [Mini Apps marketplace](https://circles.gnosis.io/miniapps) for experimental, community, and hackathon apps, including [Circles Garage competition](https://garage.aboutcircles.com/) entries.\n\nGarage apps:\n\n- Can be hosted anywhere — your own domain, Vercel, Netlify, GitHub Pages, etc.\n- Run under a stricter host transaction policy (see [Garage transaction policy](#garage-transaction-policy)).\n- Show a legal notice to users. Apps flagged with `\"strongDisclaimer\": true` in the manifest show a stronger \"use at your own risk\" preview disclaimer instead of the standard curated mini-app notice.\n\nTo submit a curated production-grade Embedded Mini App instead, see [docs.aboutcircles.com/miniapps/contribute-mini-apps](https://docs.aboutcircles.com/miniapps/contribute-mini-apps).\n\n### What the PR should contain\n\nGarage submissions only need a manifest entry — the app itself stays in your repo and deployment.\n\n- A new entry in [`static/miniapps.json`](static/miniapps.json) with `\"category\": \"garage\"` pointing at your deployed app\n- Optionally a square logo committed under `static/app-logos/`\n- The deployed URL must already be reachable and embeddable in an iframe\n\nOpen the PR against `master` on [aboutcircles/CirclesMiniapps](https://github.com/aboutcircles/CirclesMiniapps).\n\n### How the host loads your app\n\nThe marketplace reads metadata from `static/miniapps.json`. When a user opens `/miniapps/\u003cslug\u003e`, the host loads the `url` from your entry inside an iframe and exposes the wallet bridge via `postMessage` (see [Integration with Mini Apps SDK](#intgration-with-mini-apps-sdk) below).\n\n### Manifest fields\n\n| Field | Required | Notes |\n|---|---|---|\n| `slug` | yes | URL-safe, unique identifier. Becomes the path `/miniapps/\u003cslug\u003e`. |\n| `name` | yes | Display name shown in the marketplace. |\n| `logo` | yes | HTTPS URL or repo-relative path of a square logo (SVG or PNG, min 64×64 px). Empty string falls back to a first-letter tile. |\n| `url` | yes | Absolute HTTPS URL of your deployed app. Must load in an iframe. |\n| `description` | yes | Short description shown under the app name. |\n| `tags` | yes | At least one tag, e.g. `[\"defi\"]`. |\n| `category` | yes | Must be `\"garage\"`. |\n| `isHidden` | no | If `true`, hides the tile from the grid. The app is still reachable at `/miniapps/\u003cslug\u003e`. |\n| `strongDisclaimer` | no | If `true`, the app shows the strong \"use at your own risk\" disclaimer instead of the standard curated mini-app notice. |\n\nExample entry:\n\n```json\n{\n  \"slug\": \"your-app-slug\",\n  \"name\": \"Your App\",\n  \"logo\": \"/app-logos/your-app.png\",\n  \"url\": \"https://your-app.example.com/\",\n  \"description\": \"One-sentence description of what it does.\",\n  \"tags\": [\"demo\", \"tools\"],\n  \"category\": \"garage\"\n}\n```\n\n### Garage transaction policy\n\nGarage apps post transactions through `@aboutcircles/miniapp-sdk`'s `sendTransactions` (see [Integration with Mini Apps SDK](#intgration-with-mini-apps-sdk) below). Before the approval popup is shown, the host runs the batch through a policy that rejects any tx that:\n\n1. Targets the user's currently-acting Safe address.\n2. Targets the user's primary Safe (when operating in child-safe mode).\n3. Uses any of these Safe-management 4-byte selectors:\n\n| Selector | Function |\n|---|---|\n| `0x0d582f13` | `addOwnerWithThreshold(address,uint256)` |\n| `0xf8dc5dd9` | `removeOwner(address,address,uint256)` |\n| `0xe318b52b` | `swapOwner(address,address,address)` |\n| `0x694e80c3` | `changeThreshold(uint256)` |\n| `0xe19a9dd9` | `setGuard(address)` |\n| `0xf08a0323` | `setFallbackHandler(address)` |\n| `0x610b5925` | `enableModule(address)` |\n| `0xe009cfde` | `disableModule(address,address)` |\n| `0x6a761202` | `execTransaction(...)` |\n\nThe whole batch is rejected on the first offender. The user sees a \"Restricted action\" modal explaining what was blocked; the iframe receives a `tx_rejected` postMessage.\n\nWhat a Garage app **cannot** do:\n\n- Wrap its own `execTransaction` to act on a Safe the user co-owns. The host already wraps every tx as needed; calling `execTransaction` yourself is treated as a smuggling attempt.\n- Add owners, swap guards, enable modules, or otherwise mutate the user's Safe configuration.\n\nIf you need these, the app does not belong in Garage — submit it as a curated Embedded Mini App via the docs site link above.\n\n### PR checklist\n\n- [ ] Entry added to `static/miniapps.json` with all required fields and `\"category\": \"garage\"`\n- [ ] App loads over HTTPS and renders inside an iframe (no `X-Frame-Options: DENY`, no restrictive `frame-ancestors`)\n- [ ] Logo resolves to a valid image\n- [ ] `slug` is unique\n- [ ] No attempt to call `execTransaction` or any Safe-management selectors from the app\n- [ ] PR title: `feat: add \u003cyour app name\u003e (garage)`\n\nThe Circles team reviews and merges PRs on a best-effort basis.\n\n---\n\n## Please Note:\nIf you only want to test your miniapps, you don't need to go through the below steps and run the environment locally. You can use [Circles Playground](https://circles.gnosis.io/playground).\n\n## Prerequisites\n\n- [Node.js](https://nodejs.org) 18+\n- [mkcert](https://github.com/FiloSottile/mkcert) for local TLS certificates\n\n---\n\n## 1. Install mkcert\n\n**macOS:**\n```sh\nbrew install mkcert\nmkcert -install\n```\n\n**Linux:**\n```sh\nsudo apt install libnss3-tools\ncurl -JLO \"https://dl.filippo.io/mkcert/latest?for=linux/amd64\"\nchmod +x mkcert-v*-linux-amd64\nsudo mv mkcert-v*-linux-amd64 /usr/local/bin/mkcert\nmkcert -install\n```\n\n**Windows:**\n```sh\nchoco install mkcert\nmkcert -install\n```\n\n---\n\n## 2. Configure environment\n\nCopy `.env.example` to `.env` and fill in your values:\n\n```sh\ncp .env.example .env\n```\n\n```env\nVITE_COMETH_API_KEY=your_cometh_api_key\nVITE_PIMLICO_API_KEY=your_pimlico_api_key\nVITE_BASE_URL=circles.gnosis.io\n```\n\n`VITE_BASE_URL` is used for page titles and the dev server hostname. It must match the TLS certificate and `/etc/hosts` entry below.\n\n---\n\n## 3. Generate TLS certificates\n\nRun this from the project root, using your `VITE_BASE_URL` value:\n\n```sh\nmkcert circles-dev.gnosis.io\n```\n\nThis produces two files in the current directory:\n\n- `circles-dev.gnosis.io.pem` — certificate\n- `circles-dev.gnosis.io-key.pem` — private key\n\nThese are gitignored and must be generated locally by each developer.\n\n---\n\n## 4. Add the host to /etc/hosts\n\nThe dev server binds to the hostname, so you need to point it to localhost.\n\n**macOS / Linux:**\n\n```sh\nsudo sh -c 'echo \"127.0.0.1 circles-dev.gnosis.io\" \u003e\u003e /etc/hosts'\n```\n\n**Windows** — open `C:\\Windows\\System32\\drivers\\etc\\hosts` as Administrator and add:\n\n```\n127.0.0.1 circles-dev.gnosis.io\n```\n\n---\n\n## 5. Install dependencies\n\n```sh\nnpm install\n```\n\n---\n\n## 6. Run the dev server\n\n```sh\nsudo npm run dev\n```\n\nThe app is now available at **https://circles-dev.gnosis.io** (port 443).\n\n\u003e Your browser will trust the certificate because mkcert adds its CA to the system trust store.\n\n---\n\n## Running example mini apps locally\n\nThe `examples/` directory contains demo mini apps you can run alongside the host for testing.\n\n**Sign Message demo** (port 5181):\n```sh\nnpm run demo:sign\n```\n\n**ERC20 Transfer demo** (port 5180):\n```sh\nnpm run demo:tx\n```\n\nTo test locally, update `static/miniapps.json` to point the relevant app URL to `http://localhost:518x/`.\n\n---\n\n## Mini apps\n\nApps listed in `static/miniapps.json` appear on the `/miniapps` page. See [Submitting Your App](#submitting-your-app-to-the-marketplace) for the full entry format.\n\n### URL patterns\n\n| URL | Description |\n|---|---|\n| `/miniapps` | App list |\n| `/miniapps/\u003cslug\u003e` | Open a specific app directly |\n| `/miniapps/\u003cslug\u003e?data=\u003cbase64\u003e` | Open app and pass arbitrary data to it |\n\n### Passing data to apps\n\nThe `?data=` param carries arbitrary base64-encoded data to the mini app. The host decodes it and delivers it via a `app_data` postMessage. The mini app defines its own schema — plain strings, JSON, ABI-encoded bytes, etc.\n\n**Example — base64 JSON:**\n```js\nconst data = btoa(JSON.stringify({ message: 'Please sign this', context: 'my-app:v1' }))\n// use in URL: /miniapps/my-app?data=\u003cdata\u003e\n```\n\n**Example — ABI-encoded bytes (viem):**\n```js\nimport { encodeAbiParameters } from 'viem'\nconst encoded = encodeAbiParameters(\n  [{ type: 'string' }, { type: 'address' }],\n  ['Hello', '0xABC...']\n)\nconst data = btoa(encoded)\n```\n\n---\n\n## Intgration with Mini Apps SDK\n\nMini apps communicate with the host via `window.postMessage`. Use [Mini App SDK](https://www.npmjs.com/package/@aboutcircles/miniapp-sdk) for a ready-made client-side SDK.\n\n## Wallet\n\nWallet connection uses [Cometh Connect SDK](https://docs.cometh.io) with a Safe smart account and Pimlico as the paymaster on Gnosis Chain.\n\n- Connecting triggers a passkey prompt via `navigator.credentials.get()` — the user picks their passkey and Cometh resolves the associated Safe address automatically\n- No address input required — the Safe address is derived from the passkey\n- On successful connect the address is saved to `localStorage` and restored on next visit without prompting the passkey again\n- Disconnecting clears both the in-memory state and `localStorage`\n\n---\n\n## Build\n\n```sh\nnpm run build\n```\n\nOutput goes to `build/`. It is a fully static site (SvelteKit adapter-static) with a `404.html` fallback for client-side routing of dynamic slug routes.\n\n\n## Developer responsibilities\nBy submitting a mini-app for listing, you confirm that:\nYour app and its use of Circles / Gnosis tooling complies with all applicable laws and regulations in the jurisdictions .\nYou have not introduced, and will not introduce, any malicious code, backdoors or other potentially technologically harmful content or software designed to compromise users’’ assets, rights, wallets or the Circles/Gnosis infrastructure, and you will take reasonable care in accordance with industry practice to avoid the existence of any bugs or vulnerabilities in the mini-apps you develop that could lead to loss of user funds or disruption to our systems.\nThe Circles / Gnosis team may reject, de-list, disable or restrict the availability of any mini-app at any time, in its sole discretion, including where we suspect any legal or  security risks, or where we have reason to believe you are engaging in abusive or prohibited behaviour.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faboutcircles%2FCirclesMiniapps","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faboutcircles%2FCirclesMiniapps","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faboutcircles%2FCirclesMiniapps/lists"}