A cross-platform mini app framework for building web3 widgets that run inside wallets and dapps.
| Package | Description |
|---|---|
@goodwidget/core | EIP-1193 provider normalization, host detection, wallet hooks, React context |
@goodwidget/ui | Tamagui-based themeable component library (React + React Native Web) |
@goodwidget/embed | Web Component wrapper for embedding mini apps in any HTML page |
@goodwidget/claim-widget | Sample publishable widget — React component + Web Component |
@goodwidget/goodreserve-widget | Reserve swap widget package (buy/sell flow on Celo/XDC) |
pnpm install
pnpm run build# React web demo with style override showcasecd examples/react-web && pnpm run dev
# Plain HTML page using the claim widget as a web componentcd examples/html && pnpm run dev
# Expo (React Native) — standalone, see examples/expo/README.mdimport{GoodWidgetProvider,useWallet}from'@goodwidget/core'import{MiniAppShell,Card,Heading,Text,Button,ButtonText}from'@goodwidget/ui'functionMyApp(){const{ address, connect }=useWallet()return(<MiniAppShelltitle="My Mini App"><Card><Headinglevel={4}>Welcome</Heading><Text>{address??'Not connected'}</Text><ButtononPress={connect}fullWidth><ButtonText>Connect</ButtonText></Button></Card></MiniAppShell>)}exportdefaultfunctionApp({ provider, themeOverrides }){return(<GoodWidgetProviderprovider={provider}themeOverrides={themeOverrides}><MyApp/></GoodWidgetProvider>)}import{createGoodWidgetConfig}from'@goodwidget/ui'constconfig=createGoodWidgetConfig({tokens: {color: {primary: '#7B61FF'}},themes: {light_Button: {background: '#7B61FF'}},})<GoodWidgetProviderconfig={config}>...</GoodWidgetProvider><ThirdPartyAppprovider={myWallet}themeOverrides={{tokens: {color: {primary: '#FF6B00'}},themes: {light_GlassCard: {background: '#FFF3E0'}},}}/>good-miniapp {
--gw-color-primary:#ff6b00;
--gw-Card-background:#fff3e0;
--gw-Button-background:#ff6b00;
}import{createMiniAppElement}from'@goodwidget/embed'import{MyApp}from'./MyApp'constElement=createMiniAppElement(MyApp,{shadow: true,props: {chainId: 'attribute'},events: ['transaction-sent'],})customElements.define('my-miniapp',Element)<my-miniappchain-id="42220"></my-miniapp><script>constel=document.querySelector('my-miniapp')el.provider=window.ethereumel.themeOverrides={tokens: {color: {primary: '#7B61FF'}}}</script>Use createComponent() to ensure your components are theme-overridable by hosts:
import{createComponent,Card}from'@goodwidget/ui'exportconstGlassCard=createComponent(Card,{name: 'GlassCard',// Required — enables theme targetingbackgroundColor: 'rgba(255,255,255,0.1)',variants: {elevated: {true: {shadowRadius: 20},},}asconst,})// Hosts can now override via:// themeOverrides: { themes: { light_GlassCard: { background: '...' }}}// or CSS: --gw-GlassCard-background: ...;GoodWidget auto-detects and normalizes providers from:
- Farcaster — via
sdk.wallet.getEthereumProvider() - MiniPay (Celo) — via
window.ethereumwithisMiniPayflag - World App — via MiniKit bridge
- Any EIP-1193 wallet — via
window.ethereumor explicit provider prop
See docs/PACKAGING.md for the full guide on how to build, bundle, and publish your widget as an npm package that works in React, React Native, and plain HTML.
See docs/widget-author-instructions.md for the practical design-system workflow for new widgets and widget-local components.
See docs/qa-guide.md.
GoodWidget/
packages/
core/ → @goodwidget/core (provider, hooks, EIP-1193, host detection)
ui/ → @goodwidget/ui (component library, theme system)
embed/ → @goodwidget/embed (Web Component wrapper)
claim-widget/ → @goodwidget/claim-widget (sample publishable widget)
goodreserve-widget/ → @goodwidget/goodreserve-widget (reserve swap widget)
examples/
react-web/ → React demo with style override showcase
html/ → Plain HTML consuming a web component widget
expo/ → Expo (React Native) app (standalone)
docs/
PACKAGING.md → How to package & distribute your widget
See ARCHITECTURE.md for detailed design decisions and conventions.