@pkme/widget-bridge
v1.0.17
Published
TypeScript React bridge client for Secret City Games widget integration across Framer, Figma, and web platforms
Maintainers
Readme
@pkme/widget-bridge
A TypeScript React bridge client for Secret City Games widget integration across Framer, Figma, and web platforms.
Installation
No installation needed for Framer or Figma! Both platforms auto-resolve npm packages.
For other environments:
npm install @pkme/widget-bridgeQuick Start
React Hooks (Framer, React apps)
import React from "react"
import { useBridgeData } from "@pkme/widget-bridge"
interface GlobalData {
playerName?: string
theme?: 'light' | 'dark'
totalScore?: number
}
interface CardData {
progress?: number
completed?: boolean
}
function MyWidget() {
const {
globalData,
itemData,
setGlobal,
setItem,
navigate,
complete,
isReady
} = useBridgeData<GlobalData, CardData>()
if (!isReady) {
return <div>Connecting to Secret City Games...</div>
}
return (
<div>
<h1>Player: {globalData?.playerName}</h1>
<p>Progress: {itemData?.progress || 0}%</p>
<button onClick={() => setItem({ progress: 50 })}>
Update Progress
</button>
<button onClick={() => complete({ score: 100 })}>
Complete Card
</button>
</div>
)
}Vanilla JavaScript (Figma plugins, vanilla web)
import { bridge } from "@pkme/widget-bridge"
// Wait for bridge to be ready
await bridge.ready()
console.log('Connected to Secret City Games!')
// Set up data subscriptions
bridge.subscribeGlobal((globalData) => {
console.log('Global data updated:', globalData)
})
bridge.subscribeItem((itemData) => {
console.log('Item data updated:', itemData)
})
// Update data
await bridge.setGlobal({ playerName: 'Alice' })
await bridge.setItem({ progress: 75 })
// Navigate
await bridge.navigate('/next-card')
await bridge.complete({ score: 100 })Import Options
For Framer (Immediate Availability)
Use CDN import for immediate availability in Framer:
import { useBridgeData } from "https://unpkg.com/@pkme/[email protected]/dist/index.esm.js"
import { bridge } from "https://unpkg.com/@pkme/[email protected]/dist/index.esm.js"Alternative CDN Imports
// jsDelivr CDN (reliable alternative)
import { useBridgeData } from "https://cdn.jsdelivr.net/npm/@pkme/[email protected]/dist/index.esm.js"
// Standard npm import (works once JSPM indexes - may take 24hrs)
import { useBridgeData, bridge } from "@pkme/widget-bridge"
// JSPM CDN (once indexed)
import { useBridgeData } from "https://jspm.dev/@pkme/[email protected]"Note: Use unpkg or jsDelivr CDNs for immediate availability. These serve the exact files from npm without transformation, avoiding compatibility issues with esm.sh.
Core Features
- 🔄 Real-time data sync between widgets and Secret City Games app
- 🎯 Global & Item data - shared vs card-specific state
- 🚀 Navigation - seamless routing between game cards
- 🛡️ Loop prevention - optimistic updates without recursion
- 📱 Cross-platform - Framer, Figma, React Native WebView, iframe
- 🔧 TypeScript - full type safety included
React Hooks
useBridgeData<TGlobal, TItem>()
Complete integration with global and item data plus navigation:
const {
globalData, // Shared across all cards
itemData, // Current card only
setGlobal, // Update shared data
setItem, // Update current card
navigate, // Navigate to other cards
complete, // Mark card complete
back, // Go back
isReady, // Connection status
context, // { sessionId, gameId, viewId }
environment // 'expo' | 'iframe' | 'standalone'
} = useBridgeData<GlobalData, CardData>()useBridge()
Access bridge instance and status:
const { bridge, isReady, context, environment } = useBridge()useGlobalData<T>()
Manage global game state:
const [globalData, setGlobalData] = useGlobalData<MyGlobalType>()useItemData<T>()
Manage card-specific data:
const [itemData, setItemData] = useItemData<MyItemType>()Bridge Methods
Data Operations
// Current card data
await bridge.setItem({ progress: 50 })
bridge.subscribeItem((data) => console.log('Item updated:', data))
// Specific card data
await bridge.setItemById('card-123', { completed: true })
bridge.subscribeItemById('card-123', (data) => console.log('Card 123:', data))
// Global data (shared)
await bridge.setGlobal({ playerName: 'Alice' })
bridge.subscribeGlobal((data) => console.log('Global:', data))Navigation
// Navigate to another card
await bridge.navigate('/games/puzzle/cards/level-2', {
title: 'Level 2',
difficulty: 'medium'
})
// Go back
await bridge.back()
// Complete current card
await bridge.complete({
score: 100,
timeSpent: 120
})Utility Functions
import {
navigateToNextCard,
completeCard,
navigateToCard,
savePuzzleProgress,
updateGlobalGameState
} from "@pkme/widget-bridge"
// Navigate to next card with completion
await navigateToNextCard({ completed: true, score: 100 })
// Complete current card
await completeCard({ score: 100, timeSpent: 120 })
// Navigate to specific card
await navigateToCard('level-2', { difficulty: 'medium' })
// Save progress
await savePuzzleProgress(0.75, { hintsUsed: 2 })
// Update global state
await updateGlobalGameState({ currentLevel: 3 })Static Assets
The package includes game utilities:
import { VALID_WORDS, isValidWord } from "@pkme/widget-bridge/assets/games/wordle-words"
// Validate 5-letter words (2,343 valid words)
if (!isValidWord(userGuess)) {
showError("Not a valid word")
}
// Get random word
const randomWord = VALID_WORDS[Math.floor(Math.random() * VALID_WORDS.length)]Examples
Framer Component
See /examples/framer/PuzzleWidget.tsx for a complete interactive Framer component.
Figma Plugin
See /examples/figma/puzzle-plugin.ts for a complete Figma plugin example.
Environment Detection
The bridge automatically detects the runtime environment:
console.log('Environment:', bridge.environment)
// 'expo' - React Native WebView (Secret City Games app)
// 'iframe' - Web iframe
// 'standalone' - Development/testingTypeScript Support
Full type definitions included:
import type {
BridgeInstance,
BridgeContext,
BridgeMessage,
UseBridgeReturn,
UseBridgeDataReturn
} from "@pkme/widget-bridge"
interface MyGlobalData {
playerName: string
theme: 'light' | 'dark'
}
interface MyCardData {
progress: number
completed: boolean
}
const {
globalData,
itemData
} = useBridgeData<MyGlobalData, MyCardData>()Browser Bundle
For vanilla HTML/JS:
<script src="https://unpkg.com/@pkme/widget-bridge/dist/browser.js"></script>
<script>
const { bridge } = window.SecretCityBridge
bridge.ready().then(() => {
console.log('Bridge ready!')
bridge.setGlobal({ test: true })
})
</script>Requirements
- React >=16.8.0 (for React hooks)
- Node.js >=14.0.0 (for development)
- TypeScript (optional but recommended)
License
MIT License
