Joseph Carothers
← All projects

React · TypeScript

Page Lock - React Ownership Management Library

A React ownership-management library that prevents conflicting edits in collaborative product workflows.

Live demo ↗GitHub ↗Sun Jan 26 2025 · 4 min read
My role
Library author
Focus
Type-safe React hooks, ownership state, storage adapters, and ready-to-use UI components.
Stack
ReactJSJavascriptTypescript
ImpactDemonstrates reusable product infrastructure for teams that need safer collaborative editing flows.
Page Lock - React Ownership Management Library cover

Page Lock - React Ownership Management Library

Page Lock is a React library I built to solve a common problem in collaborative web applications: preventing multiple users from editing the same content simultaneously. It provides elegant, real-time page ownership management with built-in UI components and hooks.

The Problem

In collaborative applications, when multiple users try to edit the same record or page simultaneously, you get:

  • Data conflicts - Last save wins, losing other users' work
  • User confusion - People don't know someone else is editing
  • Wasted effort - Duplicate work that gets overwritten

Traditional solutions are either too complex or don't provide good UX.

The Solution

Page Lock provides a simple, elegant solution with:

🔐 Real-time ownership tracking - Know who's editing what, when
🔄 Automatic ownership transfer - Seamless handoffs between users
🎨 Beautiful UI components - Ready-to-use badges and modals
📱 Mobile-friendly design - Works great on all devices
🎯 TypeScript support - Full type safety out of the box
🚀 Framework agnostic - Works with Next.js, Create React App, etc.

Live Demo

PageLock Demo

localhost:3000
A
Alice
alice@example.com

Records

Important Document

ID: 1

This is a very important document that needs careful coordination when editing. It contains sensitive information that should be managed carefully to avoid conflicts.

Project Roadmap

ID: 2

Our project roadmap details the upcoming features and milestones. The next quarter focuses on improving user experience and adding real-time collaboration features.

Meeting Notes

ID: 3

Notes from our last team meeting discussing the new features. We covered the implementation timeline, resource allocation, and potential challenges we need to address.
localhost:3000
B
Bob
bob@example.com

Records

Important Document

ID: 1

This is a very important document that needs careful coordination when editing. It contains sensitive information that should be managed carefully to avoid conflicts.

Project Roadmap

ID: 2

Our project roadmap details the upcoming features and milestones. The next quarter focuses on improving user experience and adding real-time collaboration features.

Meeting Notes

ID: 3

Notes from our last team meeting discussing the new features. We covered the implementation timeline, resource allocation, and potential challenges we need to address.
PageLock Console
Local Storage Data:

Key Features

🔒 Flexible Locking Strategies

// Lock entire pages
const { lockPage, unlockPage } = usePageOwnership({ 
  pageId: 'user-profile-123' 
});

// Lock specific components
<OwnershipModal pageId="document-editor-456" />

// Just show ownership status
<OwnerBadge pageId="settings-panel-789" />

🌐 Multiple Storage Adapters

// Use localStorage for simple cases
const adapter = createLocalStorageAdapter({
  prefix: 'my-app'
});

// Use your API for production
const adapter = createApiStorageAdapter({
  getAllOwners: () => fetch('/api/owners').then(r => r.json()),
  lockPage: (pageId, userId, userName) => 
    fetch('/api/lock', { method: 'POST', body: JSON.stringify({pageId, userId, userName}) }),
  unlockPage: (pageId, userId) => 
    fetch('/api/unlock', { method: 'POST', body: JSON.stringify({pageId, userId}) }),
  takePageOwnership: (pageId, userId, userName) => 
    fetch('/api/take-ownership', { method: 'POST', body: JSON.stringify({pageId, userId, userName}) })
});

⚡ Real-time Updates

The library polls for ownership changes at configurable intervals (default 3 seconds), ensuring all users see locks and releases immediately. No websockets required!

Technical Architecture

Core Components

ComponentPurposeUse Case
OwnershipProviderContext provider for ownership stateWrap your app or specific sections
usePageOwnershipHook for programmatic controlCustom implementations
OwnerBadgeSimple ownership indicatorShow who owns what
OwnershipModalFull ownership management UIComplete lock/unlock flow

Type Safety

interface PageOwner {
  user_id: string;
  user_name: string;
  page_id: string;
  timestamp: number;
}

interface OwnershipConfig {
  userAdapter: UserAdapter;
  ownershipAdapter: OwnershipAdapter;
  options?: {
    pollingInterval?: number;
  };
}

Real-World Use Cases

1. CRM Record Editing

Prevent sales reps from simultaneously editing the same customer record, avoiding data loss and confusion.

2. Document Collaboration

Lock document sections while users are editing, similar to Google Docs but for React applications.

3. Configuration Management

Ensure only one admin can modify system settings at a time, preventing conflicting changes.

4. Form Workflows

Lock multi-step forms to prevent multiple submissions or conflicting edits during long workflows.

Installation & Quick Start

npm install @joecarot/page-lock
# or
yarn add @joecarot/page-lock

Basic Implementation

import {
  OwnershipProvider,
  createLocalStorageAdapter,
  OwnerBadge
} from '@joecarot/page-lock';

// Setup adapters
const userAdapter = {
  getCurrentUser: () => Promise.resolve({
    id: 'user-123',
    email: 'user@example.com',
    name: 'John Doe'
  })
};

const ownershipAdapter = createLocalStorageAdapter({
  prefix: 'my-app'
});

const config = {
  userAdapter,
  ownershipAdapter,
  options: {
    pollingInterval: 3000
  }
};

// Use in your app
function App() {
  return (
    <OwnershipProvider config={config}>
      <div>
        <h1>User Profile</h1>
        <OwnerBadge pageId="user-profile-123" />
        {/* Your form content */}
      </div>
    </OwnershipProvider>
  );
}

Development Process

Built with Modern Tools

  • TypeScript for type safety and better DX
  • Jest for comprehensive testing
  • GitHub Actions for CI/CD
  • tsup for efficient bundling
  • Tailwind CSS for styling

Testing Strategy

# Run tests
npm test

# Coverage report
npm run coverage

# Run example
cd example && npm start

The library includes extensive unit tests covering:

  • Ownership state management
  • Real-time polling behavior
  • Error handling scenarios
  • Component rendering states

Performance Considerations

Optimized Polling

  • Smart intervals: Only polls when components are mounted
  • Efficient updates: Uses React's built-in state management
  • Memory cleanup: Automatic cleanup on unmount

Bundle Size

The library is designed to be lightweight:

  • Tree-shakeable exports
  • Minimal dependencies
  • Efficient TypeScript compilation

Future Enhancements

Planned Features

🔄 WebSocket Support - Real-time updates without polling
🎭 Role-based Permissions - Different lock types for different user roles
🔌 More Adapters - Redis, PostgreSQL, MongoDB adapters
📊 Analytics - Usage tracking and ownership metrics
🎨 Theme Customization - More styling options

Contributing

The project is open source and welcomes contributions! Check out the GitHub repository for:

  • 📋 Issue tracking
  • 🔄 Pull request guidelines
  • 📖 Development setup
  • 🧪 Testing instructions

Lessons Learned

Building this library taught me about:

API Design

Creating intuitive APIs that are both simple for basic use cases and flexible for complex scenarios.

State Management

Handling real-time state synchronization across multiple components and user sessions.

Library Distribution

Packaging, versioning, and distributing a TypeScript library with proper type definitions.

User Experience

Balancing functionality with simplicity - making complex ownership logic feel natural.


Page Lock solves a real problem that many collaborative applications face. By providing simple, elegant ownership management, it helps teams build better collaborative experiences without the complexity of traditional solutions.

Try it out in your next project - I'd love to hear how it works for you!

📦 npm package | 📚 GitHub repository | 🎯 Live example