---
updatedAt: 2026-05-27T21:04:59.000Z
agentTools:
  projectIndex: https://docs.upside.tech/llms.txt
---

# Miniapp Creation

Miniapps are sandboxed HTML apps that live inside the Upside dashboard. They can query live customer data via SQL and render widgets, reports, or interactive tools that you share with your team. There are two supported authoring paths: the **Upside MCP** (for any MCP client connected to Upside) and the **in-app agent** (the agent built into the dashboard).

## What you'll build

A *hosted* miniapp:

* Lives inside the dashboard, sharable with your org
* Can use the MiniApp SDK to query live Upside data
* Supports versioning (open → sealed → active)
* Previewable via deep links before promotion

<div style={{borderLeft:'4px solid #347BD1',background:'#e8f1fb',padding:'14px 18px',borderRadius:'6px',margin:'20px 0'}}>
  <div style={{fontWeight:700,color:'#347BD1',marginBottom:'6px',fontSize:'14px'}}>📘 Live (hosted) vs. static (standalone)</div>
  <div style={{color:'#1f4768',fontSize:'14px',lineHeight:1.55}}>You can build <strong>both</strong> kinds yourself — you do <strong>not</strong> need Upside to build live apps for you. A <strong>live (hosted)</strong> miniapp is wired to your live Upside data via the MiniApp SDK, runs inside the dashboard, and is sharable and versioned (this page covers these). A <strong>static (standalone)</strong> miniapp is a self-contained HTML file with no dashboard integration and no live data.<br /><br /><strong>Ask for "live" explicitly.</strong> The agent won't always default to a live app — especially for deep-research / deep-dive style requests, where it often builds a standalone (static) app instead. Tell it something like <em>"make this a live app connected to my Upside data"</em> to get a hosted one.</div>
</div>

***

## Path 1: Creating a Miniapp via the Upside MCP

You don't write code or call tools yourself — describe the miniapp you want in plain English to your MCP client, and the agent handles the build for you. It creates a workspace, writes the HTML, wires up the SDK to query your live data, and registers versions on your behalf.

<div style={{display:'flex',alignItems:'center',gap:'8px',margin:'24px 0',padding:'14px 18px',background:'#f8fafc',borderRadius:'8px',flexWrap:'wrap',border:'1px solid #e2e8f0'}}>
  <span style={{display:'inline-flex',alignItems:'center',justifyContent:'center',width:'24px',height:'24px',borderRadius:'999px',background:'#2d6a4f',color:'white',fontWeight:700,fontSize:'12px',flexShrink:0}}>1</span>
  <span style={{fontSize:'13px',color:'#334155',fontWeight:600}}>Describe</span>
  <span style={{color:'#cbd5e1'}}>→</span>
  <span style={{display:'inline-flex',alignItems:'center',justifyContent:'center',width:'24px',height:'24px',borderRadius:'999px',background:'#2d6a4f',color:'white',fontWeight:700,fontSize:'12px',flexShrink:0}}>2</span>
  <span style={{fontSize:'13px',color:'#334155',fontWeight:600}}>Preview</span>
  <span style={{color:'#cbd5e1'}}>→</span>
  <span style={{display:'inline-flex',alignItems:'center',justifyContent:'center',width:'24px',height:'24px',borderRadius:'999px',background:'#2d6a4f',color:'white',fontWeight:700,fontSize:'12px',flexShrink:0}}>3</span>
  <span style={{fontSize:'13px',color:'#334155',fontWeight:600}}>Iterate</span>
  <span style={{color:'#cbd5e1'}}>→</span>
  <span style={{display:'inline-flex',alignItems:'center',justifyContent:'center',width:'24px',height:'24px',borderRadius:'999px',background:'#2d6a4f',color:'white',fontWeight:700,fontSize:'12px',flexShrink:0}}>4</span>
  <span style={{fontSize:'13px',color:'#334155',fontWeight:600}}>Approve</span>
</div>

### 1. Describe what you want

In your MCP client, tell the agent what to build. For example:

<div style={{display:'flex',gap:'12px',margin:'16px 0',alignItems:'flex-start'}}>
  <div style={{flexShrink:0,width:'34px',height:'34px',borderRadius:'999px',background:'#e8f1fb',display:'flex',alignItems:'center',justifyContent:'center',fontSize:'16px'}}>👤</div>
  <div style={{flex:1,background:'#f1f5f9',padding:'12px 16px',borderRadius:'14px',borderTopLeftRadius:'4px',fontStyle:'italic',color:'#334155',lineHeight:1.55,fontSize:'14px'}}>"Build me a customer health scorecard that shows the top 20 accounts by engagement score over the last 90 days, with a sparkline for each."</div>
</div>

### 2. Review the preview

The agent creates an **open** (preview-only) version of the miniapp and gives you a deep link of the form:

`https://app.upside.tech/apps/{mini_app_id}?version_id={version_id}`

Open the link to see what the agent built.

### 3. Iterate

Tell the agent what to adjust — chart type, colors, filters, copy, layout. It updates the open version in place. Refresh the preview after each round and keep going until you're happy.

### 4. Approve and promote

When you're satisfied, ask the agent to seal and promote the version. The miniapp moves from `open` → `sealed` → `active` and becomes visible per its sharing settings.

### Editing an existing miniapp

To update a miniapp that's already live, tell the agent which one to change. It imports the current version into a workspace, applies your changes, and creates a new open version for you to preview before promotion.

### A note on sharing

New miniapps default to `creator_only` — only you can see them until sharing is updated. Ask the agent to grant view/edit access, or update sharing from the miniapp settings.

***

## Path 2: Creating a Miniapp via the In-App Agent

You can also prompt the in-app agent inside the Upside dashboard to build a miniapp for you — describe what you want and the agent will create one that renders in the dashboard, just like the miniapps from Path 1.

<div style={{borderLeft:'4px solid #7a4a9e',background:'#f0e8f5',padding:'14px 18px',borderRadius:'6px',margin:'20px 0'}}>
  <div style={{fontWeight:700,color:'#7a4a9e',marginBottom:'6px',fontSize:'14px'}}>🤖 Learn more about the in-app agent</div>
  <div style={{color:'#5a3578',fontSize:'14px',lineHeight:1.55}}>See the <a href="/docs/in-app-agent" style={{color:'#7a4a9e',fontWeight:600}}>In-App Agent guide</a> for an overview of what it does and how to work with it.</div>
</div>

![](https://files.readme.io/2033d6aaf58b90d9a436b8aa88ee7aaa587a8815aa46357271b34c26f505411f-image.png)

<br />

***

## Lifecycle reference

<div style={{display:'flex',alignItems:'center',gap:'10px',flexWrap:'wrap',margin:'20px 0 16px 0'}}>
  <span style={{display:'inline-block',padding:'6px 14px',borderRadius:'999px',background:'#f1f5f9',color:'#475569',fontWeight:600,fontSize:'13px'}}>draft</span>
  <span style={{color:'#94a3b8',fontWeight:600}}>→</span>
  <span style={{display:'inline-block',padding:'6px 14px',borderRadius:'999px',background:'#d4e4f3',color:'#347BD1',fontWeight:600,fontSize:'13px'}}>open</span>
  <span style={{color:'#94a3b8',fontWeight:600}}>→</span>
  <span style={{display:'inline-block',padding:'6px 14px',borderRadius:'999px',background:'#f9eed8',color:'#a1560b',fontWeight:600,fontSize:'13px'}}>sealed</span>
  <span style={{color:'#94a3b8',fontWeight:600}}>→</span>
  <span style={{display:'inline-block',padding:'6px 14px',borderRadius:'999px',background:'#d8ebde',color:'#2d6a4f',fontWeight:600,fontSize:'13px'}}>active</span>
</div>

<div style={{display:'grid',gridTemplateColumns:'repeat(auto-fit, minmax(160px, 1fr))',gap:'12px',margin:'8px 0 24px 0'}}>
  <div style={{borderTop:'3px solid #94a3b8',padding:'10px 12px',background:'#f8fafc',borderRadius:'6px'}}>
    <div style={{fontWeight:700,color:'#475569',fontSize:'13px',marginBottom:'4px'}}>draft</div>
    <div style={{color:'#64748b',fontSize:'13px',lineHeight:1.4}}>Miniapp entity exists, no version yet.</div>
  </div>

  <div style={{borderTop:'3px solid #347BD1',padding:'10px 12px',background:'#e8f1fb',borderRadius:'6px'}}>
    <div style={{fontWeight:700,color:'#347BD1',fontSize:'13px',marginBottom:'4px'}}>open</div>
    <div style={{color:'#1f4768',fontSize:'13px',lineHeight:1.4}}>Previewable, mutable, iterate freely.</div>
  </div>

  <div style={{borderTop:'3px solid #a1560b',padding:'10px 12px',background:'#f9eed8',borderRadius:'6px'}}>
    <div style={{fontWeight:700,color:'#a1560b',fontSize:'13px',marginBottom:'4px'}}>sealed</div>
    <div style={{color:'#a1560b',fontSize:'13px',lineHeight:1.4}}>Immutable, ready to promote.</div>
  </div>

  <div style={{borderTop:'3px solid #2d6a4f',padding:'10px 12px',background:'#d8ebde',borderRadius:'6px'}}>
    <div style={{fontWeight:700,color:'#2d6a4f',fontSize:'13px',marginBottom:'4px'}}>active</div>
    <div style={{color:'#2d6a4f',fontSize:'13px',lineHeight:1.4}}>Promoted, visible per sharing scope.</div>
  </div>
</div>

## Before you start

You'll need:

* An **MCP client connected to your Upside org** (for Path 1) — e.g., Claude Desktop, Cursor, or Claude Code
* Or access to the **Upside dashboard** (for Path 2)
* **Permission to create miniapps** in your Upside org — ask your team lead if you're not sure