{"filename":"beefreeSDK-nocode-content-editor-cursorrules-prompt-file.mdc","content":"---\ndescription: \"Cursor rules for embedding Beefree SDK's no-code content editors (for emails, pages, and popups) into a web application.\"\nglobs: **/*\nalwaysApply: false\n---\n# Beefree SDK Guidelines\nGuidelines and best practices for building applications with [Beefree SDK](https://docs.beefree.io/beefree-sdk), including installation, authentication, configuration, customization, and template management.\n\n## Installation Guidelines\n\n### Package Installation\n- Install the Beefree SDK package using npm or yarn:\n  ```bash\n  npm install @beefree.io/sdk\n  # or\n  yarn add @beefree.io/sdk\n  ```\n\n### Dependencies\n- Beefree SDK requires the following core dependencies:\n  ```json\n  {\n    \"dependencies\": {\n      \"@beefree.io/sdk\": \"^9.0.2-fix-optional-url-config.0\",\n      \"axios\": \"^1.10.0\",\n      \"express\": \"^5.1.0\",\n      \"cors\": \"^2.8.5\",\n      \"dotenv\": \"^17.2.0\"\n    }\n  }\n  ```\n\n### Environment Setup\n- Create a `.env` file in your project root with your Beefree credentials:\n  ```env\n  BEE_CLIENT_ID=your_client_id_here\n  BEE_CLIENT_SECRET=your_client_secret_here\n  ```\n\n## Authentication Guidelines\n\n### Proxy Server Setup\n- ALWAYS use a proxy server for authentication to protect your credentials\n- Create a proxy server file (e.g., `proxy-server.js`) to handle authentication:\n  ```javascript\n  import express from 'express';\n  import cors from 'cors';\n  import axios from 'axios';\n  import dotenv from 'dotenv';\n\n  dotenv.config();\n\n  const app = express();\n  const PORT = 3001;\n\n  app.use(cors());\n  app.use(express.json());\n\n  const BEE_CLIENT_ID = process.env.BEE_CLIENT_ID;\n  const BEE_CLIENT_SECRET = process.env.BEE_CLIENT_SECRET;\n\n  // V2 Auth Endpoint\n  app.post('/proxy/bee-auth', async (req, res) => {\n    try {\n      const { uid } = req.body;\n      \n      const response = await axios.post(\n        'https://auth.getbee.io/loginV2',\n        {\n          client_id: BEE_CLIENT_ID,\n          client_secret: BEE_CLIENT_SECRET,\n          uid: uid || 'demo-user'\n        },\n        { headers: { 'Content-Type': 'application/json' } }\n      );\n      \n      res.json(response.data);\n    } catch (error) {\n      console.error('Auth error:', error.message);\n      res.status(500).json({ error: 'Failed to authenticate' });\n    }\n  });\n\n  app.listen(PORT, () => {\n    console.log(`Proxy server running on http://localhost:${PORT}`);\n  });\n  ```\n\n### Authentication Process\n- Use the V2 authentication endpoint: `https://auth.getbee.io/loginV2`\n- Pass the ENTIRE API response to the Beefree SDK, not just the token\n- Example authentication call:\n  ```typescript\n  const token = await fetch('http://localhost:3001/proxy/bee-auth', {\n    method: 'POST',\n    headers: { 'Content-Type': 'application/json' },\n    body: JSON.stringify({ uid: 'demo-user' })\n  }).then(res => res.json());\n  ```\n\n## Container Setup Guidelines\n\n### HTML Container\n- Create a dedicated container element for the Beefree SDK:\n  ```html\n  <div id=\"beefree-sdk-container\"></div>\n  ```\n\n### CSS Styling\n- Style the container to ensure proper display:\n  ```css\n  #beefree-sdk-container {\n    position: absolute;\n    top: 0px;\n    bottom: 0px;\n    left: 0px;\n    right: 0px;\n    height: 600px;\n    width: 90%;\n    margin: 20px auto;\n    border: 1px solid #ddd;\n    border-radius: 8px;\n  }\n  ```\n\n### React Container\n- For React applications, the following code snippet shows an example using refs to manage the container:\n  ```typescript\n  const containerRef = useRef<HTMLDivElement>(null);\n\n  return (\n    <div\n      id=\"beefree-react-demo\"\n      ref={containerRef}\n      style={{\n        height: '600px',\n        width: '90%',\n        margin: '20px auto',\n        border: '1px solid #ddd',\n        borderRadius: '8px'\n      }}\n    />\n  );\n  ```\n\n## Configuration Guidelines\n\n### Required Configuration Parameters\n- ALWAYS include the `container` parameter in your configuration:\n  ```typescript\n  const beeConfig = {\n    container: 'beefree-sdk-container', // Required\n    language: 'en-US'\n  };\n  ```\n\n### Optional Configuration Parameters\n- Customize your SDK with optional parameters:\n  ```typescript\n  const beeConfig = {\n    container: 'beefree-sdk-container', // Required\n    language: 'en-US',\n    specialLinks: [\n      {\n        type: \"unsubscribe\",\n        label: \"Unsubscribe\",\n        link: \"http://[unsubscribe]/\",\n      },\n      {\n        type: \"subscribe\",\n        label: \"Subscribe\",\n        link: \"http://[subscribe]/\",\n      },\n    ],\n    mergeTags: [\n      {\n        name: \"First Name\",\n        value: \"[first_name]\",\n      },\n      {\n        name: \"Last Name\",\n        value: \"[last_name]\",\n      },\n      {\n        name: \"Email\",\n        value: \"[email]\",\n      },\n    ]\n  };\n  ```\n\n### Callback Functions\n- Implement essential callback functions for proper functionality:\n  ```typescript\n  const beeConfig = {\n    container: 'beefree-sdk-container',\n    onSave: function (jsonFile, htmlFile) {\n      console.log(\"Template saved:\", jsonFile);\n      // Implement custom save logic here\n    },\n    onAutoSave: function (jsonFile) {\n      console.log(\"Auto-saving template...\");\n      localStorage.setItem(\"email.autosave\", jsonFile);\n    },\n    onSend: function (htmlFile) {\n      console.log(\"Email ready to send:\", htmlFile);\n      // Implement custom send logic here\n    },\n    onError: function (errorMessage) {\n      console.error(\"Beefree SDK error:\", errorMessage);\n      // Handle errors appropriately\n    }\n  };\n  ```\n\n## SDK Initialization Guidelines\n\n### Basic Initialization\n- Initialize the Beefree SDK with proper error handling:\n  ```typescript\n  async function initializeBeefree(authResponse) {\n    try {\n      const bee = new BeefreeSDK(authResponse);\n      bee.start(beeConfig, {});\n      console.log('Beefree SDK initialized successfully');\n    } catch (error) {\n      console.error('Failed to initialize Beefree SDK:', error);\n    }\n  }\n  ```\n\n### React Integration\n- For React applications, the following code snippet shows an example using useEffect for initialization:\n  ```typescript\n  useEffect(() => {\n    async function initializeEditor() {\n      const beeConfig = {\n        container: 'beefree-react-demo',\n        language: 'en-US',\n        onSave: (pageJson: string, pageHtml: string, ampHtml: string | null, templateVersion: number, language: string | null) => {\n          console.log('Saved!', { pageJson, pageHtml, ampHtml, templateVersion, language });\n        },\n        onError: (error: unknown) => {\n          console.error('Error:', error);\n        }\n      };\n\n      const token = await fetch('http://localhost:3001/proxy/bee-auth', {\n        method: 'POST',\n        headers: { 'Content-Type': 'application/json' },\n        body: JSON.stringify({ uid: 'demo-user' })\n      }).then(res => res.json());\n\n      const bee = new BeefreeSDK(token);\n      bee.start(beeConfig, {});\n    }\n\n    initializeEditor();\n  }, []);\n  ```\n\n## Template Loading Guidelines\n\n### Loading Templates\n- Use the `start()` method with template data to load existing templates:\n  ```typescript\n  // Load template from localStorage\n  const selectedTemplate = JSON.parse(localStorage.getItem('currentEmailData'));\n  \n  if (selectedTemplate) {\n    beefreeSDKInstance.start(selectedTemplate);\n    console.log('Loaded template from localStorage');\n  } else {\n    // Start with empty template\n              beefreeSDKInstance.start();\n          console.log('Started with empty template');\n  }\n  ```\n\n### Template Storage\n- Store templates in localStorage for persistence while testing:\n  ```typescript\n  // Save template data\n  localStorage.setItem('currentEmailData', JSON.stringify(templateData));\n  localStorage.setItem('currentEmailName', emailName);\n  \n  // Load template data\n  const emailData = localStorage.getItem('currentEmailData');\n  const emailName = localStorage.getItem('currentEmailName');\n  ```\n\n### Autosave Functionality\n- Implement autosave to prevent data loss:\n  ```typescript\n  onAutoSave: function (jsonFile) {\n    console.log(\"Auto-saving template...\");\n    localStorage.setItem(\"email.autosave\", jsonFile);\n  }\n  ```\n\n## HTML Import Guidelines\n\n### HTML Importer API\n- Use the HTML Importer API to convert existing HTML templates to Beefree SDK format\n- API endpoint: `https://api.getbee.io/v1/conversion/html-to-json`\n- Reference: [HTML Importer API Documentation](https://docs.beefree.io/beefree-sdk/apis/html-importer-api/import-html)\n\n### Import Process\n- Convert HTML templates to Beefree SDK's native JSON format:\n  ```javascript\n  const response = await fetch('https://api.getbee.io/v1/conversion/html-to-json', {\n    method: 'POST',\n    headers: {\n      \"Authorization\": \"Bearer Enter Dev Console API Key as Bearer token\",\n      \"Content-Type\": \"text/html\"\n    },\n    body: \"<!DOCTYPE html><html><body><h1>Hello World</h1></body></html>\"\n  }); \n  const data = await response.json();\n  ```\n\n### Loading Imported Templates\n- Load imported templates into the Beefree SDK:\n  ```typescript\n  const importedTemplate = await importHtmlTemplate(htmlContent);\n  beefreeSDK.start(importedTemplate);\n  ```\n\n## Error Handling Guidelines\n\n### onError Callback\n- ALWAYS implement the `onError` callback to handle SDK errors:\n  ```typescript\n  onError: function (errorMessage) {\n    console.error(\"Beefree SDK error:\", errorMessage);\n    // Display user-friendly error message\n    document.getElementById('beefree-sdk-container').innerHTML = \n      '<div class=\"error\">Error loading Beefree SDK: ' + errorMessage.message + '</div>';\n  }\n  ```\n\n### Authentication Error Handling\n- Handle authentication failures gracefully:\n  ```typescript\n  function getBeeToken(callback) {\n    fetch('/api/beefree/auth', {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json' },\n      body: JSON.stringify({ uid: beeConfig.uid })\n    })\n    .then(response => {\n      if (!response.ok) throw new Error('Auth failed: ' + response.status);\n      return response.json();\n    })\n    .then(data => {\n      callback(data);\n    })\n    .catch(error => {\n      console.error('Error getting Beefree token:', error);\n      document.getElementById('beefree-sdk-container').innerHTML = \n        '<div class=\"error\">Failed to authenticate with Beefree. Please check your credentials and try again.</div>';\n    });\n  }\n  ```\n\n## Template Change Tracking Guidelines\n\n### Track Message Changes\n- Implement template change tracking to monitor changes made by end users\n- Reference: [Track Message Changes Documentation](https://docs.beefree.io/beefree-sdk/getting-started/tracking-message-changes)\n\n### Change Detection\n- Use the `onChange` callback to track template changes:\n  ```typescript\n  onChange: function (jsonFile, response) {\n  console.log('json', jsonFile);\n  console.log('response', response);\n    },\n  ```\n\n## Customization Guidelines\n\n### UI Customization\nCustomize the Beefree SDK appearance with:\n- [Customized Themes](https://docs.beefree.io/beefree-sdk/other-customizations/appearance/themes)\n- [Custom CSS](https://docs.beefree.io/beefree-sdk/other-customizations/appearance/custom-css) \n\n### Language Customization\n- Set the language for internationalization:\n  ```typescript\n  const beeConfig = {\n    container: 'beefree-sdk-container',\n    language: 'en-US', // or 'es-ES', 'fr-FR', etc.\n  };\n  ```\n\n### Merge Tags and Special Links\n- Configure merge tags and special links for email personalization:\n  ```typescript\n  const beeConfig = {\n    container: 'beefree-sdk-container',\n    mergeTags: [\n      { name: \"First Name\", value: \"[first_name]\" },\n      { name: \"Last Name\", value: \"[last_name]\" },\n      { name: \"Email\", value: \"[email]\" },\n      { name: \"Company\", value: \"[company]\" }\n    ],\n    specialLinks: [\n      { type: \"unsubscribe\", label: \"Unsubscribe\", link: \"http://[unsubscribe]/\" },\n      { type: \"subscribe\", label: \"Subscribe\", link: \"http://[subscribe]/\" },\n      { type: \"webview\", label: \"View in Browser\", link: \"http://[webview]/\" }\n    ]\n  };\n  ```\n### Other Customizations\nReference the official [Beefree SDK technical documentation](https://docs.beefree.io/beefree-sdk) for a comprehnsive reference of possible customizations.  \n\n## Best Practices\n\n### Performance Optimization\n- Initialize the Beefree SDK only when it is actually needed in your application.\n- Properly clean up SDK resources when they are no longer required (e.g., when navigating away or closing the editor).\n- Handle errors gracefully to prevent application crashes or unexpected behavior.\n\n### Security\n- **Never** expose your Beefree SDK client credentials in any frontend or public code.\n- Always use a secure backend or proxy server to handle authentication and sensitive operations.\n- Validate and sanitize all user inputs before passing them to the SDK to prevent security vulnerabilities.\n\n### User Experience\n- Show appropriate loading indicators while the SDK is initializing or performing operations.\n- Display clear and helpful error messages to users if something goes wrong.\n- Implement automatic saving or progress tracking to prevent data loss.\n\n### Code Organization\n- Keep SDK configuration separate from initialization and business logic for better maintainability.\n- Use strong typing (e.g., TypeScript or similar) where possible to improve code safety and clarity.\n- Ensure robust error handling throughout your integration, regardless of the tech stack or framework used.\n\n## Examples\n\n### Complete React Component\nReference the full project at [beefree-react-demo](https://github.com/BeefreeSDK/beefree-react-demo).\n```typescript\nimport { useEffect, useRef } from 'react';\nimport BeefreeSDK from '@beefree.io/sdk';\n\nexport default function BeefreeEditor() {\n  const containerRef = useRef<HTMLDivElement>(null);\n\n  useEffect(() => {\n    async function initializeEditor() {\n      const beeConfig = {\n        container: 'beefree-react-demo',\n        language: 'en-US',\n        onSave: (pageJson: string, pageHtml: string, ampHtml: string | null, templateVersion: number, language: string | null) => {\n          console.log('Saved!', { pageJson, pageHtml, ampHtml, templateVersion, language });\n        },\n        onError: (error: unknown) => {\n          console.error('Error:', error);\n        }\n      };\n\n      const token = await fetch('http://localhost:3001/proxy/bee-auth', {\n        method: 'POST',\n        headers: { 'Content-Type': 'application/json' },\n        body: JSON.stringify({ uid: 'demo-user' })\n      }).then(res => res.json());\n\n      const bee = new BeefreeSDK(token);\n      bee.start(beeConfig, {});\n    }\n\n    initializeEditor();\n  }, []);\n\n  return (\n    <div\n      id=\"beefree-react-demo\"\n      ref={containerRef}\n      style={{\n        height: '600px',\n        width: '90%',\n        margin: '20px auto',\n        border: '1px solid #ddd',\n        borderRadius: '8px'\n      }}\n    />\n  );\n}\n```\n\n### Complete HTML Implementation\nReference the complete project at Beefree SDK [multiple-versions-concept](https://github.com/BeefreeSDK/beefree-sdk-simple-schema/tree/main/multiple-versions-concept).\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <title>Beefree SDK - Email Builder</title>\n    <meta charset=\"utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <style type=\"text/css\">\n      #beefree-sdk-container {\n        position: absolute;\n        top: 0px;\n        bottom: 0px;\n        left: 0px;\n        right: 0px;\n      }\n    </style>\n  </head>\n  <body>\n    <div id=\"beefree-sdk-container\"></div>\n    <!-- Bundle the official @beefree.io/sdk package and expose BeefreeSDK from your app entrypoint. -->\n    <script type=\"text/javascript\">\n      const beeConfig = {\n            container: 'beefree-sdk-container',\n    uid: 'demo-user-' + Date.now(),\n    language: 'en-US',\n        onSave: function (jsonFile, htmlFile) {\n          console.log(\"Template saved:\", jsonFile);\n        },\n        onError: function (errorMessage) {\n          console.error(\"Beefree SDK error:\", errorMessage);\n        }\n      };\n\n      function getBeeToken(callback) {\n        fetch('/api/beefree/auth', {\n          method: 'POST',\n          headers: { 'Content-Type': 'application/json' },\n          body: JSON.stringify({ uid: beeConfig.uid })\n        })\n        .then(response => response.json())\n        .then(data => callback(data))\n        .catch(error => {\n          console.error('Error getting Beefree token:', error);\n        });\n      }\n\n      function initializeBeefree(authResponse) {\n        const bee = new BeefreeSDK(authResponse);\n        bee.start(beeConfig, {});\n      }\n\n      getBeeToken(initializeBeefree);\n    </script>\n  </body>\n</html>\n```\n"}