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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@qarakash/blockwriteai

v1.0.9

Published

BlockWriteAI JSON-first drop-in block writing editor with free core blocks, preview mounting, and license-gated premium plugins.

Readme

BlockWriteAI

BlockWriteAI is a drop-in block writing editor for the web. It is built to feel familiar to Editor.js users, but ships as plain CSS and JavaScript files that can be used in PHP, Laravel, CodeIgniter, static HTML, dashboards, or any project that can load a script tag.

The editor stores and saves content as JSON first. Projects can render that JSON on any page by adding a BlockWriteAI preview container, while advanced document blocks such as tables, media galleries, attachments, diagrams, charts, signatures, and code editing remain available as plugins.

All public assets, package entry points, and browser globals use the BlockWriteAI name.

Highlights

  • Editor.js-style block JSON output.
  • Plain script tag integration with no build step required.
  • Paragraphs, headings, quotes, callouts, dividers, buttons, toggle blocks, raw HTML, links, embeds, tables, lists, and nested checklists.
  • Floating inline toolbar with typography, colors, highlight, alignment, comments, links, and formatting controls.
  • Multi-image upload, drag and drop, resize, crop, rotate, and gallery layout.
  • Attachment blocks for documents and videos.
  • Code block with formatting, syntax help, language detection, and suggestions.
  • Charts, LaTeX, audio, layout columns, code assistance, and optional history plugins in the free plugin set.
  • Premium plugins for Drawing, Mermaid, Signature, Signature Flow, and AI writing, delivered after server-side license verification.
  • Undo, redo, autosave, block actions, drag reordering, and optional JSON save/export buttons.
  • JSON-powered preview mounting for public document pages.
  • JSON save API examples for future database storage.

Project Structure

BlockWriteAI/
  package.json
  composer.json
  pyproject.toml
  dist/
    blockwriteai.css
    blockwriteai.js
    blockwriteai-logo.svg
    blockwriteai-favicon.svg
    plugins/
      blockwriteai-advanced-blocks.js
      blockwriteai-drawing.js
      blockwriteai-mermaid.js
      blockwriteai-ai.js
      blockwriteai-code-assist.js
      blockwriteai-history.js
      blockwriteai-signature.js
      blockwriteai-signature-flow.js
  examples/
    index.html
    preview.html
    upload.php
    api/
      document.php
      preview.php
    uploads/
      .gitkeep
  blockwriteai_editor/
    static/blockwriteai/
  src/
    BlockWriteAIAssets.php
  types/
    index.d.ts

Installation

BlockWriteAI can be consumed as a CDN/script-link package, an npm package, a Python static-assets package, or a Composer package.

Script Link

Use the npm CDN for a locked release build:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@qarakash/[email protected]/dist/blockwriteai.css">

<script src="https://cdn.jsdelivr.net/npm/@qarakash/[email protected]/dist/blockwriteai.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@qarakash/[email protected]/dist/plugins/blockwriteai-code-assist.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@qarakash/[email protected]/dist/plugins/blockwriteai-advanced-blocks.js"></script>

blockwriteai-advanced-blocks.js is the free advanced bundle. It includes Chart, LaTeX, Audio, and Columns/Layout. Drawing, Mermaid, Signature, Signature Flow, and AI are premium plugins and should not be loaded directly in production.

Load History only when a project needs the history dropdown:

<script src="https://cdn.jsdelivr.net/npm/@qarakash/[email protected]/dist/plugins/blockwriteai-history.js"></script>

For development against the current GitHub branch, replace the npm URLs with the GitHub CDN form:

https://cdn.jsdelivr.net/gh/qarAkash/BlockWriteAI@main/dist/...

Premium License Gating

Drawing, Mermaid drawing, Signature, Signature Flow, and AI can be licensed through the BlockWriteAI Platform. Normal editor blocks continue to work without a license. Premium plugin scripts are delivered only after the license endpoint returns an active trial or subscription. Without a valid license, those tools are not registered and do not appear in the insert-block menu.

const editor = new BlockWriteAI({
  holder: "#editor",
  premium: {
    licenseKey: "bwai_live_xxxxx",
    verifyEndpoint: "http://localhost/blockwriteai-platform/api/license_verify.php",
    pluginEndpoint: "http://localhost/blockwriteai-platform/api/premium_plugins.php",
    usageEndpoint: "http://localhost/blockwriteai-platform/api/ai_usage.php",
    autoLoadPlugins: true,
    features: ["drawing", "mermaid", "signature", "signature_flow", "ai"]
  },
  ai: {
    endpoint: "/api/ai.php"
  }
});

The verify endpoint must return a features object with these keys when enabled:

{
  "drawing": true,
  "mermaid": true,
  "signature": true,
  "signature_flow": true,
  "ai": true
}

The AI plugin calls premium.usageEndpoint before each AI request so the platform can enforce the 7-day trial and daily prompt limits.

For stronger production security, do not load premium plugin files directly from a public CDN. Load the free core first, request the premium plugins from your BlockWriteAI Platform, and create the editor only after the server has verified the license. The platform serves Drawing, Mermaid, Signature, Signature Flow, and AI as a verified bundle after checking the requested feature flags:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@qarakash/[email protected]/dist/blockwriteai.css">
<script src="https://cdn.jsdelivr.net/npm/@qarakash/[email protected]/dist/blockwriteai.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@qarakash/[email protected]/dist/plugins/blockwriteai-code-assist.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@qarakash/[email protected]/dist/plugins/blockwriteai-advanced-blocks.js"></script>
<script>
  async function boot() {
    await BlockWriteAI.loadPremiumPlugins({
      licenseKey: "bwai_live_xxxxx",
      endpoint: "http://localhost/blockwriteai-platform/api/premium_plugins.php",
      features: ["drawing", "mermaid", "signature", "signature_flow", "ai"]
    });

    window.editor = new BlockWriteAI({
      holder: "#editor",
      premium: {
        licenseKey: "bwai_live_xxxxx",
        verifyEndpoint: "http://localhost/blockwriteai-platform/api/license_verify.php",
        usageEndpoint: "http://localhost/blockwriteai-platform/api/ai_usage.php"
      }
    });
  }
  boot();
</script>

This matters because browser-only locks can be edited in DevTools. Server-side license verification, usage metering, signature event storage, and verified premium bundle delivery are the enforceable parts.

npm

Package name:

@qarakash/blockwriteai

Install:

npm install @qarakash/blockwriteai

Bundler entry points:

import BlockWriteAI from "@qarakash/blockwriteai";
import "@qarakash/blockwriteai/css";
import "@qarakash/blockwriteai/plugins/code-assist";
import "@qarakash/blockwriteai/plugins/advanced";
import "@qarakash/blockwriteai/plugins/history";

After npm publishing, the same package is also available through npm CDNs:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@qarakash/[email protected]/dist/blockwriteai.css">
<script src="https://cdn.jsdelivr.net/npm/@qarakash/[email protected]/dist/blockwriteai.js"></script>

Python

Package name:

blockwriteai-editor

Install:

pip install blockwriteai-editor

Copy packaged static files into your Flask, Django, or any Python web app static directory:

from blockwriteai_editor import copy_static

copy_static("static/blockwriteai")

Python helpers are also available for generating asset tags. script_tags() loads only core/free plugins by default. Pass history=True only on pages where you want the optional History dropdown:

from blockwriteai_editor import premium_script_tags, stylesheet_tag, script_tags

print(stylesheet_tag("/static/blockwriteai"))
print(script_tags("/static/blockwriteai"))
print(script_tags("/static/blockwriteai", history=True))

# Only for private/licensed deployments. Public apps should prefer the platform
# premium bundle endpoint shown in the Premium License Gating section.
print(premium_script_tags("/static/blockwriteai", ["signature", "ai"]))

PHP / Composer

Package name:

qarakash/blockwriteai

Install:

composer require qarakash/blockwriteai

Publish assets into your public folder:

cp -R vendor/qarakash/blockwriteai/dist public/blockwriteai

PHP helper. scriptTags() loads only core/free plugins by default. Pass history: true only on pages where you want the optional History dropdown:

use QarAkash\BlockWriteAI\BlockWriteAIAssets;

echo BlockWriteAIAssets::stylesheetTag('/blockwriteai');
echo BlockWriteAIAssets::scriptTags('/blockwriteai');
echo BlockWriteAIAssets::scriptTags('/blockwriteai', plugins: true, history: true);

// Only for private/licensed deployments. Public apps should prefer the platform
// premium bundle endpoint shown in the Premium License Gating section.
echo BlockWriteAIAssets::premiumScriptTags('/blockwriteai', ['signature', 'ai']);

Local XAMPP Demo

Copy the BlockWriteAI folder into your web root, for example:

C:\xampp\htdocs\BlockWriteAI

Open:

http://localhost/BlockWriteAI/examples/

Browser Usage

<link rel="stylesheet" href="/BlockWriteAI/dist/blockwriteai.css">

<div id="editor"></div>

<script src="/BlockWriteAI/dist/blockwriteai.js"></script>
<script src="/BlockWriteAI/dist/plugins/blockwriteai-code-assist.js"></script>
<script src="/BlockWriteAI/dist/plugins/blockwriteai-advanced-blocks.js"></script>

<script>
const editor = new BlockWriteAI({
  holder: "#editor",
  maxWidth: "960px", // optional; omit for full-width editor shell
  placeholder: "Write something, or press / for blocks",
  data: {
    blocks: [
      {
        type: "paragraph",
        data: {
          text: "Hello from BlockWriteAI",
          alignment: "left"
        }
      }
    ]
  },
  onChange(data) {
    console.log("Changed document", data);
  },
  async onSave(data) {
    await fetch("/save-document.php", {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify(data)
    });
  }
});
</script>

By default, BlockWriteAI mounts the full branded editor shell: logo, product subtitle, Editor heading, centered AI progress, and the right-aligned JSON sync status. If no data is provided, the editor starts with one empty paragraph block automatically. Use shell: false when you only want the raw editor surface, or pass maxWidth: "960px" / shell: { maxWidth: "960px" } to constrain the editor width in your project.

Built-in toolbar buttons are intentionally opt-in for package consumers. saveButton, exportButton, and exportHtmlButton default to false, so applications can use their own UI and call editor.save() when needed.

Saving JSON

BlockWriteAI is designed to save JSON first. In production, store the JSON in your database and render it later in read-only mode or through exported HTML.

document.querySelector("#save").addEventListener("click", async () => {
  const data = await editor.save();

  await fetch("/save-document.php", {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify(data)
  });
});

The default toolbar includes a Save button. Use onSave to receive the JSON response when the user clicks it:

const editor = new BlockWriteAI({
  holder: "#editor",
  async onSave(data) {
    await fetch("/documents/123", {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify(data)
    });
  }
});

AI Plugin

AI is a premium plugin. Load it through the platform premium bundle after license verification. The browser plugin never receives your OpenAI API key; it calls your own server endpoint.

<script src="/blockwriteai/blockwriteai.js"></script>

<script>
  async function boot() {
    await BlockWriteAI.loadPremiumPlugins({
      licenseKey: "bwai_live_xxxxx",
      endpoint: "/blockwriteai-platform/api/premium_plugins.php",
      features: ["ai"]
    });

    window.editor = new BlockWriteAI({
      holder: "#editor",
      premium: {
        licenseKey: "bwai_live_xxxxx",
        verifyEndpoint: "/blockwriteai-platform/api/license_verify.php",
        usageEndpoint: "/blockwriteai-platform/api/ai_usage.php"
      },
      ai: {
        endpoint: "/api/blockwriteai-ai.php"
      }
    });
  }
  boot();
</script>

The included demo endpoint is examples/api/ai.php. For local development, copy examples/api/openai.local.example.php to examples/api/openai.local.php and add a development key, or set OPENAI_API_KEY in the server environment. Do not expose the key in browser JavaScript.

The drawer can also be opened without selecting text from the centered AI button in the editor toolbar, or programmatically with editor.openAI().

Available AI drawer actions:

  • Improve writing
  • Fix grammar
  • Summarize
  • Expand
  • Make professional
  • Generate BlockWriteAI blocks from a prompt

Preview Pages

Create any page in your application and add a preview container. BlockWriteAI will load saved JSON and render the document HTML inside that container.

<link rel="stylesheet" href="/blockwriteai/blockwriteai.css">

<div class="blockwriteai-preview" data-source="/documents/123.json"></div>

<script src="/blockwriteai/blockwriteai.js"></script>
<script src="/blockwriteai/plugins/blockwriteai-advanced-blocks.js"></script>
<script>
  BlockWriteAI.mountPreviews();
</script>

If the preview page must render premium blocks, load the licensed premium bundle before BlockWriteAI.mountPreviews():

async function mountDocumentPreview() {
  await BlockWriteAI.loadPremiumPlugins({
    licenseKey: "bwai_live_xxxxx",
    endpoint: "/blockwriteai-platform/api/premium_plugins.php",
    features: ["drawing", "mermaid", "signature", "signature_flow", "ai"]
  });
  BlockWriteAI.mountPreviews();
}
mountDocumentPreview();

The JSON endpoint can return either a BlockWriteAI document directly or an API wrapper such as:

{
  "ok": true,
  "data": {
    "time": 1779540000000,
    "version": "1.0.9",
    "blocks": []
  }
}

Example PHP receiver:

<?php
header('Content-Type: application/json');

$json = file_get_contents('php://input');
$data = json_decode($json, true);

if (!$data || !isset($data['blocks']) || !is_array($data['blocks'])) {
    http_response_code(422);
    echo json_encode(['error' => 'Invalid BlockWriteAI document']);
    exit;
}

file_put_contents(__DIR__ . '/saved-document.json', json_encode($data, JSON_PRETTY_PRINT));

echo json_encode(['ok' => true]);

Uploads

The demo includes examples/upload.php and stores files under examples/uploads/. For production, replace this with your own storage layer.

const editor = new BlockWriteAI({
  holder: "#editor",
  uploadOutput: ["upload", "base64"],
  upload: {
    image: async (file) => {
      const form = new FormData();
      form.append("file", file);
      form.append("kind", "image");

      const response = await fetch("/BlockWriteAI/examples/upload.php", {
        method: "POST",
        body: form
      });

      return response.json();
    },
    file: async (file) => {
      const form = new FormData();
      form.append("file", file);
      form.append("kind", "file");

      const response = await fetch("/BlockWriteAI/examples/upload.php", {
        method: "POST",
        body: form
      });

      return response.json();
    }
  }
});

uploadOutput controls what gets written into the saved JSON:

  • "base64" or ["base64"] stores uploaded media directly in the block JSON. This is the default.
  • "upload" or ["upload"] stores the response from your upload handler, such as a server URL.
  • ["upload", "base64"] stores both, useful when you want server files plus a portable JSON backup.

Expected upload response:

{
  "url": "/BlockWriteAI/examples/uploads/example.pdf",
  "name": "example.pdf",
  "size": 12345,
  "type": "application/pdf"
}

When both outputs are enabled, saved image and attachment items include the server response under upload and the inline file data under base64.

API Methods

await editor.save();          // Get JSON document
editor.getData();             // Get current data synchronously
editor.render(data);          // Replace editor content
editor.clear();               // Reset editor
editor.exportHTML();          // Export HTML
editor.exportMarkdown();      // Export Markdown API, hidden from the default UI
editor.importHTML(html);      // Import HTML into blocks
editor.setReadOnly(true);     // Toggle read-only mode
editor.undo();                // Undo last change
editor.redo();                // Redo last undo
editor.destroy();             // Remove editor instance
BlockWriteAI.mountPreviews(); // Render JSON into .blockwriteai-preview containers

Data Shape

{
  "time": 1779540000000,
  "version": "1.0.9",
  "blocks": [
    {
      "id": "block-title",
      "type": "heading",
      "data": {
        "level": 2,
        "text": "BlockWriteAI document",
        "alignment": "left"
      }
    },
    {
      "id": "block-body",
      "type": "paragraph",
      "data": {
        "text": "Reusable content saved as JSON."
      }
    }
  ]
}

Tool Control

Limit available blocks per project:

const editor = new BlockWriteAI({
  holder: "#editor",
  tools: [
    "paragraph",
    "heading",
    "image",
    "list",
    "table"
  ]
});

Disable specific tools:

const editor = new BlockWriteAI({
  holder: "#editor",
  tools: {
    raw: false,
    attaches: false
  }
});

Autosave

const editor = new BlockWriteAI({
  holder: "#editor",
  autosave: {
    key: "blockwriteai-draft",
    load: true
  }
});

Security Notes

BlockWriteAI sanitizes normal rich text blocks before saving and exporting. Raw HTML blocks are intentionally treated as trusted HTML, so enable the raw HTML tool only for trusted users.

For production applications:

  • Validate JSON on the server.
  • Sanitize output again before public rendering.
  • Restrict upload types and file sizes.
  • Store uploaded files outside executable PHP paths when possible.
  • Add authentication before saving documents.

GitHub

Repository target:

https://github.com/qarAkash/BlockWriteAI.git

Publishing Packages

After a release is ready, publish each package from the repository root.

Create a Git release tag for script-link/CDN users:

git tag v1.0.9
git push origin v1.0.9

Publish npm:

npm publish --access public

Publish Python:

python -m build
python -m twine upload dist/*

Publish Composer:

Submit https://github.com/qarAkash/BlockWriteAI to Packagist as qarakash/blockwriteai.

Status

BlockWriteAI is currently an active custom editor library and demo project. It is suitable for continued feature development, integration testing, and database-backed storage work.