npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@pkme/widget-bridge

v1.0.17

Published

TypeScript React bridge client for Secret City Games widget integration across Framer, Figma, and web platforms

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-bridge

Quick 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/testing

TypeScript 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

Repository

secret-city-go