tacel-canva
v1.1.0
Published
Premium Canva integration module for Tacel Electron apps with OAuth 2.0, inline design editor, 10 productivity features, 34 themes, keyboard shortcuts, and glassmorphism UI.
Maintainers
Readme
Tacel Canva Module - Premium Edition
Universal Canva integration module for Tacel Electron apps with premium UI and advanced features. A complete design management solution with OAuth authentication, inline editing, analytics, and 10+ productivity features.
✨ Features
Core Features
- ✅ OAuth 2.0 Authentication with PKCE (Proof Key for Code Exchange)
- ✅ Premium Design Gallery with glassmorphism effects and staggered animations
- ✅ Inline Design Editor - Edit designs without leaving the app
- ✅ Export/Download designs in multiple formats (PNG, PDF, JPG)
- ✅ Custom Collections - Organize designs into custom collections
- ✅ Favorites System - Star designs for quick access
- ✅ Advanced Search - Search with filters and sorting
- ✅ 34 Built-in Themes - Professional color schemes
- ✅ Keyboard Shortcuts - Full keyboard navigation (press
?for help) - ✅ Toast Notifications - Elegant feedback system
Premium Features (NEW)
- 🏷️ Brand Kit Access - Quick access to brand colors, logos, and fonts
- 📋 Design Templates Browser - Browse Canva templates by category
- 📅 Scheduled Publishing Queue - Schedule design exports for specific dates
- 📝 Design Annotations & Notes - Add notes, tags, and link to tasks
- 📋 Quick Insert to Documents - Copy URLs, HTML for emails, or download
- ⚖️ Design Comparison View - Compare up to 4 designs side-by-side
- 📦 Asset Library Sync - Designate reusable assets for quick access
- 📊 Design Analytics Dashboard - Track views, exports, and usage stats
- 🎯 Batch Export with Presets - Export multiple designs with saved settings
- 💬 Design Request System - Submit and track design requests
UI/UX Enhancements
- Glassmorphism Effects - Blurred backgrounds on modals and menus
- Gradient System - Beautiful gradients throughout the UI
- Layered Shadows - Depth with xs, sm, md, lg, xl shadow levels
- Micro-interactions - Hover effects, staggered animations, smooth transitions
- Premium Context Menus - Right-click anywhere for quick actions
- Responsive Design - Adapts to all screen sizes
- Loading Skeletons - Shimmer effects while content loads
Installation
npm install tacel-canvaQuick Start
1. Register Canva Integration
Go to Canva Developer Portal and create an integration:
- Set redirect URI:
http://localhost:3000/canva/callback - Enable scopes:
design:meta:read,design:content:read,folder:read - Save your Client ID and Client Secret
2. Backend Setup (main.js)
const { initCanvaApi } = require('tacel-canva/canva-api');
// Initialize Canva API handlers
initCanvaApi({
clientId: process.env.CANVA_CLIENT_ID,
clientSecret: process.env.CANVA_CLIENT_SECRET,
redirectUri: 'http://localhost:3000/canva/callback',
channelPrefix: 'canva', // IPC channel prefix
});3. Frontend Setup (renderer)
<!-- Include CSS -->
<link rel="stylesheet" href="node_modules/tacel-canva/canva.css">
<!-- Include JS -->
<script src="node_modules/tacel-canva/index.js"></script>const { TacelCanva } = require('tacel-canva');
// Initialize the module
const canva = TacelCanva.initialize(document.getElementById('canva-container'), {
// Current user context
currentUserId: 'user-123',
currentUserName: 'Pierre',
// Token storage callbacks (required)
onGetToken: async (userId) => {
// Return stored tokens from your DB
const tokens = await window.electron.invoke('get-canva-tokens', userId);
return tokens; // { access_token, refresh_token, expires_at }
},
onSaveToken: async (userId, tokens) => {
// Save tokens to your DB
await window.electron.invoke('save-canva-tokens', { userId, tokens });
},
onRevokeToken: async (userId) => {
// Delete tokens from your DB
await window.electron.invoke('delete-canva-tokens', userId);
},
// Optional features (all enabled by default)
features: {
export: true,
createNew: true,
folders: true,
search: true,
preview: true,
sorting: true,
viewToggle: true,
contextMenu: true,
dragDrop: true,
favorites: true,
recentlyViewed: true,
bulkActions: true,
collections: true,
themePicker: true,
// Premium features
brandKit: true,
templates: true,
scheduledExports: true,
annotations: true,
quickInsert: true,
compareView: true,
assetLibrary: true,
analytics: true,
batchExport: true,
designRequests: true,
},
// Optional theming
theme: 'default', // or any of 34 built-in themes
});4. Handle OAuth Callback
Create a callback route in your app to handle the OAuth redirect:
// In your app's routing logic
if (window.location.pathname === '/canva/callback') {
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get('code');
if (code) {
// Complete OAuth flow
await canva.completeOAuth(code);
}
}Configuration
Backend Options
initCanvaApi({
clientId: string, // Required: Canva client ID
clientSecret: string, // Required: Canva client secret
redirectUri: string, // Required: OAuth redirect URI
channelPrefix: string, // Optional: IPC channel prefix (default: 'canva')
});Frontend Options
TacelCanva.initialize(container, {
// Required
currentUserId: string,
onGetToken: async (userId) => tokens,
onSaveToken: async (userId, tokens) => void,
onRevokeToken: async (userId) => void,
// Optional
currentUserName: string,
features: {
export: boolean, // Default: true
createNew: boolean, // Default: true
folders: boolean, // Default: true
search: boolean, // Default: true
},
theme: string, // Default: 'default'
channelPrefix: string, // Default: 'canva'
});Theming
Override CSS variables to match your app's theme:
.tacel-canva {
--tc-primary: #00c4cc;
--tc-primary-hover: #00a8b0;
--tc-bg: #ffffff;
--tc-bg-secondary: #f5f5f5;
--tc-border: #e0e0e0;
--tc-text: #333333;
--tc-text-muted: #666666;
--tc-shadow: rgba(0, 0, 0, 0.1);
--tc-border-radius: 8px;
--tc-spacing: 16px;
}Example: Wire-Scheduler Theme
.tacel-canva {
--tc-primary: #4a90e2;
--tc-primary-hover: #357abd;
--tc-bg: #1e1e1e;
--tc-bg-secondary: #2a2a2a;
--tc-border: #3a3a3a;
--tc-text: #ffffff;
--tc-text-muted: #b0b0b0;
}API Reference
Frontend Methods
TacelCanva.initialize(container, config)
Initialize the Canva module in a container element.
canva.completeOAuth(code)
Complete the OAuth flow with the authorization code from the callback.
canva.destroy()
Clean up the module and remove all event listeners.
IPC Channels
All channels are prefixed with your configured channelPrefix (default: canva):
canva:get-auth-url- Get OAuth authorization URLcanva:exchange-token- Exchange authorization code for tokenscanva:refresh-token- Refresh access tokencanva:list-designs- List user's designscanva:get-design- Get design detailscanva:export-design- Export design to filecanva:get-export- Get export job statuscanva:list-folders- List user's folderscanva:revoke-token- Revoke access token
Token Storage
The module does NOT store tokens itself. You must implement token storage in your app's database.
Example Token Schema
CREATE TABLE canva_tokens (
user_id VARCHAR(255) PRIMARY KEY,
access_token TEXT NOT NULL,
refresh_token TEXT NOT NULL,
expires_at BIGINT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);Example IPC Handlers
// In your app's main.js
ipcMain.handle('get-canva-tokens', async (event, userId) => {
const row = await db.query('SELECT * FROM canva_tokens WHERE user_id = ?', [userId]);
return row ? {
access_token: row.access_token,
refresh_token: row.refresh_token,
expires_at: row.expires_at
} : null;
});
ipcMain.handle('save-canva-tokens', async (event, { userId, tokens }) => {
await db.query(
'INSERT INTO canva_tokens (user_id, access_token, refresh_token, expires_at) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE access_token = ?, refresh_token = ?, expires_at = ?',
[userId, tokens.access_token, tokens.refresh_token, tokens.expires_at, tokens.access_token, tokens.refresh_token, tokens.expires_at]
);
});
ipcMain.handle('delete-canva-tokens', async (event, userId) => {
await db.query('DELETE FROM canva_tokens WHERE user_id = ?', [userId]);
});OAuth Flow
- User clicks "Connect Canva Account"
- Module generates PKCE challenge
- Module requests auth URL from backend
- Backend returns Canva authorization URL
- Module opens URL in browser
- User authorizes in Canva
- Canva redirects to your callback URL with code
- Your app calls
canva.completeOAuth(code) - Module exchanges code for tokens via backend
- Module saves tokens via
onSaveTokencallback - Module loads designs and renders gallery
Canva API Limits
- List designs: 100 requests/minute per user
- Export design: 20 requests/minute per user
- Thumbnails: Expire after 15 minutes
- Edit/View URLs: Expire after 30 days
Troubleshooting
"No tokens found" error
Make sure your onGetToken callback returns tokens in the correct format:
{ access_token: string, refresh_token: string, expires_at: number }OAuth redirect not working
Verify your redirect URI in Canva Developer Portal matches exactly:
http://localhost:3000/canva/callbackCORS errors
Token exchange must happen on the backend (Electron main process), not in the renderer. The module handles this automatically via IPC.
Designs not loading
Check that you enabled the correct scopes in Canva Developer Portal:
design:meta:readdesign:content:readfolder:read
License
UNLICENSED - Internal use only
Keyboard Shortcuts
Press ? to view the keyboard shortcuts help modal in the app.
| Key | Action |
|-----|--------|
| 1 | Navigate to My Designs |
| 2 | Navigate to Favorites |
| 3 | Navigate to Brand Kit |
| 4 | Navigate to Templates |
| 5 | Navigate to Asset Library |
| 6 | Navigate to Compare View |
| 7 | Navigate to Scheduled Exports |
| 8 | Navigate to Analytics |
| 9 | Navigate to Design Requests |
| / or Ctrl+F | Focus search input |
| V | Toggle grid/list view |
| Ctrl+A | Select all designs |
| Esc | Deselect all / Close modals |
| ? | Show keyboard shortcuts help |
Premium Features Guide
1. Brand Kit Access
Access your brand colors, logos, and fonts quickly.
- Navigate via sidebar or press
3 - Add custom brand colors with color picker
- Copy hex codes with one click
- Persistent storage per user
2. Design Templates Browser
Browse Canva's template library by category.
- Navigate via sidebar or press
4 - Click any category to open in Canva
- Categories: Social Media, Presentations, Marketing, Documents, and more
3. Scheduled Publishing Queue
Schedule design exports for specific dates and times.
- Navigate via sidebar or press
7 - Click "+ Schedule Export" to add new
- Set date, time, format, and quality
- Cancel scheduled exports anytime
- Persistent queue per user
4. Design Annotations & Notes
Add notes, tags, and link designs to tasks.
- Right-click any design → "Notes & Tags"
- Add markdown-formatted notes
- Tag designs for organization
- Link to task IDs for tracking
- All annotations persist per user
5. Quick Insert to Documents
Quickly insert designs into emails and documents.
- Right-click any design → "Quick Insert"
- Copy image URL for embedding
- Copy HTML snippet for emails
- Download directly to clipboard
6. Design Comparison View
Compare up to 4 designs side-by-side.
- Navigate via sidebar or press
6 - Right-click designs → "Add to Compare"
- View designs in grid layout
- Remove individual designs or clear all
7. Asset Library Sync
Designate frequently-used designs as reusable assets.
- Navigate via sidebar or press
5 - Right-click designs → "Add to Asset Library"
- Quick access to logos, icons, templates
- Copy URLs or download assets
- Persistent library per user
8. Design Analytics Dashboard
Track design usage, views, and exports.
- Navigate via sidebar or press
8 - View total designs, favorites, assets
- See recently viewed designs
- Track most viewed designs
- Export history and trends
9. Batch Export with Presets
Export multiple designs with saved settings.
- Select multiple designs (Ctrl+Click)
- Click "Export" in toolbar
- Choose format, quality, naming pattern
- Save presets for future use
- Exports all selected designs
10. Design Request System
Submit and track design requests.
- Navigate via sidebar or press
9 - Click "+ New Request" to submit
- Track pending and completed requests
- Add title, description, dimensions, deadline
- Team collaboration feature
Built-in Themes
The module includes 34 professionally designed themes:
Light Themes: Default, Ocean, Forest, Sunset, Lavender, Rose, Mint, Peach, Sky, Coral
Dark Themes: Dark, Midnight, Forest Dark, Ocean Dark, Purple Dark, Red Dark, Teal Dark, Amber Dark, Blue Dark, Green Dark
Vibrant Themes: Neon, Cyberpunk, Retro, Pastel, Monochrome, High Contrast
App-Specific: Wire Scheduler, Office HQ, Tech Portal, ShipWorks
Applying Themes
// Via config
const canva = TacelCanva.initialize(container, {
theme: 'ocean',
// ... other config
});
// Programmatically
canva.setTheme('midnight');Custom Theme
.tacel-canva {
--tc-primary: #your-color;
--tc-primary-hover: #your-hover-color;
--tc-primary-light: rgba(your-color, 0.12);
--tc-bg: #ffffff;
--tc-bg-secondary: #f8fafc;
--tc-border: #e2e8f0;
--tc-text: #0f172a;
--tc-text-muted: #64748b;
/* ... see canva.css for all variables */
}Advanced Configuration
Feature Data Storage
The module requires IPC handlers for storing feature data:
// In main.js
const fs = require('fs');
const path = require('path');
const DATA_DIR = path.join(app.getPath('userData'), 'canva-data');
function ensureDataDir() {
if (!fs.existsSync(DATA_DIR)) {
fs.mkdirSync(DATA_DIR, { recursive: true });
}
}
function createFeatureStorage(filename) {
const filePath = path.join(DATA_DIR, filename);
return {
get: async (userId) => {
ensureDataDir();
if (fs.existsSync(filePath)) {
const data = JSON.parse(fs.readFileSync(filePath, 'utf8'));
return data[userId] || null;
}
return null;
},
save: async (userId, data) => {
ensureDataDir();
let cache = {};
if (fs.existsSync(filePath)) {
cache = JSON.parse(fs.readFileSync(filePath, 'utf8'));
}
cache[userId] = data;
fs.writeFileSync(filePath, JSON.stringify(cache, null, 2));
}
};
}
// Create storages
const brandKitStorage = createFeatureStorage('brand-kit.json');
const annotationsStorage = createFeatureStorage('annotations.json');
const assetLibraryStorage = createFeatureStorage('asset-library.json');
const analyticsStorage = createFeatureStorage('analytics.json');
const scheduledExportsStorage = createFeatureStorage('scheduled-exports.json');
const designRequestsStorage = createFeatureStorage('design-requests.json');
// Register handlers
ipcMain.handle('get-canva-brand-kit', async (event, userId) => {
return await brandKitStorage.get(userId);
});
ipcMain.handle('save-canva-brand-kit', async (event, { userId, brandKit }) => {
await brandKitStorage.save(userId, brandKit);
});
// Repeat for all feature storages...Design Cache Storage
For faster loading, implement design caching:
const designsCacheStorage = createFeatureStorage('designs-cache.json');
ipcMain.handle('get-canva-designs-cache', async (event, userId) => {
return await designsCacheStorage.get(userId);
});
ipcMain.handle('save-canva-designs-cache', async (event, { userId, designs, lastSync }) => {
await designsCacheStorage.save(userId, { designs, lastSync, count: designs.length });
});Complete IPC Channel Reference
Authentication Channels
canva:get-auth-url- Get OAuth authorization URLcanva:exchange-token- Exchange authorization code for tokenscanva:refresh-token- Refresh access tokencanva:revoke-token- Revoke access token
Design Channels
canva:list-designs- List user's designs with paginationcanva:get-design- Get design details by IDcanva:export-design- Export design to filecanva:get-export- Get export job status
Storage Channels (App-Implemented)
get-canva-tokens- Retrieve stored tokenssave-canva-tokens- Save tokens to storagedelete-canva-tokens- Delete tokens from storageget-canva-collections- Get user's collectionssave-canva-collections- Save collectionsget-canva-designs-cache- Get cached designssave-canva-designs-cache- Save designs cacheget-canva-brand-kit- Get brand kit datasave-canva-brand-kit- Save brand kit dataget-canva-annotations- Get design annotationssave-canva-annotations- Save annotationsget-canva-asset-library- Get asset librarysave-canva-asset-library- Save asset libraryget-canva-analytics- Get analytics datasave-canva-analytics- Save analytics dataget-canva-scheduled-exports- Get scheduled exportssave-canva-scheduled-exports- Save scheduled exportsget-canva-design-requests- Get design requestssave-canva-design-requests- Save design requestsdownload-canva-design- Download design to file system
Performance Optimization
Design Caching
The module implements cache-first loading:
- Loads cached designs immediately for instant display
- Syncs with Canva API in background
- Updates UI when new designs are found
- Reduces API calls and improves perceived performance
Lazy Loading
- Thumbnails load with
loading="lazy"attribute - Pagination with continuation tokens
- Load more designs on demand
Debounced Search
Search input is debounced to reduce API calls while typing.
Browser Compatibility
- Chrome/Edge 90+
- Firefox 88+
- Safari 14+
- Electron 13+
Version History
v1.0.0 (Current)
- Initial release with all premium features
- 34 built-in themes
- 10 productivity features
- Keyboard shortcuts
- Inline design editor
- Toast notification system
- Glassmorphism UI
- Complete documentation
Support
For issues or questions, contact the Tacel development team.
License
UNLICENSED - Internal use only
