Concept Map Builder Chrome Extension (2026)

Concept maps are powerful tools for visualizing relationships between ideas. Building a Chrome extension that enables users to create, edit, and export concept maps directly from their browser opens up numerous possibilities for knowledge workers, researchers, and developers. This guide walks you through the architecture, key components, and implementation details for creating a functional concept map builder as a Chrome extension.

Understanding the Core Architecture

A Chrome extension concept map builder consists of three primary components: the popup interface, the background service worker, and the content script for page interaction. The popup handles the primary user interface where users create and manipulate nodes. The background worker manages data persistence and handles communication between different parts of the extension.

The data model for a concept map is straightforward. Each node represents a concept, and edges represent relationships between concepts. A simple JSON structure captures this:

const conceptMap = {
 nodes: [
 { id: "node-1", label: "Chrome Extension", x: 100, y: 100 },
 { id: "node-2", label: "Concept Map", x: 300, y: 200 },
 { id: "node-3", label: "JavaScript", x: 500, y: 100 }
 ],
 edges: [
 { from: "node-1", to: "node-2", label: "creates" },
 { from: "node-1", to: "node-3", label: "uses" }
 ]
};

This structure allows you to serialize the concept map easily for storage and export.

Setting Up the Extension Structure

Every Chrome extension requires a manifest file. For a concept map builder targeting modern Chrome versions, use Manifest V3:

{
 "manifest_version": 3,
 "name": "Concept Map Builder",
 "version": "1.0",
 "description": "Create and manage concept maps from your browser",
 "permissions": ["storage", "activeTab"],
 "action": {
 "default_popup": "popup.html",
 "default_icon": "icon.png"
 },
 "host_permissions": ["<all_urls>"]
}

The popup.html file serves as your primary interface. Include a canvas element for rendering the concept map and toolbar buttons for common actions like adding nodes, connecting them, and exporting the result.

Implementing the Canvas Rendering

The rendering engine is the heart of your concept map builder. HTML5 Canvas provides excellent performance for interactive diagrams. Create a dedicated JavaScript module that handles node rendering, edge drawing, and user interactions.

class ConceptMapRenderer {
 constructor(canvasId) {
 this.canvas = document.getElementById(canvasId);
 this.ctx = this.canvas.getContext('2d');
 this.nodes = [];
 this.edges = [];
 this.selectedNode = null;
 this.dragging = null;
 
 this.setupEventListeners();
 }
 setupEventListeners() {
 this.canvas.addEventListener('mousedown', this.handleMouseDown.bind(this));
 this.canvas.addEventListener('mousemove', this.handleMouseMove.bind(this));
 this.canvas.addEventListener('mouseup', this.handleMouseUp.bind(this));
 }
 render() {
 this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
 this.drawEdges();
 this.drawNodes();
 }
 drawNodes() {
 this.nodes.forEach(node => {
 this.ctx.fillStyle = node.selected ? '#4a90d9' : '#ffffff';
 this.ctx.fillRect(node.x - 50, node.y - 25, 100, 50);
 this.ctx.strokeRect(node.x - 50, node.y - 25, 100, 50);
 this.ctx.fillStyle = '#333333';
 this.ctx.fillText(node.label, node.x, node.y + 5);
 });
 }
 drawEdges() {
 this.edges.forEach(edge => {
 const fromNode = this.nodes.find(n => n.id === edge.from);
 const toNode = this.nodes.find(n => n.id === edge.to);
 if (fromNode && toNode) {
 this.ctx.beginPath();
 this.ctx.moveTo(fromNode.x, fromNode.y);
 this.ctx.lineTo(toNode.x, toNode.y);
 this.ctx.stroke();
 }
 });
 }
}

This renderer supports basic node selection, dragging, and edge visualization. Extend it with double-click handlers for node editing and zoom controls for larger concept maps.

Managing State and Persistence

Chrome’s storage API provides reliable persistence for your concept maps. Use chrome.storage.local for extension-specific data:

class ConceptMapStore {
 static async saveMap(mapId, data) {
 return new Promise((resolve, reject) => {
 chrome.storage.local.set({ [mapId]: data }, () => {
 if (chrome.runtime.lastError) {
 reject(chrome.runtime.lastError);
 } else {
 resolve();
 }
 });
 });
 }
 static async loadMap(mapId) {
 return new Promise((resolve, reject) => {
 chrome.storage.local.get(mapId, (result) => {
 if (chrome.runtime.lastError) {
 reject(chrome.runtime.lastError);
 } else {
 resolve(result[mapId] || null);
 }
 });
 });
 }
 static async listMaps() {
 return new Promise((resolve) => {
 chrome.storage.local.get(null, (result) => {
 resolve(Object.keys(result));
 });
 });
 }
}

This storage layer enables users to save multiple concept maps and resume their work across browser sessions.

Adding Export Functionality

Users often need to export their concept maps for presentations or documentation. Implement multiple export formats:

function exportAsJSON(mapData) {
 const blob = new Blob([JSON.stringify(mapData, null, 2)], { 
 type: 'application/json' 
 });
 downloadBlob(blob, 'concept-map.json');
}
function exportAsPNG(canvas) {
 canvas.toBlob((blob) => {
 downloadBlob(blob, 'concept-map.png');
 });
}
function exportAsSVG(nodes, edges) {
 let svg = '<svg xmlns="http://www.w3.org/2000/svg">';
 edges.forEach(edge => {
 svg += `<line x1="${edge.from.x}" y1="${edge.from.y}" x2="${edge.to.x}" y2="${edge.to.y}" stroke="black"/>`;
 });
 nodes.forEach(node => {
 svg += `<rect x="${node.x-50}" y="${node.y-25}" width="100" height="50" fill="white" stroke="black"/>`;
 svg += `<text x="${node.x}" y="${node.y+5}" text-anchor="middle">${node.label}</text>`;
 });
 svg += '</svg>';
 const blob = new Blob([svg], { type: 'image/svg+xml' });
 downloadBlob(blob, 'concept-map.svg');
}
function downloadBlob(blob, filename) {
 const url = URL.createObjectURL(blob);
 const a = document.createElement('a');
 a.href = url;
 a.download = filename;
 a.click();
 URL.revokeObjectURL(url);
}

Integrating with Web Content

A powerful feature for a concept map builder is the ability to extract content from web pages. Use content scripts to scrape headings and key terms:

// content.js
function extractPageContent() {
 const headings = Array.from(document.querySelectorAll('h1, h2, h3'))
 .map(h => h.textContent.trim());
 
 const links = Array.from(document.querySelectorAll('a'))
 .map(a => ({
 text: a.textContent.trim(),
 href: a.href
 }))
 .filter(l => l.text && l.href);
 return { headings, links };
}
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
 if (request.action === 'extractContent') {
 const content = extractPageContent();
 sendResponse(content);
 }
});

This enables users to quickly generate concept maps from research materials or organize their browsing findings.

Performance Optimization Tips

For larger concept maps, implement viewport culling to only render visible nodes. Use requestAnimationFrame for smooth drag interactions. Consider using Web Workers for complex layout algorithms if you implement automatic node positioning.

function renderFrame() {
 if (this.needsRender) {
 this.render();
 this.needsRender = false;
 }
 requestAnimationFrame(this.renderFrame.bind(this));
}

Step-by-Step: Creating Your First Concept Map

  1. Open any article, documentation page, or research paper in Chrome
  2. Click the extension icon to open the concept map editor panel
  3. Click “Extract Concepts”. the content script identifies key terms from the page text
  4. Drag extracted concepts onto the canvas as nodes
  5. Click two nodes sequentially to create an edge (relationship) between them
  6. Label the edge by typing in the popup that appears (“causes”, “depends on”, “part of”)
  7. Click “Export” to download the map as SVG or JSON for use in other tools

Advanced: Auto-Generating Edges from Page Content

Parse sentence co-occurrences to suggest relationships between extracted concepts:

function suggestEdges(concepts, pageText) {
 const sentences = pageText.split(/[.!?]+/);
 const suggestions = [];
 for (const sentence of sentences) {
 const presentConcepts = concepts.filter(c => sentence.toLowerCase().includes(c.toLowerCase()));
 if (presentConcepts.length >= 2) {
 for (let i = 0; i < presentConcepts.length - 1; i++) {
 suggestions.push({
 from: presentConcepts[i],
 to: presentConcepts[i + 1],
 sentence: sentence.trim(),
 confidence: 0.6
 });
 }
 }
 }
 return suggestions;
}

Display suggested edges as dashed lines that users can confirm or dismiss with a click.

Comparison with Standalone Mind-Mapping Tools

Feature This Extension MindMeister Miro
Auto-extract from web pages Yes No No
Browser-native Yes No (app) No (app)
Offline support Yes (local storage) No No
Collaboration Not included Yes Yes
Cost Free to build Freemium Freemium

The extension’s key differentiator is the ability to extract concepts directly from the web page you are reading, rather than manually entering all nodes. Miro and MindMeister win for collaborative work.

Troubleshooting Common Issues

Canvas performance degrades with many nodes: Switch from SVG to Canvas API rendering for concept maps with more than 50 nodes. Use requestAnimationFrame and only redraw elements that have changed:

function renderFrame() {
 if (this.needsRender) {
 this.render();
 this.needsRender = false;
 }
 requestAnimationFrame(this.renderFrame.bind(this));
}

Concept extraction returning too many or too few terms: Add a relevance threshold based on term frequency. filter out both very common words (stop words) and very rare words that appear only once in the text.

Export JSON not compatible with other tools: Use standard graph interchange formats like GraphML or the Cytoscape.js JSON format so exported maps can be imported into visualization tools.

Edges overlapping nodes on complex maps: Implement a simple force-directed layout algorithm that spaces nodes apart automatically, or let users drag nodes to manual positions and snap to a grid.

The modular architecture separates concerns cleanly, making it straightforward to add features like deal alerts, real-time collaboration, or integration with Obsidian and Roam Research.


Try it: Paste your error into our Error Diagnostic for an instant fix.

I'm a solo developer in Vietnam. 50K Chrome extension users. $500K+ on Upwork. 5 Claude Max subscriptions running agent fleets in parallel. These are my actual CLAUDE.md templates, orchestration configs, and prompts. Not a course. Not theory. The files I copy into every project before I write a line of code. **[See what's inside →](https://zovo.one/lifetime?utm_source=ccg&utm_medium=cta-default&utm_campaign=chrome-extension-concept-map-builder)** $99 once. Free forever. 47/500 founding spots left.

Related Reading

Built by theluckystrike. More at zovo.one

Find the right skill → Browse 155+ skills in our Skill Finder.