@arandana/landing-editor
v1.6.1
Published
A React library with Craft.js integration for building landing page editors
Downloads
53
Maintainers
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-editorPeer 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:
- Edición (Editor Mode): Full editing capabilities with drag-and-drop, component settings, and customization
- Vista previa (Preview Mode): Read-only view showing exactly what was configured in editor mode
- 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-maldonadoAPI 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}/settingsResponse: LandingSettings object containing profile, services, social links, and theme.
2. Fetch User Profile
GET /api/v1/users/{tenantSlug}/profileResponse: UserProfile object with user details.
3. Fetch Services
GET /api/v1/users/{tenantSlug}/servicesResponse: Array of Service objects.
4. Fetch Social Links
GET /api/v1/users/{tenantSlug}/social-linksResponse: Array of SocialLink objects.
5. Save Editor Customizations
PUT /api/v1/landing/{tenantSlug}/editor-dataRequest Body:
{
"editorData": {
/* serialized CraftJS editor state */
},
"updatedAt": "2025-10-23T10:30:00Z"
}6. Book a Service
POST /api/v1/users/{tenantSlug}/services/{serviceId}/bookRequest 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
- User drags component (e.g., "Tarjeta de Presentación") from toolbar
- Editor detects component type and fetches corresponding backend data
- Component is created with backend data as initial props
- 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" immediatelyCustomization
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:
- Install dependencies with pnpm
- Build the library using
pnpm run build:lib - Publish the package to GitHub Packages
Creating a Release from GitHub Web Interface
- Go to the GitHub repository
- Click on "Releases" in the right sidebar or go to
/releases - Click "Create a new release"
- Choose or create a new tag (e.g.,
v1.0.0,v1.1.0) - Add a release title and description
- 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:
- Index / overview
- Getting started guide (EN)
- Quick start (ES)
- Setup guide (ES)
- Implementation summary (ES)
- Troubleshooting
- Changes made / changelog
- Implementation README
- Implementation complete notes
If you can't find a specific document, check the docs/ folder or open an issue in the repository.
