PHPackages                             rafaelogic/writr - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Templating &amp; Views](/categories/templating)
4. /
5. rafaelogic/writr

ActiveLibrary[Templating &amp; Views](/categories/templating)

rafaelogic/writr
================

A comprehensive Notion-like editor for Laravel using Editor.js with advanced features

v1.1.0(9mo ago)01MITJavaScriptPHP ^8.1

Since Aug 12Pushed 9mo agoCompare

[ Source](https://github.com/rafaelogic/writr)[ Packagist](https://packagist.org/packages/rafaelogic/writr)[ RSS](/packages/rafaelogic-writr/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (12)Versions (3)Used By (0)

Writr - Laravel Notion-like Editor Package
==========================================

[](#writr---laravel-notion-like-editor-package)

[![Version](https://camo.githubusercontent.com/82607e69abe99314712caaca3e9c3d804b6290df91f9771848c2c84b1d6bf4b8/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f76657273696f6e2d312e312e302d626c75652e737667)](https://camo.githubusercontent.com/82607e69abe99314712caaca3e9c3d804b6290df91f9771848c2c84b1d6bf4b8/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f76657273696f6e2d312e312e302d626c75652e737667)[![Laravel](https://camo.githubusercontent.com/6cd412ab3917222dca1d325437f5da3a0447c0bea05696cf7b6ce64d1ee8492a/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d3130253242253230253743253230313125323025374325323031322d7265642e737667)](https://camo.githubusercontent.com/6cd412ab3917222dca1d325437f5da3a0447c0bea05696cf7b6ce64d1ee8492a/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d3130253242253230253743253230313125323025374325323031322d7265642e737667)[![PHP](https://camo.githubusercontent.com/fb7c72456e13f7d5ecf8486e29d02a2e6775aaf4d18622a63529976b0ed0740e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e312532422d707572706c652e737667)](https://camo.githubusercontent.com/fb7c72456e13f7d5ecf8486e29d02a2e6775aaf4d18622a63529976b0ed0740e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e312532422d707572706c652e737667)[![License](https://camo.githubusercontent.com/8bb50fd2278f18fc326bf71f6e88ca8f884f72f179d3e555e20ed30157190d0d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e2e737667)](https://camo.githubusercontent.com/8bb50fd2278f18fc326bf71f6e88ca8f884f72f179d3e555e20ed30157190d0d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e2e737667)

A production-ready, comprehensive Notion-like editor for Laravel applications using Editor.js. Features a complete block-based editing experience with advanced tools, file handling, and seamless Laravel integration.

📖 Table of Contents
-------------------

[](#-table-of-contents)

- [🌐 Live Demo](#-live-demo)
- [✨ Features](#-features)
    - [📝 Core Editor Capabilities](#-core-editor-capabilities)
    - [🚀 Advanced Features](#-advanced-features)
    - [🔧 Laravel Integration](#-laravel-integration)
    - [🏗️ Architecture &amp; Development](#%EF%B8%8F-architecture--development)
- [📦 Installation](#-installation)
    - [Requirements](#requirements)
    - [1. Install via Composer](#1-install-via-composer)
    - [2. Publish Assets (Optional)](#2-publish-assets-optional)
    - [3. Setup Layout](#3-setup-layout)
- [🚀 Quick Start](#-quick-start)
    - [Basic Usage](#basic-usage)
    - [With Laravel Validation](#with-laravel-validation)
    - [Advanced Configuration](#advanced-configuration)
    - [Component Architecture](#component-architecture)
- [⚙️ Configuration](#%EF%B8%8F-configuration)
    - [🎨 Settings UI (Recommended)](#-settings-ui-recommended)
    - [📄 Configuration File](#-configuration-file)
    - [Editor Settings](#editor-settings)
    - [Tools Configuration](#tools-configuration)
    - [Feature Configuration](#feature-configuration)
- [📁 File Upload System](#-file-upload-system)
    - [Upload Configuration](#upload-configuration)
    - [Custom Upload Handler](#custom-upload-handler)
    - [Upload Progress &amp; Validation](#upload-progress--validation)
- [🔄 Content Processing](#-content-processing)
    - [Working with Content](#working-with-content)
    - [Content Validation](#content-validation)
    - [Search Integration](#search-integration)
- [Advanced Features](#advanced-features)
    - [Auto-save](#auto-save)
    - [Dark Mode](#dark-mode)
    - [Custom Styling](#custom-styling)
- [API Endpoints](#api-endpoints)
- [🎨 Frontend Integration](#-frontend-integration)
    - [Direct JavaScript Usage](#direct-javascript-usage)
    - [Custom Tools](#custom-tools)
    - [Event Handling](#event-handling)
- [🏗️ Development &amp; Building](#%EF%B8%8F-development--building)
    - [Development Setup](#development-setup)
    - [Building Assets](#building-assets)
    - [Testing](#testing)
    - [Project Structure](#project-structure)
- [🚀 Performance &amp; Optimization](#-performance--optimization)
    - [Performance Features](#performance-features)
    - [Optimization Tips](#optimization-tips)
    - [Memory Management](#memory-management)
    - [Bundle Analysis](#bundle-analysis)
- [🌍 Browser Compatibility](#-browser-compatibility)
- [🤝 Contributing](#-contributing)
    - [Development Setup](#development-setup-1)
    - [Contribution Guidelines](#contribution-guidelines)
    - [Development Workflow](#development-workflow)
    - [Areas for Contribution](#areas-for-contribution)
- [📄 License](#-license)
- [🆘 Support &amp; Community](#-support--community)
    - [Documentation &amp; Resources](#documentation--resources)
    - [Getting Help](#getting-help)
    - [Community](#community)
- [🙏 Credits &amp; Acknowledgments](#-credits--acknowledgments)

🌐 Live Demo
-----------

[](#-live-demo)

**[Try the Interactive Demo →](https://rafaelogic.github.io/writr/)**

Experience all features of Writr Editor including:

- All block types and inline formatting tools
- Real-time content capture and form submission
- Content export in multiple formats (HTML, Markdown, JSON)
- Professional inline toolbar with modern design
- Mobile-responsive editing interface

✨ Features
----------

[](#-features)

### 📝 Core Editor Capabilities

[](#-core-editor-capabilities)

- ✅ **Complete Editor.js Integration**: All standard tools (headers, paragraphs, lists, tables, images, code blocks, quotes, embeds)
- ✅ **Drag &amp; Drop Reordering**: Intuitive block reorganization with visual feedback
- ✅ **Undo/Redo System**: Full undo stack with keyboard shortcuts (Ctrl+Z / Ctrl+Y)
- ✅ **Live Preview Mode**: Toggle between edit and rendered preview
- ✅ **Dark/Light Themes**: Built-in theme system with automatic system detection
- ✅ **Mobile Responsive**: Optimized touch interface for all device sizes
- ✅ **Keyboard Shortcuts**: Full keyboard navigation and editing support

### 🚀 Advanced Features

[](#-advanced-features)

- ✅ **Enhanced Inline Toolbar**: Modern inline toolbar with bottom positioning for text formatting
- ✅ **Content Capture System**: Automatic content capture for seamless form submissions
- ✅ **Settings UI**: Professional settings interface for all configuration options
- ✅ **Auto-save**: Configurable automatic content saving with debouncing
- ✅ **Table of Contents**: Auto-generated navigation from document headers
- ✅ **Word &amp; Character Count**: Real-time statistics display
- ✅ **Content Export**: HTML, Markdown, Plain Text, and JSON export formats
- ✅ **Content Import**: Import from HTML, Markdown, and plain text sources
- ✅ **File Upload System**: Drag-and-drop image and file uploads with validation
- ✅ **Memory Management**: Intelligent cleanup to prevent memory leaks
- ✅ **Performance Monitoring**: Built-in performance tracking and optimization

### 🔧 Laravel Integration

[](#-laravel-integration)

- ✅ **Blade Component**: Drop-in `` component with self-contained rendering
- ✅ **Form Integration**: Seamless Laravel form integration with validation rules
- ✅ **Asset Management**: Optimized asset bundling and cache-busting
- ✅ **Service Provider**: Auto-discovery with comprehensive configuration
- ✅ **Middleware Support**: Built-in CSRF protection and rate limiting
- ✅ **Queue Integration**: Background processing for heavy operations

### 🏗️ Architecture &amp; Development

[](#️-architecture--development)

- ✅ **Modern JavaScript**: ES6+ modules with tree-shaking and optimization
- ✅ **Build System**: Laravel Mix + Webpack with development and production configurations
- ✅ **Zero Global Dependencies**: All dependencies bundled, no pollution of global scope
- ✅ **TypeScript Support**: Full type definitions and IntelliSense support
- ✅ **Testing Suite**: Comprehensive unit and integration tests (PHPUnit + Vitest)
- ✅ **Security Hardened**: Content sanitization, CSRF protection, and input validation

📦 Installation
--------------

[](#-installation)

### Requirements

[](#requirements)

- **PHP**: 8.1 or higher
- **Laravel**: 10.x, 11.x, or 12.x
- **Node.js**: 16+ (for asset compilation)
- **Modern Browser**: Chrome 70+, Firefox 65+, Safari 12+, Edge 79+

### 1. Install via Composer

[](#1-install-via-composer)

```
composer require rafaelogic/writr
```

The package will auto-register via Laravel's package discovery.

### 2. Publish Assets (Optional)

[](#2-publish-assets-optional)

```
# Publish configuration file (recommended for customization)
php artisan vendor:publish --tag=writr-config

# Publish all Blade views (rarely needed)
php artisan vendor:publish --tag=writr-views

# Publish compiled assets (CSS/JS) to public directory
php artisan vendor:publish --tag=writr-assets

# Publish all package files
php artisan vendor:publish --provider="Rafaelogic\Writr\WritrServiceProvider"
```

> **Note:** The Writr component is self-contained and renders directly from PHP for maximum compatibility. Publishing is typically only needed for configuration changes.

### 3. Setup Layout

[](#3-setup-layout)

Include required dependencies in your layout:

```
>

    @stack('writr-styles')

    @stack('writr-scripts')

```

🚀 Quick Start
-------------

[](#-quick-start)

### Basic Usage

[](#basic-usage)

The simplest way to get started:

```
{{-- In your Blade template --}}

    @csrf

    Save Document

```

### With Laravel Validation

[](#with-laravel-validation)

```
// In your Controller
public function store(Request $request)
{
    $validated = $request->validate([
        'title' => 'required|string|max:255',
        'content' => 'required|json' // Writr content is stored as JSON
    ]);

    // Optionally validate the structure
    $contentData = json_decode($validated['content'], true);
    if (!isset($contentData['blocks']) || empty($contentData['blocks'])) {
        return back()->withErrors(['content' => 'Content cannot be empty.']);
    }

    Document::create($validated);

    return redirect()->route('documents.index')
        ->with('success', 'Document saved successfully!');
}
```

### Advanced Configuration

[](#advanced-configuration)

```

```

### Component Architecture

[](#component-architecture)

The Writr Blade component uses **self-contained PHP rendering** for maximum compatibility and reliability. Unlike traditional Blade templates, the component renders its HTML, CSS, and JavaScript directly from the PHP class to ensure:

- ✅ **Zero dependency conflicts** - No conflicts with your app's Blade directives or CSS frameworks
- ✅ **Consistent rendering** - Same output across all Laravel versions and configurations
- ✅ **Automatic asset management** - CSS and JS assets are loaded automatically without manual setup
- ✅ **Framework agnostic** - Works with any CSS framework (Tailwind, Bootstrap, etc.)

This approach ensures the editor works out-of-the-box without requiring publishing or customization for most use cases.

⚙️ Configuration
----------------

[](#️-configuration)

The configuration file provides extensive customization options. You can manage settings in two ways:

### 🎨 Settings UI (Recommended)

[](#-settings-ui-recommended)

Access the visual settings interface at `/writr/settings` for an intuitive configuration experience:

- **Professional Interface**: Modern, responsive settings UI with dark mode support
- **Live Validation**: Real-time input validation with helpful error messages
- **Import/Export**: Backup and restore settings as JSON files
- **Keyboard Shortcuts**: Ctrl+S to save, Ctrl+Shift+R to reset
- **Organized Sections**: Editor, Tools, Features, Theme, Security, and Performance settings

```
# Visit in your browser
https://yourapp.com/writr/settings
```

### 📄 Configuration File

[](#-configuration-file)

For programmatic or advanced configuration, publish the config file:

```
php artisan vendor:publish --tag=writr-config
```

### Editor Settings

[](#editor-settings)

```
// config/writr.php
'editor' => [
    'placeholder' => 'Start writing your story...',
    'autofocus' => false,
    'readonly' => false,
    'min_height' => 300,
    'max_height' => null,
    'spellcheck' => true,
],
```

### Tools Configuration

[](#tools-configuration)

Each tool can be enabled/disabled and configured:

```
'tools' => [
    'header' => [
        'enabled' => true,
        'config' => [
            'levels' => [1, 2, 3, 4, 5, 6],
            'defaultLevel' => 2,
            'allowAnchor' => true,
        ],
    ],
    'image' => [
        'enabled' => true,
        'config' => [
            'endpoints' => [
                'byFile' => route('writr.upload.image'),
                'byUrl' => route('writr.upload.url'),
            ],
            'additionalRequestData' => [
                '_token' => csrf_token(),
            ],
            'field' => 'image',
            'types' => 'image/*',
            'captionPlaceholder' => 'Enter caption...',
        ],
    ],
    'table' => [
        'enabled' => true,
        'config' => [
            'rows' => 2,
            'cols' => 3,
            'withHeadings' => true,
        ],
    ],
    // ... more tools
],
```

### Feature Configuration

[](#feature-configuration)

```
'features' => [
    'drag_drop' => true,
    'undo_redo' => true,
    'dark_mode' => [
        'enabled' => true,
        'default' => 'auto', // 'light', 'dark', 'auto'
        'storage_key' => 'writr-theme',
    ],
    'live_preview' => true,
    'table_of_contents' => [
        'enabled' => true,
        'levels' => [1, 2, 3, 4, 5, 6],
        'position' => 'right', // 'left', 'right', 'top'
    ],
    'word_count' => [
        'enabled' => true,
        'position' => 'bottom', // 'top', 'bottom'
        'show_characters' => true,
        'show_words' => true,
        'show_reading_time' => true,
    ],
    'auto_save' => [
        'enabled' => false,
        'interval' => 30000, // 30 seconds
        'endpoint' => null,
        'debounce' => 1000,
    ],
],
```

📁 File Upload System
--------------------

[](#-file-upload-system)

### Upload Configuration

[](#upload-configuration)

```
// config/writr.php
'uploads' => [
    'disk' => 'public',
    'path' => 'writr/uploads',
    'max_file_size' => 10 * 1024 * 1024, // 10MB
    'allowed_extensions' => [
        'images' => ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg'],
        'documents' => ['pdf', 'doc', 'docx', 'txt', 'rtf'],
        'archives' => ['zip', 'rar', '7z'],
    ],
    'image_optimization' => [
        'enabled' => true,
        'quality' => 85,
        'max_width' => 1920,
        'max_height' => 1080,
    ],
],
```

### Custom Upload Handler

[](#custom-upload-handler)

Create your own upload endpoint:

```
// routes/web.php
Route::post('/custom-upload', [CustomUploadController::class, 'handle'])
    ->name('custom.upload')
    ->middleware(['auth', 'throttle:60,1']);

// CustomUploadController.php
public function handle(Request $request)
{
    $request->validate([
        'image' => 'required|image|max:10240', // 10MB
    ]);

    $file = $request->file('image');

    // Custom processing (resize, watermark, etc.)
    $processedImage = $this->processImage($file);

    $path = $processedImage->store('custom-uploads', 'public');

    return response()->json([
        'success' => 1,
        'file' => [
            'url' => Storage::url($path),
            'name' => $file->getClientOriginalName(),
            'size' => $file->getSize(),
            'caption' => '',
        ]
    ]);
}
```

### Upload Progress &amp; Validation

[](#upload-progress--validation)

```

function uploadProgress(percentComplete) {
    console.log('Upload progress:', percentComplete + '%');
    // Update progress bar, etc.
}

```

🔄 Content Processing
--------------------

[](#-content-processing)

### Working with Content

[](#working-with-content)

Writr stores content as JSON. Use the included service for processing:

```
use Rafaelogic\Writr\Services\WritrService;

class DocumentController extends Controller
{
    public function __construct(
        private WritrService $writr
    ) {}

    public function show(Document $document)
    {
        $content = json_decode($document->content, true);

        // Convert to HTML for display
        $html = $this->writr->toHtml($content);

        // Convert to Markdown
        $markdown = $this->writr->toMarkdown($content);

        // Extract plain text (for search, etc.)
        $plainText = $this->writr->toText($content);

        // Get word count and reading time
        $stats = $this->writr->getContentStats($content);
        // Returns: ['words' => 245, 'characters' => 1428, 'reading_time' => 1.2]

        // Generate table of contents
        $toc = $this->writr->generateToc($content);

        return view('documents.show', [
            'document' => $document,
            'html' => $html,
            'stats' => $stats,
            'toc' => $toc,
        ]);
    }
}
```

### Content Validation

[](#content-validation)

```
// Custom validation rule
$request->validate([
    'content' => [
        'required',
        'json',
        function ($attribute, $value, $fail) {
            $data = json_decode($value, true);

            // Validate structure
            if (!isset($data['blocks']) || !is_array($data['blocks'])) {
                $fail('Invalid content structure.');
            }

            // Validate content is not empty
            if (empty($data['blocks'])) {
                $fail('Content cannot be empty.');
            }

            // Validate each block
            foreach ($data['blocks'] as $block) {
                if (!isset($block['type']) || !isset($block['data'])) {
                    $fail('Invalid block structure.');
                }
            }
        }
    ]
]);
```

### Search Integration

[](#search-integration)

```
// Make content searchable
class Document extends Model
{
    protected $casts = [
        'content' => 'array',
    ];

    // Accessor for search indexing
    public function getSearchableContentAttribute()
    {
        return app(WritrService::class)->toText($this->content);
    }

    // Scope for searching
    public function scopeSearch($query, $term)
    {
        return $query->whereRaw(
            "JSON_UNQUOTE(JSON_EXTRACT(content, '$.blocks[*].data.text')) LIKE ?",
            ["%{$term}%"]
        );
    }
}
```

Advanced Features
-----------------

[](#advanced-features)

### Auto-save

[](#auto-save)

```

```

### Dark Mode

[](#dark-mode)

```

```

### Custom Styling

[](#custom-styling)

```
// config/writr.php
'theme' => [
    'css_variables' => [
        '--writr-primary-color' => '#your-color',
        '--writr-bg-color' => '#your-bg-color',
    ],
],
```

API Endpoints
-------------

[](#api-endpoints)

The package provides several API endpoints for editor functionality:

- `POST /writr/upload-image` - Upload images
- `POST /writr/upload-file` - Upload files
- `POST /writr/fetch-url` - Fetch URL metadata
- `POST /writr/preview` - Generate content preview
- `POST /writr/export` - Export content
- `POST /writr/auto-save` - Auto-save content

🎨 Frontend Integration
----------------------

[](#-frontend-integration)

### Direct JavaScript Usage

[](#direct-javascript-usage)

For advanced customization, use the JavaScript API directly:

```
import WritrEditor from './vendor/writr/js/writr.esm.js';

// Initialize editor
const editor = new WritrEditor({
    holder: 'editor-container',
    data: {
        blocks: []
    },
    tools: {
        // Custom tool configuration
    },
    features: {
        darkMode: true,
        autoSave: {
            enabled: true,
            interval: 15000,
            endpoint: '/api/auto-save'
        }
    },
    onChange: (data) => {
        console.log('Content changed:', data);
        // Handle changes
    },
    onReady: () => {
        console.log('Editor is ready');
    }
});

// Editor methods
editor.save().then(data => {
    console.log('Saved data:', data);
});

editor.clear();
editor.render(newData);
editor.focus();
```

### Custom Tools

[](#custom-tools)

Create your own Editor.js tools:

```
// CustomAlertTool.js
class CustomAlertTool {
    static get toolbox() {
        return {
            title: 'Alert',
            icon: '...'
        };
    }

    constructor({ data, api }) {
        this.data = data;
        this.api = api;
        this.wrapper = undefined;
    }

    render() {
        this.wrapper = document.createElement('div');
        this.wrapper.classList.add('custom-alert');

        const input = document.createElement('input');
        input.placeholder = 'Enter alert message...';
        input.value = this.data.text || '';
        input.addEventListener('input', (e) => {
            this.data.text = e.target.value;
        });

        this.wrapper.appendChild(input);
        return this.wrapper;
    }

    save() {
        return {
            text: this.data.text || '',
            level: this.data.level || 'info'
        };
    }

    validate(savedData) {
        return savedData.text && savedData.text.trim() !== '';
    }
}

// Register tool
const editor = new WritrEditor({
    tools: {
        alert: CustomAlertTool
    }
});
```

### Event Handling

[](#event-handling)

```
// Listen to editor events
editor.on('change', (data) => {
    // Content changed
    localStorage.setItem('draft', JSON.stringify(data));
});

editor.on('focus', () => {
    // Editor focused
    document.body.classList.add('editor-focused');
});

editor.on('blur', () => {
    // Editor lost focus
    document.body.classList.remove('editor-focused');
});

editor.on('tool-change', (toolName) => {
    // Active tool changed
    console.log('Active tool:', toolName);
});
```

🏗️ Development &amp; Building
-----------------------------

[](#️-development--building)

### Development Setup

[](#development-setup)

```
# Clone or install the package
composer require rafaelogic/writr

# Install frontend dependencies
cd vendor/rafaelogic/writr  # or your package directory
npm install

# Start development server
npm run dev

# Watch for changes
npm run watch
```

### Building Assets

[](#building-assets)

```
# Development build (with source maps)
npm run development

# Production build (optimized, minified)
npm run production

# Bundle build (standalone distribution)
npm run bundle
```

### Testing

[](#testing)

```
# Run PHP tests
composer test

# Run with coverage
composer test-coverage

# Run JavaScript tests
npm test

# Watch mode for JS tests
npm run test:watch

# Lint code
npm run lint
npm run lint:fix
```

### Project Structure

[](#project-structure)

```
writr/
├── config/writr.php              # Configuration file
├── src/                          # PHP source code
│   ├── WritrServiceProvider.php  # Service provider
│   ├── Components/               # Blade components
│   ├── Http/Controllers/         # Controllers
│   └── Services/                # Services
├── resources/
│   ├── js/                      # JavaScript source
│   │   ├── writr.js            # Main entry point
│   │   ├── editor/             # Editor modules
│   │   ├── tools/              # Custom tools
│   │   └── utils/              # Utilities
│   ├── css/writr.css           # Compiled CSS
│   ├── sass/writr.scss         # Sass source
│   └── views/                  # Blade templates
├── public/                     # Compiled assets
│   ├── js/writr.js            # Main bundle
│   ├── js/writr.min.js        # Minified bundle
│   ├── css/writr.css          # Compiled CSS
│   └── css/writr.min.css      # Minified CSS
└── tests/                     # Test files
    ├── Feature/               # Feature tests
    ├── Unit/                  # Unit tests
    └── frontend/              # JS tests

```

🚀 Performance &amp; Optimization
--------------------------------

[](#-performance--optimization)

### Performance Features

[](#performance-features)

- **Lazy Loading**: Tools and features load on-demand
- **Code Splitting**: Optimized bundle splitting for faster initial load
- **Memory Management**: Automatic cleanup prevents memory leaks
- **Debounced Events**: Auto-save and change events are intelligently debounced
- **Asset Optimization**: CSS/JS minification and compression
- **Caching**: Browser caching with versioning for static assets

### Optimization Tips

[](#optimization-tips)

```
// config/writr.php - Production settings
'performance' => [
    'lazy_load_tools' => true,
    'cache_assets' => true,
    'minify_output' => true,
    'debounce_delay' => 300,
    'memory_monitoring' => env('APP_ENV') === 'local',
],

// Image optimization
'uploads' => [
    'image_optimization' => [
        'enabled' => true,
        'quality' => 85,
        'progressive' => true,
        'strip_metadata' => true,
    ],
],
```

### Memory Management

[](#memory-management)

```
// Automatic memory cleanup
const editor = new WritrEditor({
    features: {
        memoryMonitoring: true, // Monitor memory usage
        autoCleanup: true,      // Automatic cleanup
        maxMemoryUsage: 50      // Max memory in MB
    }
});

// Manual cleanup
editor.destroy(); // Clean up when done
```

### Bundle Analysis

[](#bundle-analysis)

```
# Analyze bundle size
npm run bundle -- --analyze

# Check performance
npm run lighthouse
```

🌍 Browser Compatibility
-----------------------

[](#-browser-compatibility)

BrowserVersionStatusChrome70+✅ Full SupportFirefox65+✅ Full SupportSafari12+✅ Full SupportEdge79+✅ Full SupportOpera57+✅ Full SupportMobile Safari12+✅ Full SupportChrome Mobile70+✅ Full Support### Polyfills

[](#polyfills)

For older browsers, include polyfills:

```

```

🤝 Contributing
--------------

[](#-contributing)

We welcome contributions! Here's how to get started:

### Development Setup

[](#development-setup-1)

1. **Fork and Clone**

    ```
    git clone https://github.com/yourusername/writr.git
    cd writr
    ```
2. **Install Dependencies**

    ```
    composer install
    npm install
    ```
3. **Set Up Testing Environment**

    ```
    cd tests/TestApp
    composer install
    npm install
    ```
4. **Run Tests**

    ```
    # PHP tests
    composer test

    # JavaScript tests
    npm test

    # Full test suite
    npm run test:all
    ```

### Contribution Guidelines

[](#contribution-guidelines)

- **Code Style**: Follow PSR-12 for PHP, ESLint rules for JavaScript
- **Tests**: Add tests for new features and bug fixes
- **Documentation**: Update README and relevant docs
- **Commit Messages**: Use conventional commit format
- **Pull Requests**: Target the `develop` branch

### Development Workflow

[](#development-workflow)

1. Create a feature branch from `develop`
2. Make your changes with tests
3. Run the full test suite
4. Update documentation if needed
5. Submit a pull request

### Areas for Contribution

[](#areas-for-contribution)

- 🔧 **New Tools**: Create custom Editor.js tools
- 🎨 **Themes**: Design new editor themes
- 🌐 **Translations**: Add internationalization support
- 📚 **Documentation**: Improve guides and examples
- 🐛 **Bug Fixes**: Resolve issues and edge cases
- ⚡ **Performance**: Optimize loading and runtime performance

📄 License
---------

[](#-license)

This package is open-sourced software licensed under the [MIT license](LICENSE).

### Third-party Licenses

[](#third-party-licenses)

- [Editor.js](https://editorjs.io/) - Apache 2.0 License
- [Laravel](https://laravel.com/) - MIT License
- [Tailwind CSS](https://tailwindcss.com/) - MIT License

🆘 Support &amp; Community
-------------------------

[](#-support--community)

### Documentation &amp; Resources

[](#documentation--resources)

- 📖 **[Full Documentation](https://writr.dev/docs)** - Comprehensive guides and API reference
- 🎯 **[Demo &amp; Examples](demo.html)** - Interactive demo with all features
- 📚 **[API Reference](https://writr.dev/api)** - Complete API documentation
- 🏗️ **[Integration Guide](https://writr.dev/integration)** - Step-by-step Laravel integration

### Getting Help

[](#getting-help)

- 🐛 **[GitHub Issues](https://github.com/rafaelogic/writr/issues)** - Bug reports and feature requests
- 💬 **[Discussions](https://github.com/rafaelogic/writr/discussions)** - Community support and Q&amp;A
- 📧 **Email Support**:

### Community

[](#community)

- 🌟 **Star the repository** if you find it useful
- 🔄 **Share with others** who might benefit
- 🤝 **Contribute** improvements and new features
- 📝 **Write tutorials** and share your experience

🙏 Credits &amp; Acknowledgments
-------------------------------

[](#-credits--acknowledgments)

### Core Technologies

[](#core-technologies)

- **[Editor.js](https://editorjs.io/)** - The amazing block-style editor framework
- **[Laravel](https://laravel.com/)** - The elegant PHP framework
- **[Tailwind CSS](https://tailwindcss.com/)** - The utility-first CSS framework

### Special Thanks

[](#special-thanks)

- The Editor.js team for creating such a flexible and powerful editor
- The Laravel community for continuous inspiration and feedback
- All contributors who help make Writr better
- Early adopters and testers who provided valuable feedback

---

**Made with ❤️ for the Laravel community**

[Website](https://writr.dev) • [Documentation](https://writr.dev/docs) • [Demo](demo.html) • [GitHub](https://github.com/rafaelogic/writr)

###  Health Score

30

—

LowBetter than 64% of packages

Maintenance58

Moderate activity, may be stable

Popularity1

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

279d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/adeba72b4654df402e30e6f6f001b34308db553e170156abe344e7b7d20ed9cd?d=identicon)[rrafael](/maintainers/rrafael)

---

Top Contributors

[![rafaelogic](https://avatars.githubusercontent.com/u/5935096?v=4)](https://github.com/rafaelogic "rafaelogic (2 commits)")

---

Tags

laravelbladecomponenteditorwysiwygnotioneditorjs

###  Code Quality

TestsPHPUnit

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/rafaelogic-writr/health.svg)

```
[![Health](https://phpackages.com/badges/rafaelogic-writr/health.svg)](https://phpackages.com/packages/rafaelogic-writr)
```

###  Alternatives

[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9682.1M97](/packages/roots-acorn)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k12.1M99](/packages/laravel-pulse)[laravel/cashier

Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services.

2.5k25.9M107](/packages/laravel-cashier)[tightenco/jigsaw

Simple static sites with Laravel's Blade.

2.2k438.5k29](/packages/tightenco-jigsaw)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

245.2k](/packages/aedart-athenaeum)[yajra/laravel-datatables-editor

Laravel DataTables Editor plugin for Laravel 5.5+.

1186.1M2](/packages/yajra-laravel-datatables-editor)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
