Files
p2ns/plugin-sites/global.profile
2026-05-28 01:46:38 -04:00
..
2025-12-17 20:05:50 -05:00
2026-05-28 00:26:32 -04:00
2025-12-17 20:05:50 -05:00
2026-05-28 01:46:38 -04:00
2025-12-17 20:05:50 -05:00
2025-12-17 20:05:50 -05:00
2025-12-17 20:05:50 -05:00
2025-12-17 20:05:50 -05:00

Global Profile Plugin

Status: Production Ready

The Global Profile plugin provides a universal user identity system for all P2NS plugins with automatic P2P profile replication. It enables users to create, manage, and share their profiles across the entire P2NS network, with real-time updates and seamless integration with other plugins.

Overview

Global Profile is a core identity plugin that stores user profile data in a distributed HyperDB database that automatically replicates across all connected peers. Your profile is available to all P2NS plugins, enabling a unified identity experience across the network.

Key Features

Core Functionality

  • HyperDB-Backed Storage: All profile data is stored in HyperDB with automatic P2P replication across the network
  • Multi-Size Avatar System: Avatars are automatically resized and stored in multiple sizes (16px, 32px, 64px, 128px, 256px, 512px) for optimal performance
  • Real-Time Updates: Profile changes are broadcast in real-time via WebSocket to all connected clients and peers
  • Extensible Field System: Plugins can register custom fields that extend the standard profile schema
  • Cross-Plugin Integration: Profile data is accessible to all P2NS plugins through the unified API
  • Web UI: Complete web interface for managing your profile with an intuitive, modern design

Profile Fields

The plugin supports the following standard profile fields:

  • peerId - Unique identifier for the peer (required, automatically set)
  • displayName - User's display name
  • bio - Biography/about text
  • email - Email address
  • website - Personal or professional website URL
  • xUsername - X (Twitter) username
  • github - GitHub username
  • discord - Discord username
  • location - Physical location
  • avatarHash - Hash of the current avatar image
  • tags - Array of user-defined tags
  • customFields - Object for plugin-specific custom fields
  • lastUpdated - Timestamp of last profile update

Profile Management Features

  • Search & Filter: Search profiles by display name or bio, filter by tags
  • Pagination: Efficient pagination with configurable limits (1-1000 per page)
  • Sorting: Sort profiles by last updated (newest first) or display name (alphabetical)
  • Online Status: Real-time online/offline status for each peer
  • Statistics: Network-wide statistics including total profiles, online counts, and recent activity

Architecture

Storage

  • HyperDB: All profile data and avatars are stored in HyperDB using base64-encoded data for avatars
    • Profile collection (@profile/profiles): Stores all user profile data
    • Avatar collection (@profile/avatars): Stores avatar images in multiple sizes
    • Fields collection (@profile/fields): Stores custom field definitions registered by plugins

Replication

  • Automatic P2P Replication: All data automatically replicates across all connected peers using the global replication topic
  • Database Watching: Real-time database change detection broadcasts updates immediately
  • Peer Connection Handling: Profile updates are triggered when peers connect or disconnect

Real-Time Communication

  • WebSocket Server: Provides real-time updates to connected clients
    • profile-update: Broadcast when a profile is created or updated
    • profile-deleted: Broadcast when a profile is deleted
    • replication-status: Periodic updates about replication status
  • P2P Channels: Uses P2NS channels to broadcast profile updates across the network

Web Interface

The plugin includes a complete web interface accessible at the plugin domain root (/). The interface provides:

  • Profile editing form with all standard fields
  • Avatar upload with preview
  • Tag management with inline editing
  • Real-time profile listing with search
  • Online/offline status indicators
  • Connection status monitoring

API Reference

The plugin provides a comprehensive REST API. For interactive documentation with examples and curl commands, visit /api/docs when the plugin is enabled.

Profile Management

Get Your Profile

GET /api/profile

Returns your local profile. Returns a default empty profile if none exists.

Update Your Profile (Full)

PUT /api/profile
Content-Type: application/json

{
  "displayName": "John Doe",
  "bio": "Software developer",
  "website": "https://example.com",
  "email": "[email protected]",
  "xUsername": "@johndoe",
  "github": "johndoe",
  "discord": "johndoe#1234",
  "location": "San Francisco, CA",
  "tags": ["developer", "opensource"],
  "customFields": {}
}

Performs a full update of your profile. All fields must be provided.

Partially Update Your Profile

PATCH /api/profile
Content-Type: application/json

{
  "displayName": "John Doe",
  "bio": "Updated bio"
}

Updates only the provided fields. Fields not included remain unchanged.

Get Another Peer's Profile

GET /api/profile/:peerId

Returns the profile for the specified peer ID. Returns 404 if not found.

Delete Your Profile

DELETE /api/profile

Deletes your profile and all associated avatars.

Profile Listing

List All Profiles

GET /api/profiles?search=query&tag=tagName&limit=100&offset=0&sort=lastUpdated

Query Parameters:

  • search (optional): Search term to filter by displayName or bio (case-insensitive)
  • tag (optional): Filter profiles that have this tag
  • limit (optional): Maximum number of results (1-1000, default: 100)
  • offset (optional): Number of results to skip for pagination (default: 0)
  • sort (optional): Sort field - lastUpdated (default, newest first) or displayName (alphabetical)

Response:

{
  "profiles": [
    {
      "peerId": "...",
      "displayName": "John Doe",
      "bio": "...",
      "online": true,
      "tags": ["developer"],
      "customFields": {},
      "lastUpdated": 1234567890
    }
  ],
  "pagination": {
    "total": 150,
    "limit": 100,
    "offset": 0,
    "hasMore": true
  }
}

Avatar Management

Upload Avatar

POST /api/profile/avatar
Content-Type: multipart/form-data

avatar: <image file>

Uploads an avatar image. The image is automatically resized to all supported sizes (16px, 32px, 64px, 128px, 256px, 512px) and stored in HyperDB. Requires the sharp library for image processing.

Response:

{
  "success": true,
  "avatarHash": "md5_hash_of_image"
}

Get Avatar (Default Size)

GET /api/profile/avatar/:peerId

Redirects to the 64px avatar endpoint.

Get Avatar (Specific Size)

GET /api/profile/avatar/:peerId/:size

Returns the avatar image at the specified size. Valid sizes: 16, 32, 64, 128, 256, 512.

If no avatar exists, returns a default SVG placeholder with the first character of the peer ID.

Delete Avatar

DELETE /api/profile/avatar

Deletes all avatar sizes for your profile.

Custom Fields

Get All Registered Fields

GET /api/fields

Returns all custom fields registered by plugins.

Response:

{
  "fields": [
    {
      "fieldKey": "favoriteColor",
      "registeredBy": "example.plugin",
      "label": "Favorite Color",
      "type": "string",
      "description": "User's favorite color",
      "defaultValue": "blue"
    }
  ]
}

Register a Custom Field

POST /api/fields
Content-Type: application/json

{
  "fieldKey": "favoriteColor",
  "label": "Favorite Color",
  "type": "string",
  "description": "User's favorite color",
  "defaultValue": "blue"
}

Required Fields:

  • fieldKey: Unique identifier for the field (string)
  • label: Human-readable label (string)
  • type: Field type - one of: string, number, boolean, array, object

Optional Fields:

  • description: Field description (string)
  • defaultValue: Default value (any JSON-serializable value)

Note: Custom fields are stored in the customFields object in the profile. Plugins should register their fields on initialization to ensure proper validation and documentation.

Statistics

Get Profile Statistics

GET /api/stats

Response:

{
  "total": 150,
  "online": 45,
  "offline": 105,
  "recentActivity": [
    {
      "peerId": "...",
      "displayName": "John Doe",
      "hoursAgo": 2.5
    }
  ],
  "timestamp": 1234567890
}

Returns:

  • Total number of profiles in the network
  • Count of online vs offline peers
  • Recent activity (profiles updated in the last 24 hours, limited to top 10)

Documentation

Interactive API Documentation

GET /api/docs

Returns an interactive HTML page with complete API documentation, including examples and curl commands for each endpoint.

WebSocket API

The plugin provides WebSocket endpoints for real-time updates. Connect to the WebSocket server to receive:

Message Types

profile-update

Broadcast when a profile is created or updated.

{
  "type": "profile-update",
  "profile": {
    "peerId": "...",
    "displayName": "John Doe",
    ...
  },
  "timestamp": 1234567890
}

profile-deleted

Broadcast when a profile is deleted.

{
  "type": "profile-deleted",
  "peerId": "...",
  "timestamp": 1234567890
}

replication-status

Periodic updates about replication status (every 2 seconds when status changes).

{
  "type": "replication-status",
  "data": {
    "hyperdb": {
      "active": true,
      "peers": 5
    }
  },
  "timestamp": 1234567890
}

Client Messages

request-profiles

Request all profiles (for backward compatibility; use REST API /api/profiles instead).

{
  "type": "request-profiles"
}

request-replication-status

Request current replication status.

{
  "type": "request-replication-status"
}

Configuration

The plugin is enabled by default. Configuration is managed through config.json:

{
  "name": "Global Profile",
  "version": "1.1.0",
  "domain": "global.profile",
  "enabled": true,
  "description": "Universal user identity system for all P2NS plugins with P2P profile replication"
}

Enabling/Disabling

The plugin can be enabled or disabled through:

  1. Admin Panel: Navigate to the Plugins tab and toggle the Global Profile plugin status
  2. Manual Configuration: Edit plugin-sites/global.profile/config.json and change "enabled" to true or false, then restart P2NS

Dependencies

Required

  • P2NS core with HyperDB support
  • Sharp library for avatar image processing: npm install sharp

Note: If Sharp is not installed, avatar upload will fail with an error message. The plugin will function normally for all other features.

Database Schema

The plugin uses HyperDB with the following schema:

Profile Schema

  • peerId (string, required): Unique peer identifier (primary key)
  • displayName (string): Display name
  • bio (string): Biography
  • website (string): Website URL
  • email (string): Email address
  • xUsername (string): X/Twitter username
  • github (string): GitHub username
  • discord (string): Discord username
  • location (string): Location
  • avatarHash (string): Avatar hash
  • customFields (string): JSON-encoded object for custom fields
  • tags (string): JSON-encoded array of tags
  • lastUpdated (uint): Timestamp of last update

Avatar Schema

  • peerId (string, required): Peer identifier (part of composite key)
  • size (string, required): Size identifier - one of: "16", "32", "64", "128", "256", "512", "original" (part of composite key)
  • data (string, required): Base64-encoded image data

Field Definition Schema

  • fieldKey (string, required): Unique field key (primary key)
  • registeredBy (string, required): Plugin domain that registered the field
  • label (string): Human-readable label
  • type (string): Field type
  • description (string): Field description
  • defaultValue (string): JSON-encoded default value

Indexes

  • profiles-by-displayName: Case-insensitive search on displayName

Plugin Integration

Other P2NS plugins can integrate with Global Profile in several ways:

Reading Profile Data

Plugins can fetch profile data using the REST API:

// Get a specific peer's profile
const profile = await fetch(`https://global.profile/api/profile/${peerId}`);
const data = await profile.json();

// Access standard fields
console.log(data.displayName, data.bio, data.avatarHash);

// Access custom fields
console.log(data.customFields.myCustomField);

Registering Custom Fields

Plugins can extend the profile schema by registering custom fields:

// Register a custom field on plugin initialization
await fetch('https://global.profile/api/fields', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    fieldKey: 'myCustomField',
    label: 'My Custom Field',
    type: 'string',
    description: 'Description of my custom field',
    defaultValue: 'default'
  })
});

Using Avatars

Avatars can be accessed via URL:

<!-- Default size (64px) -->
<img src="https://global.profile/api/profile/avatar/PEER_ID">

<!-- Specific size -->
<img src="https://global.profile/api/profile/avatar/PEER_ID/128">

WebSocket Integration

Plugins can connect to the WebSocket server to receive real-time profile updates:

const ws = new WebSocket('wss://global.profile/ws');
ws.onmessage = (event) => {
  const message = JSON.parse(event.data);
  if (message.type === 'profile-update') {
    // Handle profile update
    console.log('Profile updated:', message.profile);
  }
};

Performance Considerations

  • Avatar Sizes: Avatars are pre-generated in multiple sizes to avoid on-the-fly resizing
  • Database Indexes: Indexes on displayName and tags enable efficient searching
  • Pagination: Profile listings use pagination to handle large networks efficiently
  • Caching: Avatar endpoints include cache headers for optimal performance
  • Base64 Storage: Avatars are stored as base64 in HyperDB for seamless replication

Troubleshooting

Avatar Upload Fails

  • Ensure the sharp library is installed: npm install sharp
  • Check that the uploaded file is a valid image format
  • Verify file size is reasonable (large files may take time to process)

Profile Updates Not Replicating

  • Verify that database replication is active (check /api/stats or WebSocket replication-status)
  • Ensure peers are connected and replication is enabled in P2NS
  • Check logs for replication errors

Database Not Ready Errors

  • The plugin waits up to 30 seconds for database initialization on startup
  • If errors persist, restart P2NS to re-initialize the database
  • Check that HyperDB is properly configured in P2NS

License

MIT