Build a Trello Integration Chrome Extension: Complete Developer Guide

24 min read

Build a Trello Integration Chrome Extension: Complete Developer Guide

Build a Trello Integration Chrome Extension: Complete Developer Guide

Integrating Trello with Chrome through a custom extension unlocks powerful productivity workflows. Whether you need a quick trello card creator accessible from any webpage, want to capture tasks while browsing, or need to manage your boards without leaving Chrome, building a trello chrome extension is an excellent project that demonstrates real-world API integration skills.

In this comprehensive guide, you’ll learn how to build a fully functional Trello Integration Chrome Extension using Manifest V3. We’ll cover everything from setting up the Trello API, implementing OAuth authentication, creating cards programmatically, and building a polished popup interface that your users will love.


Why Build a Trello Chrome Extension?

Trello is one of the most popular project management tools globally, with millions of users relying on its Kanban-style boards to organize tasks. A well-designed trello chrome extension can significantly enhance user productivity by enabling:

Instant Card Creation: Users can create trello cards directly from Chrome’s toolbar without navigating to the Trello website. This is perfect for capturing ideas, tasks, or bugs while browsing.

Contextual Task Management: A task management extension can automatically capture webpage URLs, titles, and selected text as card descriptions, providing valuable context for each task.

Quick Board Access: Users can view their boards, lists, and cards at a glance without opening a new tab, saving precious time during busy workdays.

Seamless Workflow Integration: By embedding Trello functionality directly into Chrome, you eliminate context switching and keep users in their primary workspace.

The demand for trello chrome extension solutions continues to grow as remote work and digital productivity become the norm. Building this extension will teach you valuable skills in API integration, OAuth authentication, and Chrome extension development that apply to countless other projects.


Prerequisites and Setup

Before we dive into coding, make sure you have the following:

  • A Google Chrome browser for testing
  • Node.js and npm installed (for development tools)
  • A Trello account (free tier works fine)
  • Basic knowledge of HTML, CSS, and JavaScript

Registering Your Trello Application

The first step is to register your application with Trello to obtain API credentials:

  1. Visit https://trello.com/app-key
  2. Log in to your Trello account
  3. Copy your API Key (we’ll need this later)
  4. For development, we’ll use a token-based approach instead of full OAuth

Setting Up the Project Structure

Create a new directory for your extension and set up the following structure:

trello-extension/
├── manifest.json
├── popup.html
├── popup.css
├── popup.js
├── background.js
├── content.js
├── options.html
├── options.js
└── icons/
    ├── icon16.png
    ├── icon48.png
    └── icon128.png

This structure separates concerns appropriately: popup files handle the extension’s UI, background.js manages long-running tasks and API communication, and content.js interacts with web pages.


Creating the Manifest V3 Configuration

Every Chrome extension starts with the manifest.json file. This tells Chrome about your extension’s capabilities, permissions, and structure:

{
  "manifest_version": 3,
  "name": "Trello Quick Card Creator",
  "version": "1.0.0",
  "description": "Create Trello cards instantly from any webpage. A powerful task management extension for Chrome.",
  "permissions": [
    "storage",
    "activeTab",
    "scripting"
  ],
  "host_permissions": [
    "https://api.trello.com/*",
    "https://trello.com/*"
  ],
  "action": {
    "default_popup": "popup.html",
    "default_icon": {
      "16": "icons/icon16.png",
      "48": "icons/icon48.png",
      "128": "icons/icon128.png"
    }
  },
  "background": {
    "service_worker": "background.js"
  },
  "icons": {
    "16": "icons/icon16.png",
    "48": "icons/icon48.png",
    "128": "icons/icon128.png"
  }
}

Key points about this manifest:

  • host_permissions: We need access to both the Trello API and the Trello website for authentication flows
  • permissions: storage for saving user credentials, activeTab for accessing current page information, and scripting for content script functionality
  • action: Defines the popup that appears when clicking the extension icon

Implementing Trello API Authentication

Authentication is crucial for a trello chrome extension. We’ll implement a token-based authentication system that stores credentials securely.

Storing Credentials

Create a utility module for handling Trello credentials:

// auth.js - Trello Authentication Helper
const TRELLO_API_KEY = 'YOUR_API_KEY_HERE';

class TrelloAuth {
  constructor() {
    this.baseUrl = 'https://api.trello.com/1';
  }

  // Generate authorization URL for user to approve
  getAuthUrl() {
    const returnUrl = chrome.identity.getRedirectURL();
    return `https://trello.com/1/authorize?expiration=1day&name=Chrome%20Extension&scope=read,write&response_type=token&key=${TRELLO_API_KEY}&return_url=${encodeURIComponent(returnUrl)}`;
  }

  // Save token to storage
  async saveToken(token) {
    await chrome.storage.local.set({ trelloToken: token });
  }

  // Get stored token
  async getToken() {
    const result = await chrome.storage.local.get('trelloToken');
    return result.trelloToken;
  }

  // Check if user is authenticated
  async isAuthenticated() {
    const token = await this.getToken();
    return !!token;
  }

  // Clear authentication
  async logout() {
    await chrome.storage.local.remove('trelloToken');
  }
}

const trelloAuth = new TrelloAuth();

Implementing the Authentication Flow

For simplicity, we’ll use a manual token approach where users paste their API key and token. This avoids the complexity of implementing full OAuth in an extension:

// In popup.js - Authentication Setup
document.addEventListener('DOMContentLoaded', async () => {
  const authSection = document.getElementById('auth-section');
  const mainSection = document.getElementById('main-section');
  const setupBtn = document.getElementById('setup-btn');
  const logoutBtn = document.getElementById('logout-btn');
  
  const isAuth = await trelloAuth.isAuthenticated();
  
  if (isAuth) {
    authSection.style.display = 'none';
    mainSection.style.display = 'block';
  } else {
    authSection.style.display = 'block';
    mainSection.style.display = 'none';
  }

  setupBtn.addEventListener('click', async () => {
    const apiKey = document.getElementById('api-key').value;
    const token = document.getElementById('token').value;
    
    if (apiKey && token) {
      await chrome.storage.local.set({ 
        trelloApiKey: apiKey,
        trelloToken: token 
      });
      authSection.style.display = 'none';
      mainSection.style.display = 'block';
      loadBoards();
    }
  });

  logoutBtn.addEventListener('click', async () => {
    await trelloAuth.logout();
    mainSection.style.display = 'none';
    authSection.style.display = 'block';
  });
});

This authentication approach allows users to obtain their API key and token from Trello’s developer portal, then paste them into your extension. It’s secure and doesn’t require complex redirect handling.


Building the Trello Card Creator

Now let’s implement the core functionality: creating Trello cards from the extension popup. This is where our trello card creator comes to life.

Trello API Client

First, create a client for interacting with the Trello API:

// trello-client.js - Trello API Client
class TrelloClient {
  constructor() {
    this.baseUrl = 'https://api.trello.com/1';
  }

  async getCredentials() {
    const result = await chrome.storage.local.get(['trelloApiKey', 'trelloToken']);
    return {
      key: result.trelloApiKey,
      token: result.trelloToken
    };
  }

  async request(endpoint, method = 'GET', body = null) {
    const { key, token } = await this.getCredentials();
    
    const options = {
      method,
      headers: {
        'Content-Type': 'application/json'
      }
    };

    let url = `${this.baseUrl}${endpoint}?key=${key}&token=${token}`;
    
    if (body) {
      options.body = JSON.stringify(body);
    }

    const response = await fetch(url, options);
    
    if (!response.ok) {
      throw new Error(`Trello API error: ${response.status}`);
    }
    
    return response.json();
  }

  // Get all boards for the user
  async getBoards() {
    return this.request('/members/me/boards');
  }

  // Get lists on a specific board
  async getLists(boardId) {
    return this.request(`/boards/${boardId}/lists`);
  }

  // Create a new card - the core trello card creator functionality
  async createCard(listId, cardData) {
    return this.request('/cards', 'POST', {
      name: cardData.name,
      desc: cardData.description || '',
      due: cardData.dueDate || null,
      labels: cardData.labels || [],
      urlSource: cardData.urlSource || null
    });
  }

  // Get cards on a list
  async getCards(listId) {
    return this.request(`/lists/${listId}/cards`);
  }
}

const trelloClient = new TrelloClient();

Creating the Card Creation UI

Now let’s build the popup interface for creating cards:

<!-- popup.html -->
<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="popup.css">
</head>
<body>
  <div class="container">
    <!-- Authentication Section -->
    <div id="auth-section" class="section">
      <h2>Setup Trello</h2>
      <p>Enter your Trello credentials to get started.</p>
      <a href="https://trello.com/app-key" target="_blank" class="help-link">
        Get your API Key and Token
      </a>
      <div class="form-group">
        <label for="api-key">API Key</label>
        <input type="text" id="api-key" placeholder="Enter your API Key">
      </div>
      <div class="form-group">
        <label for="token">Token</label>
        <input type="password" id="token" placeholder="Enter your Token">
      </div>
      <button id="setup-btn" class="btn-primary">Connect to Trello</button>
    </div>

    <!-- Main Application Section -->
    <div id="main-section" class="section" style="display: none;">
      <div class="header">
        <h2>Create Card</h2>
        <button id="logout-btn" class="btn-small">Logout</button>
      </div>

      <!-- Board Selection -->
      <div class="form-group">
        <label for="board-select">Board</label>
        <select id="board-select">
          <option value="">Select a board...</option>
        </select>
      </div>

      <!-- List Selection -->
      <div class="form-group">
        <label for="list-select">List</label>
        <select id="list-select" disabled>
          <option value="">Select a list...</option>
        </select>
      </div>

      <!-- Card Details -->
      <div class="form-group">
        <label for="card-name">Card Name</label>
        <input type="text" id="card-name" placeholder="Enter card title">
      </div>

      <div class="form-group">
        <label for="card-description">Description</label>
        <textarea id="card-description" rows="3" placeholder="Add description..."></textarea>
      </div>

      <!-- Include Current Page Option -->
      <div class="form-group checkbox-group">
        <input type="checkbox" id="include-page-info" checked>
        <label for="include-page-info">Include current page info</label>
      </div>

      <button id="create-card-btn" class="btn-primary" disabled>Create Card</button>

      <!-- Success/Error Messages -->
      <div id="message" class="message"></div>
    </div>
  </div>
  <script src="popup.js"></script>
</body>
</html>

Card Creation Logic

Implement the card creation logic in popup.js:

// popup.js - Card Creation Logic
let boards = [];
let selectedBoard = null;
let selectedList = null;

// Load boards on startup
async function loadBoards() {
  try {
    boards = await trelloClient.getBoards();
    const boardSelect = document.getElementById('board-select');
    
    boards.forEach(board => {
      const option = document.createElement('option');
      option.value = board.id;
      option.textContent = board.name;
      boardSelect.appendChild(option);
    });
  } catch (error) {
    showMessage('Error loading boards: ' + error.message, 'error');
  }
}

// Handle board selection
document.getElementById('board-select').addEventListener('change', async (e) => {
  selectedBoard = e.target.value;
  const listSelect = document.getElementById('list-select');
  
  listSelect.innerHTML = '<option value="">Select a list...</option>';
  listSelect.disabled = !selectedBoard;
  
  if (selectedBoard) {
    try {
      const lists = await trelloClient.getLists(selectedBoard);
      lists.forEach(list => {
        const option = document.createElement('option');
        option.value = list.id;
        option.textContent = list.name;
        listSelect.appendChild(option);
      });
    } catch (error) {
      showMessage('Error loading lists: ' + error.message, 'error');
    }
  }
});

// Handle list selection
document.getElementById('list-select').addEventListener('change', (e) => {
  selectedList = e.target.value;
  updateCreateButton();
});

// Handle card creation
document.getElementById('create-card-btn').addEventListener('click', async () => {
  if (!selectedList) return;

  const cardName = document.getElementById('card-name').value.trim();
  const cardDesc = document.getElementById('card-description').value;
  const includePageInfo = document.getElementById('include-page-info').checked;

  if (!cardName) {
    showMessage('Please enter a card name', 'error');
    return;
  }

  // Build card data
  const cardData = {
    name: cardName,
    description: cardDesc
  };

  // Optionally include current page info
  if (includePageInfo) {
    try {
      const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
      if (tab) {
        cardData.description += `\n\nSource: ${tab.title}\n${tab.url}`;
      }
    } catch (error) {
      console.error('Error getting tab info:', error);
    }
  }

  try {
    await trelloClient.createCard(selectedList, cardData);
    showMessage('Card created successfully!', 'success');
    
    // Clear form
    document.getElementById('card-name').value = '';
    document.getElementById('card-description').value = '';
  } catch (error) {
    showMessage('Error creating card: ' + error.message, 'error');
  }
});

function updateCreateButton() {
  const btn = document.getElementById('create-card-btn');
  btn.disabled = !selectedList;
}

function showMessage(text, type) {
  const messageEl = document.getElementById('message');
  messageEl.textContent = text;
  messageEl.className = `message ${type}`;
  setTimeout(() => {
    messageEl.textContent = '';
    messageEl.className = 'message';
  }, 3000);
}

This trello card creator allows users to select a board and list, enter card details, and optionally include the current webpage’s title and URL as context—perfect for creating tasks from any page you’re browsing.


Adding Context Menu Functionality

To make your task management extension even more powerful, let’s add right-click context menu integration:

// background.js - Context Menu Setup
chrome.runtime.onInstalled.addListener(() => {
  // Create context menu item
  chrome.contextMenus.create({
    id: 'createTrelloCard',
    title: 'Create Trello Card',
    contexts: ['selection', 'page']
  });
});

chrome.contextMenus.onClicked.addListener(async (info, tab) => {
  if (info.menuItemId === 'createTrelloCard') {
    // Get current selection or page info
    const cardData = {
      name: info.selectionText || tab.title,
      description: `From: ${tab.url}`
    };
    
    // Store temporarily and open popup
    await chrome.storage.local.set({ pendingCard: cardData });
    
    // Open the popup programmatically
    chrome.action.openPopup();
  }
});

This enables users to right-click anywhere in Chrome and quickly create a Trello card from selected text or the current page—another powerful feature of any trello chrome extension.


Styling Your Extension

A polished UI makes your extension stand out. Here’s a professional CSS stylesheet:

/* popup.css */
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  width: 320px;
  padding: 16px;
  background: #f5f6f8;
  color: #172b4d;
}

.container {
  background: white;
  border-radius: 8px;
  padding: 16px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.12);
}

.section h2 {
  font-size: 18px;
  margin-bottom: 12px;
  color: #172b4d;
}

.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
}

.header h2 {
  margin-bottom: 0;
}

.form-group {
  margin-bottom: 12px;
}

.form-group label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  margin-bottom: 4px;
  color: #5e6c84;
}

.form-group input,
.form-group select,
.form-group textarea {
  width: 100%;
  padding: 8px;
  border: 1px solid #dfe1e6;
  border-radius: 4px;
  font-size: 14px;
  transition: border-color 0.2s;
}

.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
  outline: none;
  border-color: #0079bf;
}

.checkbox-group {
  display: flex;
  align-items: center;
  gap: 8px;
}

.checkbox-group label {
  margin-bottom: 0;
}

.btn-primary {
  width: 100%;
  padding: 10px;
  background: #0079bf;
  color: white;
  border: none;
  border-radius: 4px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.2s;
}

.btn-primary:hover:not(:disabled) {
  background: #026aa7;
}

.btn-primary:disabled {
  background: #c1c7d0;
  cursor: not-allowed;
}

.btn-small {
  padding: 4px 8px;
  background: transparent;
  color: #5e6c84;
  border: none;
  font-size: 12px;
  cursor: pointer;
}

.btn-small:hover {
  color: #172b4d;
}

.help-link {
  display: block;
  font-size: 12px;
  color: #0079bf;
  margin-bottom: 12px;
}

.message {
  margin-top: 12px;
  padding: 8px;
  border-radius: 4px;
  font-size: 13px;
  text-align: center;
}

.message.success {
  background: #e6f4ea;
  color: #137333;
}

.message.error {
  background: #fce8e6;
  color: #c5221f;
}

Advanced Features

Now that you have the basics working, here are some advanced features to consider adding:

Quick Card Creation with Keyboard Shortcuts

Add keyboard shortcuts for power users:

// In popup.js
document.addEventListener('keydown', (e) => {
  // Ctrl+Enter to create card
  if (e.ctrlKey && e.key === 'Enter') {
    document.getElementById('create-card-btn').click();
  }
});

Labels and Due Dates

Extend the card creation to support labels and due dates:

async function createCardWithExtras(listId, cardData) {
  const card = await trelloClient.createCard(listId, cardData);
  
  if (cardData.dueDate) {
    await trelloClient.request(`/cards/${card.id}`, 'PUT', {
      due: cardData.dueDate
    });
  }
  
  return card;
}

Add the ability to search and filter boards for users with many Trello boards:

function filterBoards(searchTerm) {
  const filtered = boards.filter(board => 
    board.name.toLowerCase().includes(searchTerm.toLowerCase())
  );
  // Re-populate select with filtered boards
}

Testing Your Extension

Before publishing, thoroughly test your trello chrome extension:

  1. Load Unpacked Extension: Go to chrome://extensions, enable Developer Mode, click “Load Unpacked”, and select your extension directory.

  2. Test Authentication: Enter your API key and token, verify the boards load correctly.

  3. Test Card Creation: Create cards on different boards and lists. Verify they appear in Trello with correct details.

  4. Test Context Menu: Right-click on pages and text to verify the context menu works.

  5. Test Edge Cases: Try creating cards with special characters, very long names, and empty descriptions.


Publishing to Chrome Web Store

When ready to publish:

  1. Create screenshots and a promotional image
  2. Write a detailed description including your target keywords (trello chrome extension, trello card creator, task management extension)
  3. Set up developer payment account ($5 one-time fee)
  4. Upload your extension and submit for review

Conclusion

Building a Trello Integration Chrome Extension is an excellent project that teaches you real-world skills in API integration, authentication, and Chrome extension development. You’ve learned how to:

  • Set up a Manifest V3 extension configuration
  • Implement Trello API authentication
  • Build a trello card creator with board and list selection
  • Add context menu integration for quick card creation
  • Style your extension with professional CSS

This task management extension provides immediate value to users and can be expanded with features like labels, due dates, attachments, and integrations with other productivity tools. The skills you gained here apply directly to building integrations with dozens of other APIs—from Slack to GitHub to Notion.

Start building your trello chrome extension today and watch your productivity soar!

No previous article
No next article