Guidelines and best practices for building applications with [Beefree SDK](https://docs.beefree.io/beefree-sdk), including installation, authentication, configuration, customization, and template management
Add this skill
npx mdskills install PatrickJS/cursor-beefreesdkComprehensive, well-structured guidelines with strong security practices and extensive code examples
1---2description: Guidelines and best practices for building applications with [Beefree SDK](https://docs.beefree.io/beefree-sdk), including installation, authentication, configuration, customization, and template management3globs: **/*.{ts,tsx,js,jsx,html,css}4---56# Beefree SDK Guidelines7Guidelines and best practices for building applications with [Beefree SDK](https://docs.beefree.io/beefree-sdk), including installation, authentication, configuration, customization, and template management.89## Installation Guidelines1011### Package Installation12- Install the Beefree SDK package using npm or yarn:13 ```bash14 npm install @beefree.io/sdk15 # or16 yarn add @beefree.io/sdk17 ```1819### Dependencies20- Beefree SDK requires the following core dependencies:21 ```json22 {23 "dependencies": {24 "@beefree.io/sdk": "^9.0.2-fix-optional-url-config.0",25 "axios": "^1.10.0",26 "express": "^5.1.0",27 "cors": "^2.8.5",28 "dotenv": "^17.2.0"29 }30 }31 ```3233### Environment Setup34- Create a `.env` file in your project root with your Beefree credentials:35 ```env36 BEE_CLIENT_ID=your_client_id_here37 BEE_CLIENT_SECRET=your_client_secret_here38 ```3940## Authentication Guidelines4142### Proxy Server Setup43- ALWAYS use a proxy server for authentication to protect your credentials44- Create a proxy server file (e.g., `proxy-server.js`) to handle authentication:45 ```javascript46 import express from 'express';47 import cors from 'cors';48 import axios from 'axios';49 import dotenv from 'dotenv';5051 dotenv.config();5253 const app = express();54 const PORT = 3001;5556 app.use(cors());57 app.use(express.json());5859 const BEE_CLIENT_ID = process.env.BEE_CLIENT_ID;60 const BEE_CLIENT_SECRET = process.env.BEE_CLIENT_SECRET;6162 // V2 Auth Endpoint63 app.post('/proxy/bee-auth', async (req, res) => {64 try {65 const { uid } = req.body;6667 const response = await axios.post(68 'https://auth.getbee.io/loginV2',69 {70 client_id: BEE_CLIENT_ID,71 client_secret: BEE_CLIENT_SECRET,72 uid: uid || 'demo-user'73 },74 { headers: { 'Content-Type': 'application/json' } }75 );7677 res.json(response.data);78 } catch (error) {79 console.error('Auth error:', error.message);80 res.status(500).json({ error: 'Failed to authenticate' });81 }82 });8384 app.listen(PORT, () => {85 console.log(`Proxy server running on http://localhost:${PORT}`);86 });87 ```8889### Authentication Process90- Use the V2 authentication endpoint: `https://auth.getbee.io/loginV2`91- Pass the ENTIRE API response to the Beefree SDK, not just the token92- Example authentication call:93 ```typescript94 const token = await fetch('http://localhost:3001/proxy/bee-auth', {95 method: 'POST',96 headers: { 'Content-Type': 'application/json' },97 body: JSON.stringify({ uid: 'demo-user' })98 }).then(res => res.json());99 ```100101## Container Setup Guidelines102103### HTML Container104- Create a dedicated container element for the Beefree SDK:105 ```html106 <div id="beefree-sdk-container"></div>107 ```108109### CSS Styling110- Style the container to ensure proper display:111 ```css112 #beefree-sdk-container {113 position: absolute;114 top: 0px;115 bottom: 0px;116 left: 0px;117 right: 0px;118 height: 600px;119 width: 90%;120 margin: 20px auto;121 border: 1px solid #ddd;122 border-radius: 8px;123 }124 ```125126### React Container127- For React applications, the following code snippet shows an example using refs to manage the container:128 ```typescript129 const containerRef = useRef<HTMLDivElement>(null);130131 return (132 <div133 id="beefree-react-demo"134 ref={containerRef}135 style={{136 height: '600px',137 width: '90%',138 margin: '20px auto',139 border: '1px solid #ddd',140 borderRadius: '8px'141 }}142 />143 );144 ```145146## Configuration Guidelines147148### Required Configuration Parameters149- ALWAYS include the `container` parameter in your configuration:150 ```typescript151 const beeConfig = {152 container: 'beefree-sdk-container', // Required153 language: 'en-US'154 };155 ```156157### Optional Configuration Parameters158- Customize your SDK with optional parameters:159 ```typescript160 const beeConfig = {161 container: 'beefree-sdk-container', // Required162 language: 'en-US',163 specialLinks: [164 {165 type: "unsubscribe",166 label: "Unsubscribe",167 link: "http://[unsubscribe]/",168 },169 {170 type: "subscribe",171 label: "Subscribe",172 link: "http://[subscribe]/",173 },174 ],175 mergeTags: [176 {177 name: "First Name",178 value: "[first_name]",179 },180 {181 name: "Last Name",182 value: "[last_name]",183 },184 {185 name: "Email",186 value: "[email]",187 },188 ]189 };190 ```191192### Callback Functions193- Implement essential callback functions for proper functionality:194 ```typescript195 const beeConfig = {196 container: 'beefree-sdk-container',197 onSave: function (jsonFile, htmlFile) {198 console.log("Template saved:", jsonFile);199 // Implement custom save logic here200 },201 onAutoSave: function (jsonFile) {202 console.log("Auto-saving template...");203 localStorage.setItem("email.autosave", jsonFile);204 },205 onSend: function (htmlFile) {206 console.log("Email ready to send:", htmlFile);207 // Implement custom send logic here208 },209 onError: function (errorMessage) {210 console.error("Beefree SDK error:", errorMessage);211 // Handle errors appropriately212 }213 };214 ```215216## SDK Initialization Guidelines217218### Basic Initialization219- Initialize the Beefree SDK with proper error handling:220 ```typescript221 async function initializeBeefree(authResponse) {222 try {223 const bee = new BeefreeSDK(authResponse);224 bee.start(beeConfig, {});225 console.log('Beefree SDK initialized successfully');226 } catch (error) {227 console.error('Failed to initialize Beefree SDK:', error);228 }229 }230 ```231232### React Integration233- For React applications, the following code snippet shows an example using useEffect for initialization:234 ```typescript235 useEffect(() => {236 async function initializeEditor() {237 const beeConfig = {238 container: 'beefree-react-demo',239 language: 'en-US',240 onSave: (pageJson: string, pageHtml: string, ampHtml: string | null, templateVersion: number, language: string | null) => {241 console.log('Saved!', { pageJson, pageHtml, ampHtml, templateVersion, language });242 },243 onError: (error: unknown) => {244 console.error('Error:', error);245 }246 };247248 const token = await fetch('http://localhost:3001/proxy/bee-auth', {249 method: 'POST',250 headers: { 'Content-Type': 'application/json' },251 body: JSON.stringify({ uid: 'demo-user' })252 }).then(res => res.json());253254 const bee = new BeefreeSDK(token);255 bee.start(beeConfig, {});256 }257258 initializeEditor();259 }, []);260 ```261262## Template Loading Guidelines263264### Loading Templates265- Use the `start()` method with template data to load existing templates:266 ```typescript267 // Load template from localStorage268 const selectedTemplate = JSON.parse(localStorage.getItem('currentEmailData'));269270 if (selectedTemplate) {271 beefreeSDKInstance.start(selectedTemplate);272 console.log('Loaded template from localStorage');273 } else {274 // Start with empty template275 beefreeSDKInstance.start();276 console.log('Started with empty template');277 }278 ```279280### Template Storage281- Store templates in localStorage for persistence while testing:282 ```typescript283 // Save template data284 localStorage.setItem('currentEmailData', JSON.stringify(templateData));285 localStorage.setItem('currentEmailName', emailName);286287 // Load template data288 const emailData = localStorage.getItem('currentEmailData');289 const emailName = localStorage.getItem('currentEmailName');290 ```291292### Autosave Functionality293- Implement autosave to prevent data loss:294 ```typescript295 onAutoSave: function (jsonFile) {296 console.log("Auto-saving template...");297 localStorage.setItem("email.autosave", jsonFile);298 }299 ```300301## HTML Import Guidelines302303### HTML Importer API304- Use the HTML Importer API to convert existing HTML templates to Beefree SDK format305- API endpoint: `https://api.getbee.io/v1/conversion/html-to-json`306- Reference: [HTML Importer API Documentation](https://docs.beefree.io/beefree-sdk/apis/html-importer-api/import-html)307308### Import Process309- Convert HTML templates to Beefree SDK's native JSON format:310 ```javascript311 const response = await fetch('https://api.getbee.io/v1/conversion/html-to-json', {312 method: 'POST',313 headers: {314 "Authorization": "Bearer Enter Dev Console API Key as Bearer token",315 "Content-Type": "text/html"316 },317 body: "<!DOCTYPE html><html><body><h1>Hello World</h1></body></html>"318 });319 const data = await response.json();320 ```321322### Loading Imported Templates323- Load imported templates into the Beefree SDK:324 ```typescript325 const importedTemplate = await importHtmlTemplate(htmlContent);326 beefreeSDK.start(importedTemplate);327 ```328329## Error Handling Guidelines330331### onError Callback332- ALWAYS implement the `onError` callback to handle SDK errors:333 ```typescript334 onError: function (errorMessage) {335 console.error("Beefree SDK error:", errorMessage);336 // Display user-friendly error message337 document.getElementById('beefree-sdk-container').innerHTML =338 '<div class="error">Error loading Beefree SDK: ' + errorMessage.message + '</div>';339 }340 ```341342### Authentication Error Handling343- Handle authentication failures gracefully:344 ```typescript345 function getBeeToken(callback) {346 fetch('/api/beefree/auth', {347 method: 'POST',348 headers: { 'Content-Type': 'application/json' },349 body: JSON.stringify({350 client_id: 'your_client_id',351 client_secret: 'your_client_secret',352 uid: beeConfig.uid353 })354 })355 .then(response => {356 if (!response.ok) throw new Error('Auth failed: ' + response.status);357 return response.json();358 })359 .then(data => {360 callback(data);361 })362 .catch(error => {363 console.error('Error getting Beefree token:', error);364 document.getElementById('beefree-sdk-container').innerHTML =365 '<div class="error">Failed to authenticate with Beefree. Please check your credentials and try again.</div>';366 });367 }368 ```369370## Template Change Tracking Guidelines371372### Track Message Changes373- Implement template change tracking to monitor changes made by end users374- Reference: [Track Message Changes Documentation](https://docs.beefree.io/beefree-sdk/getting-started/tracking-message-changes)375376### Change Detection377- Use the `onChange` callback to track template changes:378 ```typescript379 onChange: function (jsonFile, response) {380 console.log('json', jsonFile);381 console.log('response', response);382 },383 ```384385## Customization Guidelines386387### UI Customization388Customize the Beefree SDK appearance with:389- [Customized Themes](https://docs.beefree.io/beefree-sdk/other-customizations/appearance/themes)390- [Custom CSS](https://docs.beefree.io/beefree-sdk/other-customizations/appearance/custom-css)391392### Language Customization393- Set the language for internationalization:394 ```typescript395 const beeConfig = {396 container: 'beefree-sdk-container',397 language: 'en-US', // or 'es-ES', 'fr-FR', etc.398 };399 ```400401### Merge Tags and Special Links402- Configure merge tags and special links for email personalization:403 ```typescript404 const beeConfig = {405 container: 'beefree-sdk-container',406 mergeTags: [407 { name: "First Name", value: "[first_name]" },408 { name: "Last Name", value: "[last_name]" },409 { name: "Email", value: "[email]" },410 { name: "Company", value: "[company]" }411 ],412 specialLinks: [413 { type: "unsubscribe", label: "Unsubscribe", link: "http://[unsubscribe]/" },414 { type: "subscribe", label: "Subscribe", link: "http://[subscribe]/" },415 { type: "webview", label: "View in Browser", link: "http://[webview]/" }416 ]417 };418 ```419### Other Customizations420Reference the official [Beefree SDK technical documentation](https://docs.beefree.io/beefree-sdk) for a comprehnsive reference of possible customizations.421422## Best Practices423424### Performance Optimization425- Initialize the Beefree SDK only when it is actually needed in your application.426- Properly clean up SDK resources when they are no longer required (e.g., when navigating away or closing the editor).427- Handle errors gracefully to prevent application crashes or unexpected behavior.428429### Security430- **Never** expose your Beefree SDK client credentials in any frontend or public code.431- Always use a secure backend or proxy server to handle authentication and sensitive operations.432- Validate and sanitize all user inputs before passing them to the SDK to prevent security vulnerabilities.433434### User Experience435- Show appropriate loading indicators while the SDK is initializing or performing operations.436- Display clear and helpful error messages to users if something goes wrong.437- Implement automatic saving or progress tracking to prevent data loss.438439### Code Organization440- Keep SDK configuration separate from initialization and business logic for better maintainability.441- Use strong typing (e.g., TypeScript or similar) where possible to improve code safety and clarity.442- Ensure robust error handling throughout your integration, regardless of the tech stack or framework used.443444## Examples445446### Complete React Component447Reference the full project at [beefree-react-demo](https://github.com/BeefreeSDK/beefree-react-demo).448```typescript449import { useEffect, useRef } from 'react';450import BeefreeSDK from '@beefree.io/sdk';451452export default function BeefreeEditor() {453 const containerRef = useRef<HTMLDivElement>(null);454455 useEffect(() => {456 async function initializeEditor() {457 const beeConfig = {458 container: 'beefree-react-demo',459 language: 'en-US',460 onSave: (pageJson: string, pageHtml: string, ampHtml: string | null, templateVersion: number, language: string | null) => {461 console.log('Saved!', { pageJson, pageHtml, ampHtml, templateVersion, language });462 },463 onError: (error: unknown) => {464 console.error('Error:', error);465 }466 };467468 const token = await fetch('http://localhost:3001/proxy/bee-auth', {469 method: 'POST',470 headers: { 'Content-Type': 'application/json' },471 body: JSON.stringify({ uid: 'demo-user' })472 }).then(res => res.json());473474 const bee = new BeefreeSDK(token);475 bee.start(beeConfig, {});476 }477478 initializeEditor();479 }, []);480481 return (482 <div483 id="beefree-react-demo"484 ref={containerRef}485 style={{486 height: '600px',487 width: '90%',488 margin: '20px auto',489 border: '1px solid #ddd',490 borderRadius: '8px'491 }}492 />493 );494}495```496497### Complete HTML Implementation498Reference the complete project at Beefree SDK [multiple-versions-concept](https://github.com/BeefreeSDK/beefree-sdk-simple-schema/tree/main/multiple-versions-concept).499```html500<!DOCTYPE html>501<html lang="en">502 <head>503 <title>Beefree SDK - Email Builder</title>504 <meta charset="utf-8" />505 <meta name="viewport" content="width=device-width, initial-scale=1" />506 <style type="text/css">507 #beefree-sdk-container {508 position: absolute;509 top: 0px;510 bottom: 0px;511 left: 0px;512 right: 0px;513 }514 </style>515 </head>516 <body>517 <div id="beefree-sdk-container"></div>518 <script src="https://app-rsrc.getbee.io/plugin/BeefreeSDK.js"></script>519 <script type="text/javascript">520 const beeConfig = {521 container: 'beefree-sdk-container',522 uid: 'demo-user-' + Date.now(),523 language: 'en-US',524 onSave: function (jsonFile, htmlFile) {525 console.log("Template saved:", jsonFile);526 },527 onError: function (errorMessage) {528 console.error("Beefree SDK error:", errorMessage);529 }530 };531532 function getBeeToken(callback) {533 fetch('/api/beefree/auth', {534 method: 'POST',535 headers: { 'Content-Type': 'application/json' },536 body: JSON.stringify({537 client_id: 'your_client_id',538 client_secret: 'your_client_secret',539 uid: beeConfig.uid540 })541 })542 .then(response => response.json())543 .then(data => callback(data))544 .catch(error => {545 console.error('Error getting Beefree token:', error);546 });547 }548549 function initializeBeefree(authResponse) {550 BeefreeSDK.create(authResponse, beeConfig, function (beefreeSDKInstance) {551 console.log('Beefree SDK initialized successfully');552 beefreeSDKInstance.start();553 });554 }555556 getBeeToken(initializeBeefree);557 </script>558 </body>559</html>560```
Full transparency — inspect the skill content before installing.