pigeonnest
v0.0.2
Published
A Vue 3 framework for PeerPigeon application development
Maintainers
Readme
PigeonNest
A comprehensive Vue 3 component library and framework for building peer-to-peer applications with PeerPigeon.
Overview
PigeonNest provides Vue 3 composables and components that make it easy to build WebRTC-based peer-to-peer applications using the PeerPigeon protocol. It offers:
- 🎯 Ready-to-use Vue Components - Drop-in UI components for peer connections, file transfers, and status displays
- 🔧 Powerful Composables - Vue 3 composables for mesh networking, streaming (PigeonFS), and distributed storage
- 📦 TypeScript Support - Full TypeScript definitions for type safety
- 🎨 Customizable - Easy to style and extend
- 📡 Real-time - Built on WebRTC for true peer-to-peer communication
Features
Core Composables
- usePeerPigeon - Main mesh network management
- usePeerStreaming - File and data streaming (PigeonFS with readable/writable streams)
- usePeerStorage - Distributed storage across the mesh
UI Components
- PeerConnectionStatus - Display connection status and network information
- PeerList - List and manage connected peers
- FileUpload - Drag-and-drop file upload with multi-file support
- StreamProgress - Real-time progress tracking for file transfers
Installation
npm install pigeonnest vue peerpigeonQuick Start
Basic Setup
<template>
<div>
<PeerConnectionStatus :status="status" :is-connected="isConnected" />
<button @click="initialize">Initialize</button>
<button @click="connect">Connect</button>
<PeerList :peers="connectedPeerIds" @select="handlePeerSelect" />
</div>
</template>
<script setup>
import { usePeerPigeon, PeerConnectionStatus, PeerList } from 'pigeonnest'
const {
status,
isConnected,
connectedPeerIds,
init,
connect
} = usePeerPigeon({
networkName: 'my-app',
maxPeers: 5
})
const initialize = async () => {
await init()
}
const connectToHub = async () => {
await connect('ws://localhost:3000')
}
const handlePeerSelect = (peerId) => {
console.log('Selected peer:', peerId)
}
</script>File Streaming (PigeonFS)
<template>
<div>
<FileUpload @upload="handleUpload" :target-peer-id="selectedPeer" />
<StreamProgress
v-for="stream in activeStreamsArray"
:key="stream.streamId"
:stream="stream"
@cancel="cancelStream"
/>
</div>
</template>
<script setup>
import { usePeerPigeon, usePeerStreaming, FileUpload, StreamProgress } from 'pigeonnest'
import { computed } from 'vue'
const { mesh } = usePeerPigeon()
const {
activeStreams,
sendFile,
receiveStream,
cancelStream
} = usePeerStreaming()
const selectedPeer = ref(null)
const handleUpload = async (files) => {
for (const file of files) {
await sendFile(mesh.value, selectedPeer.value, file)
}
}
const activeStreamsArray = computed(() => Array.from(activeStreams.value.values()))
// Listen for incoming streams
if (mesh.value) {
mesh.value.addEventListener('streamReceived', async (event) => {
const blob = await receiveStream(event)
// Download the file
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = event.metadata.filename
a.click()
})
}
</script>Advanced Streaming (Low-Level API)
Use the low-level streaming API for custom data sources:
<script setup>
import { usePeerPigeon, usePeerStreaming } from 'pigeonnest'
const { mesh } = usePeerPigeon()
const { sendStream, createStreamToPeer } = usePeerStreaming()
// Example 1: Send custom ReadableStream
const sendCustomData = async (peerId) => {
// Create a readable stream from any data source
const stream = new ReadableStream({
async start(controller) {
for (let i = 0; i < 10; i++) {
const data = new TextEncoder().encode(`Chunk ${i}\n`)
controller.enqueue(data)
await new Promise(resolve => setTimeout(resolve, 100))
}
controller.close()
}
})
await sendStream(mesh.value, peerId, stream, {
filename: 'custom-data.txt',
mimeType: 'text/plain',
totalSize: 100
})
}
// Example 2: Use WritableStream for manual control
const sendWithManualControl = async (peerId) => {
const writable = createStreamToPeer(mesh.value, peerId, {
filename: 'manual-data.bin',
totalSize: 1024
})
const writer = writable.getWriter()
try {
await writer.write(new Uint8Array([1, 2, 3, 4]))
await writer.write(new Uint8Array([5, 6, 7, 8]))
await writer.close()
} catch (error) {
await writer.abort(error)
throw error
}
}
</script>Distributed Storage
<template>
<div>
<input v-model="key" placeholder="Key" />
<input v-model="value" placeholder="Value" />
<button @click="saveData">Save</button>
<button @click="loadData">Load</button>
<div v-for="[k, entry] in entries" :key="k">
{{ k }}: {{ entry.value }}
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { usePeerPigeon, usePeerStorage } from 'pigeonnest'
const { mesh } = usePeerPigeon()
const { entries, set, get, list } = usePeerStorage()
const key = ref('')
const value = ref('')
const saveData = async () => {
await set(mesh.value, key.value, value.value)
}
const loadData = async () => {
const data = await get(mesh.value, key.value)
value.value = data
}
</script>API Reference
usePeerPigeon(options)
Main composable for managing the PeerPigeon mesh network.
Options:
peerId(string) - Custom peer IDnetworkName(string) - Network namespace for isolationmaxPeers(number) - Maximum number of peer connectionsminPeers(number) - Minimum number of peer connectionsautoConnect(boolean) - Auto-connect when joining networkautoDiscovery(boolean) - Automatic peer discovery
Returns:
mesh- PeerPigeonMesh instancestatus- Current network statusisConnected- Connection stateisInitialized- Initialization stateconnectedPeerIds- Array of connected peer IDsdiscoveredPeers- Array of discovered peerserror- Last errorinit()- Initialize the meshconnect(url)- Connect to signaling serverdisconnect()- Disconnect from networksendMessage(peerId, message)- Send message to peerbroadcast(message)- Broadcast to all peersrefreshStatus()- Refresh status information
usePeerStreaming()
Composable for handling file and data streaming (PigeonFS) using readable/writable streams.
Returns:
activeStreams- Map of active stream transfersincomingStream- Current incoming streamsendFile(mesh, peerId, file)- Send a File objectsendBlob(mesh, peerId, blob, options)- Send a BlobsendStream(mesh, peerId, stream, options)- Send a ReadableStream (low-level API)createStreamToPeer(mesh, peerId, options)- Create a WritableStream to peer (low-level API)receiveStream(event)- Receive and process a streamcancelStream(streamId)- Cancel an active stream
usePeerStorage()
Composable for distributed storage management.
Returns:
entries- Map of storage entriesloading- Loading stateerror- Last errorset(mesh, key, value, ttl)- Store a valueget(mesh, key)- Retrieve a valuehas(mesh, key)- Check if key existsdelete(mesh, key)- Delete a valueclear(mesh)- Clear all storagelist(mesh)- List all keysrefreshEntries(mesh)- Refresh all entries
Components
PeerConnectionStatus
Displays current connection status and network information.
Props:
status(PeerStatus | null) - Current peer statusisConnected(boolean) - Connection state
PeerList
List and manage connected peers.
Props:
peers(Array) - Array of peers or peer IDstitle(string) - List titleemptyMessage(string) - Message when no peersshowTimestamp(boolean) - Show connection timeshowActions(boolean) - Show action buttonsselectedPeerId(string) - Currently selected peer
Events:
@select- Peer selected@message- Send message clicked@file- Send file clicked
FileUpload
Drag-and-drop file upload component.
Props:
multiple(boolean) - Allow multiple filesaccept(string) - Accepted file typestargetPeerId(string) - Target peer for uploadprimaryText(string) - Primary instruction textsecondaryText(string) - Secondary instruction text
Events:
@upload- Files ready to upload@change- File selection changed
StreamProgress
Display progress of file transfers.
Props:
stream(StreamProgress) - Stream progress objectonCancel(boolean) - Show cancel buttononRetry(boolean) - Show retry buttononDismiss(boolean) - Show dismiss button
Events:
@cancel- Cancel transfer@retry- Retry transfer@dismiss- Dismiss completed transfer
Examples
See the examples/ directory for complete examples:
- demo.html - Complete demo application showing all features
To run the demo:
# Start a PeerPigeon signaling server
npx peerpigeon hub
# In another terminal, serve the examples
npm run dev
# Open http://localhost:5173/examples/demo.html in multiple browser tabsPeerPigeon Integration
PigeonNest is built on top of PeerPigeon 1.0.5. Key concepts:
- PigeonHub - Signaling server for peer discovery (WebSocket-based)
- PigeonFS - File system operations using readable/writable streams
- Mesh Network - WebRTC-based peer-to-peer connections
- Distributed Storage - Shared storage across peers with CRDTs
Browser Support
Requires browsers with:
- WebRTC support
- Web Streams API
- ES2020+
Tested on:
- Chrome 89+
- Firefox 102+
- Safari 14.1+
- Edge 89+
Development
# Install dependencies
npm install
# Run dev server
npm run dev
# Build library
npm run build
# Run tests
npm testContributing
Contributions are welcome! Please read our contributing guidelines before submitting PRs.
License
MIT © PeerPigeon Contributors
Links
Support
For issues and questions:
