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

@tfw.in/structura-lib

v0.2.0

Published

Structura Library Components

Readme

Structura Library

A React component library for viewing and editing structured documents with PDF rendering and persistent storage.

Features

  • 📄 PDF Viewer - Side-by-side PDF and structured content view
  • ✏️ Inline Editing - Double-click to edit any text element
  • 💾 Persistent Storage - Automatic save to SQLite database
  • 🔄 Version History - Track all edits with timestamps
  • 🎯 Bidirectional Mapping - Click highlighting between PDF and content
  • 📦 Production Ready - Zero configuration, auto-initialization

Installation

npm install @tfw.in/structura-lib

Quick Start

1. Basic Usage

import { Structura } from '@tfw.in/structura-lib';
import '@tfw.in/structura-lib/dist/esm/styles.css';

function App() {
  return (
    <Structura
      initialPdfPath="/document.pdf"
      initialJsonData={jsonData}
      props={{
        APIKey: "your-api-key",
        onSave: (editedData) => {
          console.log('Document saved:', editedData);
        }
      }}
    />
  );
}

2. With Backend Storage

import { Structura } from '@tfw.in/structura-lib';
import '@tfw.in/structura-lib/dist/esm/styles.css';

function App() {
  const [jsonData, setJsonData] = useState(null);

  const handleSave = async (editedData) => {
    const response = await fetch('http://localhost:3002/api/save', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        pdfName: 'document.pdf',
        editedJson: editedData,
        originalJson: jsonData // Only on first save
      })
    });

    const result = await response.json();
    console.log('Saved:', result);
  };

  return (
    <Structura
      initialPdfPath="/document.pdf"
      initialJsonData={jsonData}
      props={{
        APIKey: "your-api-key",
        onSave: handleSave
      }}
    />
  );
}

Props

Structura Component

| Prop | Type | Required | Description | |------|------|----------|-------------| | initialPdfPath | string \| null | No | URL or path to PDF file | | initialJsonData | any \| null | No | Pre-loaded JSON data (bypasses API call) | | props.APIKey | string | Yes | Structura API key for processing | | props.baseUrl | string | No | Custom API base URL | | props.onSave | (data: any) => void \| Promise<void> | No | Callback when user saves edits |

Backend Server (Optional)

The library includes an Express server for persistent storage.

Start the Server

cd node_modules/@tfw.in/structura-lib
npm run server

Server runs on http://localhost:3002

API Endpoints

POST /api/save

Save edited document.

curl -X POST http://localhost:3002/api/save \
  -H "Content-Type: application/json" \
  -d '{
    "pdfName": "document.pdf",
    "editedJson": {...},
    "originalJson": {...}
  }'

GET /api/load/:pdfName

Load document with latest edit.

curl http://localhost:3002/api/load/document.pdf

GET /api/history/:pdfName

Get full edit history.

curl http://localhost:3002/api/history/document.pdf

Usage Patterns

Pattern 1: Database-First Loading

useEffect(() => {
  const pdfName = 'document.pdf';

  // Try database first
  fetch(`http://localhost:3002/api/load/${pdfName}`)
    .then(res => res.json())
    .then(result => {
      setJsonData(result.document.currentJson);
    })
    .catch(() => {
      // Fallback to file
      fetch('/data.json')
        .then(res => res.json())
        .then(data => setJsonData(data));
    });
}, []);

Pattern 2: Auto-Save on Edit

const handleSave = async (editedData) => {
  await fetch('http://localhost:3002/api/save', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      pdfName: pdfUrl.split('/').pop(),
      editedJson: editedData
    })
  });

  // Reload from database to verify
  const response = await fetch(`http://localhost:3002/api/load/${pdfName}`);
  const result = await response.json();
  setJsonData(result.document.currentJson);
};

Pattern 3: URL Parameters

// Load from URL: ?pdf=/doc.pdf&json=/data.json
useEffect(() => {
  const params = new URLSearchParams(window.location.search);
  const pdf = params.get('pdf');
  const json = params.get('json');

  if (pdf && json) {
    setPdfUrl(pdf);
    fetch(json)
      .then(res => res.json())
      .then(data => setJsonData(data));
  }
}, []);

Features

Inline Editing

Double-click any text to edit:

  • Edits are tracked automatically
  • Green Save button appears when changes are made
  • Yellow highlight indicates edited content

Version History

Every save creates a new version:

  • Full edit history preserved
  • Timestamps for each edit
  • Can restore any previous version

Bidirectional Mapping

Click elements to highlight corresponding content:

  • PDF → HTML viewer
  • HTML viewer → PDF location
  • Smooth scrolling and highlighting

Development

Build the Library

npm run build

Run Test App

cd test-app
npm install
npm run dev

Open: http://localhost:5175

Run with Backend

Terminal 1:

npm run server

Terminal 2:

cd test-app
npm run dev

Database Schema

documents table

CREATE TABLE documents (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  pdf_name TEXT NOT NULL,
  original_json TEXT NOT NULL,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

edits table

CREATE TABLE edits (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  document_id INTEGER NOT NULL,
  edited_json TEXT NOT NULL,
  edit_summary TEXT,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (document_id) REFERENCES documents(id)
);

Architecture

┌──────────────────┐
│  React Component │
│   (Structura)    │
└────────┬─────────┘
         │
         ├─── PDF Viewer (Left)
         │    - Render PDF pages
         │    - Click to highlight
         │
         └─── HTML Viewer (Right)
              - Structured content
              - Inline editing
              - Save button
                     │
                     ▼
              ┌──────────────┐
              │ Express API  │
              │ (port 3002)  │
              └──────┬───────┘
                     │
                     ▼
              ┌──────────────┐
              │   SQLite DB  │
              │  (edits.db)  │
              └──────────────┘

Production Deployment

Using PM2

npm install -g pm2
pm2 start server/server.js --name structura-server
pm2 save
pm2 startup

Docker

FROM node:18
WORKDIR /app
COPY package*.json ./
RUN npm install --production
COPY . .
EXPOSE 3002
CMD ["node", "server/server.js"]

Nginx

location /api/ {
  proxy_pass http://localhost:3002;
  client_max_body_size 50M;
}

Configuration

Environment Variables

PORT=3002                    # Server port
NODE_ENV=production          # Environment
DATABASE_PATH=./edits.db     # SQLite path
MAX_JSON_SIZE=50mb          # Request limit

Troubleshooting

Save button not appearing

  1. Check onSave prop is provided
  2. Make an edit (double-click text)
  3. Rebuild library: npm run build

Database not persisting

  1. Check server is running: curl http://localhost:3002/health
  2. Check database file exists: ls -la server/edits.db
  3. Check browser console for errors

PDF not loading

  1. Check CORS settings on PDF server
  2. Verify PDF path is correct
  3. Check browser console for errors

License

MIT

Author

TFW

Support

For issues and questions:

  • GitHub: https://github.com/ChakshuGautam/structura-lib
  • Documentation: See /server/README.md for API details