# Pages Storefront

Storefront is a visual editing interface for the Pages addon that enables in-context editing of website content directly in a live preview.

## Overview

## Overview

The Storefront feature provides:
- **Live Preview**: Real-time preview of website pages within the Cockpit admin.
- **Visual Editing**: In-context editing of page components and content with a premium, modern overlay.
- **Device Simulation**: Realistic phone and tablet previews with device bezels and smooth transitions.
- **Bi-Directional Highlighting**: Hover over elements in the preview to edit, or hover over components in the admin sidebar to scroll to them in the preview.
- **Multi-Module Support**: Extensible architecture supporting Pages, Content, and Lokalize.

## Architecture

### Components

1. **Client Script** (`storefront.js`)
   - Injected into website pages when viewed through Storefront
   - Uses `ResizeObserver` for robust element tracking and positioning
   - Handles smooth scrolling and highlighting via `storefront:highlight`
   - Manages communication with the admin interface

2. **Admin Interface** (`admin/storefront.js`, `admin/storefront.css`)
   - Vue.js-based control panel with a component navigator sidebar
   - Manages iframe preview with device bezels (Phone, Tablet)
   - Handles save operations, preview updates, and reverse highlighting

3. **Module System** (`admin/modules/`)
   - Pluggable architecture for different content types
   - Currently includes: Pages, Content, Lokalize modules

## How It Works

### 1. Activation Flow

```
User clicks Storefront trigger → Opens /pages/storefront/frame?src=URL
                              → Loads page in iframe with storefront.js
                              → Scans for editable elements
                              → Enables visual editing
```

### 2. Communication Protocol

The system uses postMessage for secure iframe communication:

```javascript
// Messages from client to admin
storefront:load    - Page loaded with metadata
storefront:unload  - Page unloading
storefront:notify  - Show notification

// Messages from admin to client  
storefront:highlight - Highlight specific element
storefront:refresh   - Reload the preview
```

### 3. Element Detection

Storefront scans for elements with specific data attributes:

```html
<div data-sf-module="pages"           <!-- Module that handles this content -->
     data-sf-context="page"           <!-- Context type -->
     data-sf-data='{"id":"123"}'      <!-- Element data (JSON) -->
     data-sf-id="unique-id"           <!-- Unique identifier -->
     data-sf-title="Section Title">   <!-- Optional title -->
  <!-- Content -->
</div>
```

## Integration Guide

### For Theme Developers

#### 1. Basic Integration

Add Storefront data attributes to editable areas in your templates:

```html
<!-- For layout components -->
<div data-sf-module="pages" 
     data-sf-context="page"
     data-sf-data='{"id":"<?=$component['id']?>"}'
     data-sf-id="component-<?=$component['id']?>">
    <?php echo $component['html']; ?>
</div>

<!-- For content items -->
<article data-sf-module="content"
         data-sf-context="collection" 
         data-sf-data='{"collection":"blog","id":"<?=$post['_id']?>"}'
         data-sf-id="post-<?=$post['_id']?>">
    <h2><?=$post['title']?></h2>
    <div><?=$post['content']?></div>
</article>

<!-- For translations -->
<span data-sf-module="lokalize"
      data-sf-context="translation"
      data-sf-data='{"key":"home.welcome","locale":"en"}'
      data-sf-id="trans-home-welcome">
    <?=$t('home.welcome')?>
</span>
```

#### 2. Dynamic Content

For dynamically loaded content, trigger an update:

```javascript
// After loading new content via AJAX
if (window.storefront && window.storefront.update) {
    window.storefront.update();
}
```

#### 3. Custom Styling

The Storefront adds these classes during interaction:

```css
/* Element with active Storefront */
[data-storefront-id] {
    /* Your styles for editable elements */
}

/* Storefront highlight overlay */
storefront-highlight[active] {
    /* Customize highlight appearance */
}
```

### For Module Developers

#### Creating a Custom Storefront Module

1. **Register your module** in `admin/storefront.js`:

```javascript
import mymodule from './modules/mymodule/mymodule.js';

window.Storefront = {
    modules: {
        pages,
        content,
        lokalize,
        mymodule  // Add your module
    }
};
```

2. **Create module component** at `admin/modules/mymodule/vue-components/mymodule.js`:

```javascript
export default {
    props: {
        items: Array,      // Data from data-sf-module scan
        locale: String     // Current locale
    },
    
    methods: {
        edit(id, context) {
            // Handle edit action
            const item = this.items.find(i => i.spotId === id);
            
            // Open your edit dialog
            VueView.ui.modal('mymodule:assets/dialogs/edit.js', {item}, {
                save: (updated) => {
                    // Save logic
                    this.$emit('storefront:refresh');
                }
            });
        }
    },
    
    template: /*html*/`
        <div>
            <h3>My Module</h3>
            <div v-for="item in items">
                <!-- Module UI -->
            </div>
        </div>
    `
}
```

3. **Mark content as editable** in your frontend:

```html
<div data-sf-module="mymodule"
     data-sf-context="item"
     data-sf-data='{"id":"123","type":"widget"}'
     data-sf-id="widget-123">
    <!-- Your content -->
</div>
```

## API Reference

### Client API (storefront.js)

```javascript
// Available after DOM load
window.storefront = {
    // Update/rescan for editable elements
    update(),
    
    // Send message to admin
    send(event, data),
    
    // Show notification in admin
    notify(message, status, timeout),
    
    // Data from last scan
    data: {
        modules: {
            [moduleName]: {
                [context]: [items]
            }
        }
    }
}
```

### Admin API

```javascript
// In Vue components
methods: {
    // Reload preview iframe
    reloadIframe(),
    
    // Send message to preview
    send(event, data),
    
    // Highlight element in preview
    highlight(item)
}

// Events
'storefront:refresh' // Trigger preview reload
```

## Configuration

### Permissions

Users need the `pages/manage` permission to access Storefront.

### Viewport Modes

Default viewport sizes:
- **Phone**: 360px × 640px
- **Tablet**: 768px × 1024px  
- **Desktop**: 100% × 100%

## Tips & Best Practices

1. **Performance**
   - Minimize the number of editable elements on a single page
   - Use specific contexts to group related items
   - Avoid deeply nested editable elements

2. **Data Attributes**
   - Keep `data-sf-data` JSON small and simple
   - Use meaningful IDs in `data-sf-id`
   - Add `data-sf-title` for better UX

3. **Styling**
   - Ensure editable elements have sufficient padding for the highlight
   - Avoid `position: fixed` on editable elements
   - Test with different viewport sizes

4. **Security**
   - Always validate edit permissions server-side
   - Sanitize any data passed through `data-sf-data`
   - Don't expose sensitive information in data attributes

## Troubleshooting

### Elements not appearing in Storefront

1. Check data attributes are properly formatted
2. Ensure JSON in `data-sf-data` is valid
3. Verify the module is registered in `admin/storefront.js`
4. Check browser console for errors

### Preview not updating

1. Check for JavaScript errors in the preview
2. Verify postMessage communication isn't blocked
3. Ensure the preview URL is accessible
4. Try manually refreshing with the refresh button

### Edit actions not working

1. Verify the module's `edit()` method is implemented
2. Check permissions for the content type
3. Ensure the edit dialog/component exists
4. Look for errors in the browser console

## Limitations

- Only works with content served from the same domain (CORS)
- Requires JavaScript enabled in preview pages
- Some complex interactions may not work in iframe
- Limited to postMessage communication (no direct DOM access)

