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

@arandana/landing-editor

v1.6.1

Published

A React library with Craft.js integration for building landing page editors

Downloads

53

Readme

@meowlnir/landing-editor

A modern React 18 + TypeScript library powered by Vite and Craft.js for building beautiful landing page editors.
Simple integration, full type safety, and flexible components for your projects.


Features

  • Editor Mode: Full-featured Craft.js editor with drag-and-drop, properties panel, and save functionality
  • Preview Mode: Read-only display for rendering editor content
  • Render Mode: Display components with simulated API data (WYSIWYG demo mode)
  • React 18: Built using the latest React API
  • TypeScript: Full type definitions for IntelliSense and safety
  • Ready for Production: UMD and ES modules, TypeScript declarations included

Installation

Install via pnpm (recommended):

pnpm add @meowlnir/landing-editor

Peer Dependencies:
Make sure you have React 18 and React DOM installed in your project:

pnpm add react@^18.0.0 react-dom@^18.0.0

CDN Usage (CSS only)

If you only need the compiled CSS file, you can use a CDN without installing the full package:

<!-- jsDelivr CDN -->
<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/@meowlnir/landing-editor@latest/dist/style.css"
/>

<!-- or Unpkg CDN -->
<link
  rel="stylesheet"
  href="https://unpkg.com/@meowlnir/landing-editor@latest/dist/style.css"
/>

This exposes only the compiled styles, not the source code.


Usage

Editor Component

import { Editor } from "@meowlnir/landing-editor";

const handleSave = (data: string) => {
  // Save data to your backend or localStorage
};

export default function MyEditorApp() {
  return (
    <Editor
      initialData={savedData} // Optional: load previously saved data
      onSave={handleSave} // Optional: callback when user saves
    />
  );
}

Preview Component

import { Preview } from "@meowlnir/landing-editor";

export default function MyPreview() {
  return (
    <Preview
      data={savedData} // Optional: data to display
      className="my-preview" // Optional: CSS class
      style={{ padding: "20px" }} // Optional: inline styles
    />
  );
}

Render Component

The Render component displays your landing page with simulated API data, showing how it would look when consuming real backend data.

import { Render } from "@meowlnir/landing-editor";

export default function MyRender() {
  return (
    <Render
      data={savedData} // Optional: editor data to render
      className="my-render" // Optional: CSS class
      style={{ padding: "20px" }} // Optional: inline styles
    />
  );
}

API Reference

Editor

| Prop | Type | Description | | ------------- | ------------------------ | ------------------------------ | | initialData | string | Serialized editor data to load | | onSave | (data: string) => void | Callback when user saves |

Preview

| Prop | Type | Description | | --------------- | ------------------------------ | -------------------------- | | data | string | Serialized data to display | | className | string | CSS class for styling | | style | React.CSSProperties | Inline styles | | onButtonClick | (buttonText: string) => void | Button click handler |

Render

| Prop | Type | Description | | ----------- | --------------------- | ----------------------------------------------- | | data | string | Serialized editor data to render with mock data | | className | string | CSS class for styling | | style | React.CSSProperties | Inline styles |


Available Components

  • Container: Layout container, customizable background
  • Text: Editable text with font size
  • Button: Interactive button with color options

Hero Sections

  • Hero Simple: Clean profile-style hero with avatar
  • Hero Gradient: Hero with gradient background
  • Hero Banner: Hero with banner image
  • Hero Card: Card-style hero presentation

Content Blocks

  • Services Block: Display services with pricing, ratings, and booking
  • Social Links Block: Social media icons and links
  • Rich Text Block: HTML content editor
  • Video Block: Embed videos (YouTube, Vimeo, etc.)

You can easily extend built-in components using Craft.js resolver.

Editor Modes

The editor includes three distinct modes accessible via tabs:

  1. Edición (Editor Mode): Full editing capabilities with drag-and-drop, component settings, and customization
  2. Vista previa (Preview Mode): Read-only view showing exactly what was configured in editor mode
  3. Render Mode: Displays components with simulated API data, demonstrating how the page would look when consuming real backend services

This "What You See Is What You Get" (WYSIWYG) approach ensures your designs match production output.


Data Services & Backend Integration

Environment Configuration

Configure your backend connection via .env file:

# Data mode: 'fake' for demo data, 'real' for production API
VITE_DATA_MODE=fake

# Backend API base URL (only required for real mode)
VITE_API_BASE_URL=https://api.dashflow.com

# Default tenant slug for demo mode
VITE_DEFAULT_TENANT=roger-maldonado

API Endpoints (Production Mode)

When VITE_DATA_MODE=real, the editor expects these endpoints on your backend:

1. Fetch Landing Settings

GET /api/v1/landing/{tenantSlug}/settings

Response: LandingSettings object containing profile, services, social links, and theme.

2. Fetch User Profile

GET /api/v1/users/{tenantSlug}/profile

Response: UserProfile object with user details.

3. Fetch Services

GET /api/v1/users/{tenantSlug}/services

Response: Array of Service objects.

4. Fetch Social Links

GET /api/v1/users/{tenantSlug}/social-links

Response: Array of SocialLink objects.

5. Save Editor Customizations

PUT /api/v1/landing/{tenantSlug}/editor-data

Request Body:

{
  "editorData": {
    /* serialized CraftJS editor state */
  },
  "updatedAt": "2025-10-23T10:30:00Z"
}

6. Book a Service

POST /api/v1/users/{tenantSlug}/services/{serviceId}/book

Request Body: Service booking details (custom structure).

Auto-Injection of Backend Data

When users drag components from the toolbar, the editor automatically injects backend data into those components at creation time. This ensures seamless integration between editor and backend without manual steps.

How It Works

  1. User drags component (e.g., "Tarjeta de Presentación") from toolbar
  2. Editor detects component type and fetches corresponding backend data
  3. Component is created with backend data as initial props
  4. User sees data immediately - no placeholder phase

Components with Auto-Injection

| Component | Backend Data Source | Props Injected | | ---------------- | ------------------- | -------------------------------------------------- | | HeroSimple | UserProfile | name, role, description, profileImage | | HeroCard | UserProfile | name, role, description, profileImage | | HeroGradient | UserProfile | title, subtitle | | HeroBanner | UserProfile | title, subtitle, description, profileImage | | ServicesBlock | Service[] | services | | SocialLinksBlock | SocialLink[] | links | | VideoBlock | Video[] | videoUrl, title |

Example: Dragging a Hero

// When user drags HeroCard from toolbar:
// 1. Toolbar detects HeroCard is a Hero component
// 2. Gets backendSettings.profile: { fullName: "Roger Maldonado", profession: "Senior Engineer", ... }
// 3. Creates component with these props:
//
//   <HeroCard
//     name="Roger Maldonado"
//     role="Senior Engineer"
//     description="10+ years of experience..."
//     profileImage="https://..."
//   />
//
// 4. User sees "Roger Maldonado" immediately

Customization

Users can still customize injected data:

  • Edit component properties in the sidebar
  • Changes are saved to the editor state
  • User customizations take priority over backend data when rendering

UserProfile

interface UserProfile {
  id: string;
  slug: string;
  fullName: string;
  email: string;
  bio?: string;
  profession?: string;
  profileImage?: string;
  coverImage?: string;
  phone?: string;
  location?: string;
}

Service

interface Service {
  id: string;
  name: string;
  description: string;
  price: number;
  currency: string;
  duration: number;
  durationUnit: string;
  rating?: number;
  reviews?: number;
  icon?: string;
  color?: string;
  available: boolean;
  popular?: boolean;
  category?: string;
}

SocialLink

interface SocialLink {
  platform: string; // e.g., 'twitter', 'linkedin', 'instagram'
  url: string;
  enabled: boolean;
  icon?: string;
  order?: number;
}

LandingSettings (Complete Response)

interface LandingSettings {
  profile: UserProfile;
  services: Service[];
  socialLinks: SocialLink[];
  theme?: {
    primaryColor?: string;
    secondaryColor?: string;
    accentColor?: string;
    backgroundColor?: string;
    fontFamily?: string;
  };
  seo?: {
    title?: string;
    description?: string;
    keywords?: string[];
    ogImage?: string;
  };
  customData?: Record<string, any>;
}

Authentication

The API client automatically includes:

  • Authorization Header: Authorization: Bearer {AUTH_TOKEN} (when available)
  • Tenant Header: X-Tenant-Slug: {tenantSlug}

Configure auth token via environment or provide it when initializing the data provider.

Data Merge Strategy

When rendering, backend data is merged with editor customizations:

  • Backend provides dynamic content: profiles, services, social links
  • Editor provides layout, styling, and component configuration
  • Editor customizations take precedence for specific field overrides

Example: If a user customizes the hero title in the editor, that value is used. Otherwise, the backend profile name is displayed.


TypeScript Support

Type definitions are included for all exported components and props.

import {
  EditorProps,
  PreviewProps,
  RenderProps,
} from "@meowlnir/landing-editor";

Example

A minimal example to get you started:

import { Editor, Preview, Render } from "@meowlnir/landing-editor";

function App() {
  const [data, setData] = React.useState("");

  return (
    <>
      <Editor onSave={setData} />
      <Preview data={data} />
      <Render data={data} />
    </>
  );
}

The Editor component includes built-in tabs for switching between editor, preview, and render modes, so you typically only need to use the Editor component in your application.


Publishing and Releases

This package is automatically published to GitHub Packages when a new release is created. The GitHub Actions workflow will:

  1. Install dependencies with pnpm
  2. Build the library using pnpm run build:lib
  3. Publish the package to GitHub Packages

Creating a Release from GitHub Web Interface

  1. Go to the GitHub repository
  2. Click on "Releases" in the right sidebar or go to /releases
  3. Click "Create a new release"
  4. Choose or create a new tag (e.g., v1.0.0, v1.1.0)
  5. Add a release title and description
  6. Click "Publish release"

Creating a Release from Terminal

# Create and push a tag
git tag v1.0.0
git push origin v1.0.0

# Or create a release using GitHub CLI
gh release create v1.0.0 --title "v1.0.0" --notes "Release notes here"

The workflow will automatically trigger when:

  • A release is published with any tag
  • A tag matching the pattern v* is pushed (e.g., v1.0.0, v2.1.3)

License

MIT

Support

If you have questions or issues, please open an issue in the GitHub repository.

Documentation

The detailed implementation and setup guides have been moved to the docs/ directory. Useful files:

If you can't find a specific document, check the docs/ folder or open an issue in the repository.