046
LVL 02 — CIRCUIT BREAKER SESSION 046 DAY 46

LAYER SYSTEM

🎫 PIXELCRAFT-034
Feature | 🟠 Hard | Priority: 🟠 High

Users want to stack multiple images as layers, adjust opacity, reorder layers, toggle visibility, and merge layers. This is a core feature for any serious image editor.
CONCEPTS.UNLOCKED
🔗
Linked List Data Structure
Nodes connected by pointers (next, prev). Unlike arrays, elements aren't stored contiguously in memory. Each node knows only its neighbors — no index, no position number.
Doubly Linked List
Each node has prev and next pointers — traverse in both directions. Navigate from top layer to bottom or bottom to top. Essential for layer reordering.
Operations
Insert (add a layer), delete (remove a layer), move up/down (reorder by rewiring pointers), traverse (walk the list to render all layers).
Linked List vs Array
Reorder: linked list O(1) pointer swap vs array O(n) shift. Random access: array O(1) index vs linked list O(n) walk. Choose based on your access patterns.
🎚
Layer Properties
Each layer has: id, name, imageData, opacity, visible, blendMode. Layers are composited bottom-to-top onto the canvas, each with its own opacity and visibility.
React + Dynamic Lists
Build a <LayerPanel> component that renders the linked list as a draggable, interactive UI. Each layer item shows a thumbnail, name, opacity slider, and visibility toggle.
HANDS-ON.TASKS
01
Implement the DoublyLinkedList
class LayerNode { constructor(data) { this.data = data; // { id, name, imageData, opacity, visible, blendMode } this.prev = null; this.next = null; } } class LayerList { constructor() { this.head = null; // Top layer (rendered last) this.tail = null; // Bottom layer (rendered first) this.size = 0; } addLayer(data) { const node = new LayerNode(data); if (!this.head) { this.head = this.tail = node; } else { node.next = this.head; this.head.prev = node; this.head = node; } this.size++; return node; } removeLayer(node) { if (node.prev) node.prev.next = node.next; else this.head = node.next; if (node.next) node.next.prev = node.prev; else this.tail = node.prev; this.size--; } toArray() { const result = []; let current = this.head; while (current) { result.push(current.data); current = current.next; } return result; } }
head = top layer (rendered last, appears on top). tail = bottom layer (rendered first, the background). addLayer puts new layers on top by default.
02
Implement moveUp
moveUp(node) { if (!node.prev) return; // Already at top const prev = node.prev; // Swap positions in the list if (prev.prev) prev.prev.next = node; else this.head = node; if (node.next) node.next.prev = prev; else this.tail = prev; node.prev = prev.prev; prev.next = node.next; prev.prev = node; node.next = prev; }
Four pointer reassignments = O(1) reorder. In an array, moving an element requires shifting every other element — O(n). For layers that get reordered constantly, linked list wins.
03
Build the LayerPanel Component
function LayerPanel({ layers, onReorder, onToggleVisibility, onOpacityChange, onDelete }) { return ( <div className="flex flex-col gap-1 p-2 bg-slate-900"> <h3 className="text-xs font-bold text-slate-400 uppercase">Layers</h3> {layers.map((layer, index) => ( <LayerItem key={layer.id} layer={layer} onMoveUp={() => onReorder(layer.id, 'up')} onMoveDown={() => onReorder(layer.id, 'down')} onToggle={() => onToggleVisibility(layer.id)} onOpacity={(val) => onOpacityChange(layer.id, val)} onDelete={() => onDelete(layer.id)} /> ))} <button onClick={onAddLayer} className="...">+ New Layer</button> </div> ); }
04
Render Layers to Canvas

Traverse the list bottom-to-top (tail → head). Composite each visible layer onto the canvas with its opacity. Bottom layer first = background, top layer last = foreground.

05
Test All Operations

Add 5 layers, reorder them, toggle visibility, adjust opacity, merge two layers. Verify rendering order matches the layer panel display at every step.

06
Close the Ticket
git switch -c feature/PIXELCRAFT-034-layers git add src/ git commit -m "Add layer system with doubly linked list (PIXELCRAFT-034)" git push origin feature/PIXELCRAFT-034-layers # PR → Review → Merge → Close ticket ✅
CS.DEEP-DIVE

Data structure selection depends on your access patterns.

There is no "best" data structure — only the right one for your specific operations.

// Choosing the right data structure:

Layers (frequent reorder)
  → linked list O(1) insert/remove
Pixels (random access by coord)
  → array O(1) index
Undo history (LIFO access)
  → stack

// This is the essence of data structure
// selection and one of the most important
// decisions in software design.
"Layer Lab"
[A] Add drag-and-drop reordering to the LayerPanel using the HTML Drag and Drop API. Map drag events to moveUp/moveDown operations on the linked list.
[B] Implement a "Merge Down" feature: combine the selected layer with the one below it (composite their imageData), then remove the top layer.
[C] Benchmark: implement the same layer operations using an array. Compare the performance of reordering 100 layers. At what size does the linked list advantage show?
REF.MATERIAL
VIDEO
CS50 / Harvard
Clear visual explanation: nodes, pointers, insertion, deletion, traversal, and the tradeoffs vs arrays.
LINKED LISTCS50ESSENTIAL
VIDEO
Fireship
Rapid overview: singly vs doubly linked, operations, Big O comparison with arrays, and real-world uses.
LINKED LISTQUICK
ARTICLE
javascript.info
Overview of data structures in JavaScript: arrays, linked lists, trees, hash maps. When to use each and implementation patterns.
DATA STRUCTURESOVERVIEW
ARTICLE
Wikipedia
Theory: node structure, operations, complexity analysis, and comparison with singly linked lists and arrays.
LINKED LISTTHEORYCS
VIDEO
NeetCode
Essential data structures overview: when to use arrays, linked lists, stacks, queues, hash maps, and trees. Interview prep perspective.
DATA STRUCTURESINTERVIEW
// LEAVE EXCITED BECAUSE
You built Photoshop layers. Drag a layer → rendering order changes → image updates. A CS textbook data structure powers a real product feature.