# Contribute Mini Apps

{% embed url="<https://github.com/aboutcircles/CirclesMiniapps>" %}

{% hint style="info" %}
There are two ways to contribute Mini Apps to Circles:

* **Garage Mini Apps** — externally hosted experimental, community, and hackathon apps
* **Embedded Mini Apps** — curated production-grade apps fully shipped from this repository
  {% endhint %}

***

## Circles Mini App Host

Circles Mini Apps are hosted by a SvelteKit application that renders apps inside iframes at:

```txt
https://<VITE_BASE_URL>/miniapps
```

Mini apps communicate with the host through a `postMessage` wallet bridge for:

* Wallet connection
* Transaction requests
* Message signing
* App metadata

The marketplace reads app metadata from:

```txt
static/miniapps.json
```

When a user opens:

```txt
/miniapps/<slug>
```

the host loads the corresponding app URL inside an iframe.

***

## Choose Your Submission Type

| Type              | Best For                                                 | Hosting                          | Review Level       |
| ----------------- | -------------------------------------------------------- | -------------------------------- | ------------------ |
| Garage Mini App   | Experimental apps, hackathons, demos, community projects | External hosting allowed         | Lightweight review |
| Embedded Mini App | Curated production apps                                  | Must live inside this repository | Full review        |

***

## Garage Mini Apps

Garage Mini Apps are intended for:

* Hackathon projects
* Experimental apps
* Community tools
* Early-stage prototypes
* Circles Garage competition entries

Garage apps:

* Can be hosted anywhere
* Only require a manifest PR
* Run under a stricter transaction policy
* Show a "use at your own risk" disclaimer

Examples of allowed hosting:

* Vercel
* Netlify
* GitHub Pages
* Your own domain

### What a Garage PR should contain

Garage submissions only require a metadata entry.

The app itself remains in your own repository and deployment.

Your PR should contain:

* A new entry in `static/miniapps.json`
* Optionally a logo under `static/app-logos/`
* A deployed HTTPS URL that already works inside an iframe

Open the PR against:

```txt
aboutcircles/CirclesMiniapps
```

branch:

```txt
master
```

***

## Embedded Mini Apps

Embedded Mini Apps are curated production-grade apps that ship directly from this repository.

This path is intended for apps that:

* Should become part of the official Mini Apps experience
* Need deeper review and maintainability
* Are intended to be maintained long term inside this repository

For Embedded Mini Apps:

* The full source code must be included in the PR
* The app must live inside this repository
* External-host-only submissions are not accepted

***

## Embedded Mini App structure

Recommended layout:

```txt
src/routes/apps/<slug>/+page.svelte
src/routes/apps/<slug>/components/...
static/app-logos/<slug>.png
static/apps/<slug>/...
```

Recommended routing pattern:

| Route              | Purpose                   |
| ------------------ | ------------------------- |
| `/miniapps/<slug>` | Marketplace wrapper route |
| `/apps/<slug>`     | Actual embedded app route |

Example manifest entry:

```json
{
  "slug": "my-app",
  "name": "My App",
  "logo": "/app-logos/my-app.png",
  "url": "/apps/my-app",
  "description": "Short description of the app.",
  "tags": ["payments", "tools"],
  "category": "miniapp"
}
```

***

## Manifest Format

Both Garage and Embedded Mini Apps are registered in:

```txt
static/miniapps.json
```

### Required fields

| Field         | Required | Notes                        |
| ------------- | -------: | ---------------------------- |
| `slug`        |      yes | URL-safe unique identifier   |
| `name`        |      yes | Display name                 |
| `logo`        |      yes | HTTPS URL or local repo path |
| `url`         |      yes | App URL                      |
| `description` |      yes | Short app description        |
| `tags`        |      yes | Discovery tags               |
| `category`    |      yes | `"garage"` or `"miniapp"`    |
| `isHidden`    |       no | Hide from marketplace grid   |

***

## Example Garage Entry

```json
{
  "slug": "your-app-slug",
  "name": "Your App",
  "logo": "/app-logos/your-app.png",
  "url": "https://your-app.example.com/",
  "description": "One-sentence description.",
  "tags": ["demo", "tools"],
  "category": "garage"
}
```

***

## Example Embedded Entry

```json
{
  "slug": "embedded-app",
  "name": "Embedded App",
  "logo": "/app-logos/embedded-app.png",
  "url": "/apps/embedded-app",
  "description": "Embedded app description.",
  "tags": ["payments"],
  "category": "miniapp"
}
```

***

## Host Integration

Mini apps communicate with the host using `postMessage`.

Mini app → host:

* `request_address`
* `send_transactions`
* `sign_message`

Host → mini app:

* `wallet_connected`
* `wallet_disconnected`
* `app_data`
* `tx_success`
* `tx_rejected`
* `sign_success`
* `sign_rejected`

Current implementation lives in:

```txt
src/routes/miniapps/[slug]/+page.svelte
src/routes/playground/+page.svelte
```

Build against the actual implementation, not assumptions.

***

## Garage Transaction Policy

Garage apps run under a stricter transaction policy.

Before approval, the host rejects any transaction batch that:

* Targets the user's currently acting Safe
* Targets the user's primary Safe while in child-safe mode
* Uses restricted Safe-management selectors

Restricted selectors:

| Selector     | Function                                 |
| ------------ | ---------------------------------------- |
| `0x0d582f13` | `addOwnerWithThreshold(address,uint256)` |
| `0xf8dc5dd9` | `removeOwner(address,address,uint256)`   |
| `0xe318b52b` | `swapOwner(address,address,address)`     |
| `0x694e80c3` | `changeThreshold(uint256)`               |
| `0xe19a9dd9` | `setGuard(address)`                      |
| `0xf08a0323` | `setFallbackHandler(address)`            |
| `0x610b5925` | `enableModule(address)`                  |
| `0xe009cfde` | `disableModule(address,address)`         |
| `0x6a761202` | `execTransaction(...)`                   |

The entire batch is rejected on the first violation.

The user sees a restricted-action modal and the iframe receives:

```txt
tx_rejected
```

### Garage apps cannot

* Call `execTransaction`
* Add/remove owners
* Change Safe configuration
* Enable modules
* Modify guards
* Wrap their own Safe execution flow

If your app requires these permissions, it should be submitted as an Embedded Mini App instead.

***

## Local Development

Before opening a PR, run:

```sh
npm install
npm run check
npm run build
```

Then verify manually:

1. Open `/miniapps`
2. Confirm the app appears
3. Open `/miniapps/<slug>`
4. Confirm the iframe loads correctly
5. Test the main app flow
6. Test wallet/signing flows if applicable

***

## PR Expectations

All PRs should include:

* App metadata in `static/miniapps.json`
* Working routes and URLs
* Logo/assets
* Clear PR description
* Testing notes

Embedded Mini Apps must additionally include:

* Full application source code
* Any required dependencies
* Local assets and routes

Recommended PR titles:

Garage:

```txt
feat: add <app-name> garage app
```

Embedded:

```txt
feat: add <app-name> embedded miniapp
```

***

## Review Criteria

Maintainers will review:

* Whether the app works inside the iframe host
* Wallet/signing safety
* Build stability
* Asset quality
* Maintainability
* Transaction behavior
* Whether the correct submission path was used

***

## Common Rejection Reasons

Garage submissions may be rejected if:

* The app does not load in an iframe
* The URL is broken
* Restricted Safe-management actions are attempted
* The manifest is incomplete

Embedded submissions may be rejected if:

* The PR only links to an external deployment
* Core logic still lives outside this repository
* Local routes/assets are missing
* The app fails build or check
* The iframe integration is broken

***

## Minimal Checklist

### Garage Mini App

* [ ] Added entry to `static/miniapps.json`
* [ ] `category` is `"garage"`
* [ ] App loads over HTTPS
* [ ] App works inside iframe
* [ ] Logo resolves correctly
* [ ] `slug` is unique
* [ ] No restricted Safe-management calls

### Embedded Mini App

* [ ] App source added under `src/routes/apps/<slug>/`
* [ ] Metadata added to `static/miniapps.json`
* [ ] `category` is `"miniapp"`
* [ ] Local logo/assets committed
* [ ] `/miniapps/<slug>` works
* [ ] `npm run check` passes
* [ ] `npm run build` passes

If you want maintainers to merge and host your app directly as part of the Circles Mini Apps platform, submit it as an Embedded Mini App.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.aboutcircles.com/miniapps/contribute-mini-apps.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
