Skip to content

ScienceLiveHub/nanopub-create

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

66 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

nanopub-create

JavaScript library for creating and publishing nanopublications from templates with interactive forms

Create nanopublications using templates from the Knowledge Pixels network with an easy-to-use form interface. Built with vanilla JavaScript and powered by nanopub-rs WASM for signing and publishing.

License: MIT Node Version

Features

  • Template-based creation - Load any nanopub template by URI
  • Auto-generated forms - Dynamic forms from template placeholders
  • Template customization - Add custom styles and behavior per template type
  • Built-in signing - RSA key generation and nanopub signing via WASM
  • Network publishing - Publish directly to nanopub network
  • Type handling - Automatically handles nt:ASSERTION, nt:CREATOR, and other special placeholders
  • Smart labels - Extracts human-readable labels from URIs and patterns
  • Valid nanopubs - Generates standards-compliant nanopublications with trusty URIs

Quick Start

Installation

git clone https://github.com/ScienceLiveHub/nanopub-create.git
cd nanopub-create
npm install

Development

# Start dev server
npm run dev

# Open browser to http://localhost:3000/nanopub-create/demo/index.html 

Try It Out

Using the Demo

  1. Setup Profile

    • Enter your name
    • Add ORCID (optional)
    • Click "Generate Keys & Save Profile"
  2. Load a Template

    • Try: https://w3id.org/np/RAX_4tWTyjFpO6nz63s14ucuejd64t2mK3IBlkwZ7jjLo
    • Click "Load Template"
  3. Fill the Form

    • Enter values for all fields
    • Click "Create Nanopublication"
  4. Sign & Download

    • Review the preview (unsigned nanopub in TriG format)
    • Click "Sign & Download" to sign and download the nanopublication

Publishing Your Signed Nanopublication

After downloading your signed nanopublication file (e.g., nanopub-signed-2025-10-26T16-03-01-925Z.trig), you can publish it to the nanopub network:

Using curl:

curl -X POST https://np.knowledgepixels.com/ \
  -H "Content-Type: application/trig" \
  --data-binary @nanopub-signed-2025-10-26T16-03-01-925Z.trig

Using nanopub-rs CLI:

# Install nanopub CLI (if not already installed)
cargo install nanopub

# Publish your signed nanopub
nanopub publish nanopub-signed-2025-10-26T16-03-01-925Z.trig

Viewing Your Published Nanopub:

After successful publication, you'll receive a nanopub URI like:

https://w3id.org/np/RAbc123...

You can view your published nanopublication using the companion library nanopub-view.

Usage

As a Library

import NanopubCreator from '@sciencelivehub/nanopub-create';

// Initialize
const creator = new NanopubCreator({
  publishServer: null  // Set to null for signing only, or provide server URL for publishing
});

// Initialize WASM
await creator.initWasm();

// Setup profile
await creator.setupProfile('Your Name', 'https://orcid.org/0000-0002-1234-5678');

// Load template and render form
const templateUri = 'https://w3id.org/np/RAX_4tWTyjFpO6nz63s14ucuejd64t2mK3IBlkwZ7jjLo';
const container = document.getElementById('form-container');
await creator.renderFromTemplateUri(templateUri, container);

// Listen for nanopub creation
creator.on('create', ({ trigContent }) => {
  console.log('Created nanopub:', trigContent);
});

// Sign the nanopub
const signedContent = await creator.publish(trigContent);

// The signed nanopub can then be published to a nanopub server

Programmatic Creation

// For programmatic creation without a form UI, you can use the lower-level APIs:

import { TemplateParser } from '@sciencelivehub/nanopub-create';
import { NanopubBuilder } from '@sciencelivehub/nanopub-create';

// Parse template
const parser = new TemplateParser();
const template = await parser.fetchTemplate(templateUri);
await parser.parseTemplate();

// Build nanopub from form data
const builder = new NanopubBuilder(parser.template);
const formData = {
  'st01_subject': 'https://doi.org/10.1234/example',
  'st02_predicate': 'http://purl.org/spar/cito/cites',
  'st02_object': 'https://doi.org/10.5678/cited'
};

const trigContent = await builder.buildFromFormData(formData, {
  creator: 'https://orcid.org/0000-0002-1234-5678',
  creatorName: 'Your Name'
});

// Then sign with the creator instance
const signedContent = await creator.publish(trigContent);

Template Customization

nanopub-create supports custom styling and behavior for different template types through a flexible customization system.

Available Templates

Geographical Coverage - Document geographical coverage of research

https://w3id.org/np/RAsPVd3bNOPg5vxQGc1Tqn69v3dSY-ASrAhEFioutCXao

Citation with CiTO - Create citation relationships between papers

https://w3id.org/np/RAX_4tWTyjFpO6nz63s14ucuejd64t2mK3IBlkwZ7jjLo

Comment on Paper - Add quotes and commentary to papers

https://w3id.org/np/RAVEpTdLrX5XrhNl_gnvTaBcjRRSDu_hhZix8gu2HO7jI

Browse more templates at Knowledge Pixels or explore existing nanopublications to find templates.

Creating Custom Templates

To add custom styling and behavior for a template:

  1. Create a template class in src/templates/[name]/[name]Template.js
  2. Create template styles in src/styles/templates/[name].css
  3. Register the template in src/templates/registry.js
  4. Import the styles in src/styles/styles-index.css

See CONTRIBUTING.md for detailed instructions on creating custom template styles.

Example: Geographical Template

The geographical template demonstrates the customization system:

Custom styling - Green theme for geography-related forms

.template-geographical {
  --geo-primary: #059669;
}

Field grouping - Groups geometry and WKT fields together

detectSemanticGroups() {
  return [{
    id: 'geometry-group',
    label: 'Geometry Details (WKT Format)',
    statements: [geometryLinkStmt.id, wktStmt.id],
    collapsible: true
  }];
}

Auto-fill rules - Automatically derives geometry ID from location

getAutofillRules() {
  return [{
    trigger: 'location',
    target: 'geometry-id',
    transform: (value) => value.toLowerCase().replace(/\s+/g, '-')
  }];
}

Field hints - Provides helpful examples for WKT format

customizeField(field, placeholder) {
  if (placeholder.id === 'wkt') {
    const hint = document.createElement('div');
    hint.innerHTML = 'WKT Format Example: POINT(2.3 48.9)';
    field.parentElement?.appendChild(hint);
  }
}

Project Structure

nanopub-create/
├── src/
│   ├── core/
│   │   ├── nanopubBuilder.js      # Generates TriG from templates
│   │   ├── templateParser.js      # Parses nanopub templates
│   │   └── formGenerator.js       # Creates HTML forms
│   ├── templates/
│   │   ├── registry.js            # Template customization registry
│   │   ├── base/
│   │   │   └── baseTemplate.js    # Base customization class
│   │   └── geographical/
│   │       └── geographicalTemplate.js  # Example customization
│   ├── components/
│   │   └── ui/                    # Reusable UI components
│   ├── styles/
│   │   ├── tailwind.base.css      # Base Tailwind utilities
│   │   ├── styles-index.css       # Main CSS entry point
│   │   └── templates/
│   │       └── geographical.css   # Template-specific styles
│   ├── utils/
│   │   └── labelFetcher.js        # Fetches URI labels
│   └── index.js                   # Main entry point
├── demo/
│   └── index.html                 # Demo page
├── package.json
├── vite.config.js
├── CONTRIBUTING.md                # Template customization guide
├── LICENSE
└── README.md

How It Works

1. Template Parsing

// Fetches and parses template
const template = await templateParser.parse(templateContent);

// Extracts:
// - Placeholders (form fields)
// - Statements (RDF structure)
// - Metadata (types, labels, patterns)

2. Form Generation

// Creates HTML form from placeholders
formGenerator.render(template, container);

// Supports:
// - Text inputs (LiteralPlaceholder)
// - Textareas (LongLiteralPlaceholder)
// - Dropdowns (RestrictedChoicePlaceholder)
// - URL inputs (ExternalUriPlaceholder)

3. Nanopub Building

// Generates TriG format
const trig = await nanopubBuilder.buildFromFormData(formData, metadata);

// Handles:
// - Special placeholders (nt:ASSERTION, nt:CREATOR)
// - Label patterns (${placeholder} replacement)
// - Multi-line strings (triple quotes)
// - Type declarations (npx:hasNanopubType)

4. Signing & Publishing

// Sign with WASM
const signed = await nanopubSign.sign(trig, privateKey);

// Publish to network
const uri = await nanopubSign.publish(signed);

Template Support

Supports all standard nanopub template types:

Placeholder Type Form Element Example
LiteralPlaceholder Text input Short text
LongLiteralPlaceholder Textarea Multi-line text
ExternalUriPlaceholder URL input DOI, URL
UriPlaceholder URL input Any URI
RestrictedChoicePlaceholder Dropdown Predefined options
GuidedChoicePlaceholder Autocomplete Search-based
IntroducedResource Text input New resource

Special Placeholders

  • nt:ASSERTION - Replaced with sub:assertion
  • nt:CREATOR - Replaced with user's ORCID

Label Patterns

Templates can include dynamic labels:

nt:hasNanopubLabelPattern "Citations for: ${article}"

Automatically extracts values and generates:

rdfs:label "Citations for: 10.1145/3460210.3493546"

Profile Management

Generate Keys and Setup Profile

await creator.initWasm();
await creator.setupProfile('Your Name', 'https://orcid.org/0000-0002-1234-5678');

Keys are stored in browser localStorage and never leave your machine.

Check Profile Status

const hasProfile = creator.hasProfile();
const profile = creator.getProfile(); // Returns { name, orcid }

Export Profile

const keys = creator.exportKeys();
// Save as JSON for backup

Import Profile

creator.importKeys(profileData);
// Restore from backup

Clear Credentials

creator.clearCredentials();
// Removes stored profile and keys

Development

Prerequisites

  • Node.js 18+
  • npm or yarn

Commands

# Install dependencies
npm install

# Start dev server (http://localhost:3000)
npm run dev

# Build for production
npm run build

# Preview production build
npm run preview

# Clear cache and restart
npx vite --force

Configuration

vite.config.js:

import { defineConfig } from 'vite';
import wasm from 'vite-plugin-wasm';
import topLevelAwait from 'vite-plugin-top-level-await';

export default defineConfig({
  plugins: [wasm(), topLevelAwait()],
  optimizeDeps: {
    exclude: ['@nanopub/sign']  // CRITICAL for WASM
  }
});

Dependencies

Runtime

  • @nanopub/sign - WASM library for signing/publishing

Development

  • vite - Build tool and dev server
  • vite-plugin-wasm - WASM support
  • vite-plugin-top-level-await - Top-level await support

Contributing

Contributions welcome! Please see CONTRIBUTING.md for:

  • How to create custom template styles
  • Code style guidelines
  • Pull request process

Troubleshooting

Hash URIs vs Slash URIs

The @nanopub/sign WASM library generates hash-based URIs (#) for nanopub graphs. nanopub-create uses these hash URIs as-is to maintain cryptographic integrity.

Why hash URIs are used:

  • Required for trusty URI validation (cryptographic hash verification)
  • Changing URIs after signing breaks the trusty hash
  • Hash URIs are still valid and functional nanopublications
  • Compatible with the nanopub network and ecosystem

Output format:

PREFIX sub: <https://w3id.org/np/RA...#> .

GRAPH <https://w3id.org/np/RA...#/Head> {
  this: np:hasAssertion <...#/assertion> .
}

Note on slash URIs: While slash-based URIs (/) are more RESTful and HTTP dereferenceable, converting hash URIs to slash URIs after signing breaks the trusty hash validation, preventing publication to the nanopub network. The WASM library would need to be modified to generate slash URIs natively for this to work.

WASM Not Loading

# Clear cache and restart
npx vite --force

Types Not Showing

Check that templateParser.js searches entire template:

// Should be this.content, not assertionBlock
const typesMatch = this.content.match(/nt:hasTargetNanopubType/);

Label Pattern Not Working

Verify pattern is being parsed:

// Should search this.content
const patternMatch = this.content.match(/nt:hasNanopubLabelPattern/);

Resources

License

MIT License - see LICENSE file for details

Authors

ScienceLive Hub

Acknowledgments


Questions? Open an issue or visit our discussions

About

A JavaScript/React library for creating nanopublications with beautiful, interactive forms.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •