Build a Digital Mood Board App
Create a drag-and-drop mood board for planning aesthetics, projects, and vibes. Pinterest but make it yours.
Build a Digital Mood Board App
Pinterest is great but sometimes you just want a blank canvas where you can throw images, colors, text, and vibes together without an algorithm telling you what to look at. Let's build your own mood board app.
๐ก Pro tip
Want to see the finished app first? Try the live demo and come back to learn how it works!
Why Would You Build This?
Real talk โ mood boards aren't just for aesthetics (although they're great for that). People use them for:
- Planning a rebrand โ collecting colors, fonts, and visual inspo before redesigning a website or social media
- Apartment decorating โ pulling together furniture, paint colors, and textures before you commit
- Event planning โ weddings, parties, photoshoots โ visualizing the vibe before spending money
- Creative projects โ album art, YouTube thumbnails, merch designs
- Vision boards โ goals, affirmations, dream life visualization
And building it yourself means no watermarks, no subscription fees, and no ads for things you already bought.
๐ฌ Denise says
I use mood boards for literally everything โ redesigning my website, planning content, even figuring out what I want my apartment to look like. Building one as a coding project means you learn drag-and-drop, canvas layouts, and image handling, all while making something you'll genuinely use.
What We're Building
- A blank canvas you can add items to
- Drag and drop to rearrange
- Add images (from URL or upload)
- Add color swatches
- Add text notes
- Save your board to come back to later
Step 1: The Board Data
1// Each item on the board has a position, size, and content2const boardItem = {3id: 1,4type: 'image', // 'image', 'color', 'text'5content: 'https://example.com/photo.jpg', // URL, hex color, or text6x: 120, // position from left7y: 80, // position from top8width: 200,9height: 250,10rotation: -3, // slight tilt for that collage feel11};1213// A board is just a collection of items14const board = {15id: 'spring-vibes',16name: 'Spring Vibes',17items: [],18background: '#FFF8F0',19};
Step 2: Draggable Item Component
1import { useState } from 'react';23function BoardItem({ item, onMove, onDelete }) {4const [isDragging, setIsDragging] = useState(false);5const [dragStart, setDragStart] = useState({ x: 0, y: 0 });67const handleMouseDown = (e) => {8setIsDragging(true);9setDragStart({10x: e.clientX - item.x,11y: e.clientY - item.y,12});13};1415const handleMouseMove = (e) => {16if (!isDragging) return;17onMove(item.id, {18x: e.clientX - dragStart.x,19y: e.clientY - dragStart.y,20});21};2223const handleMouseUp = () => {24setIsDragging(false);25};2627return (28<div29className={`board-item ${isDragging ? 'dragging' : ''}`}30style={{31left: item.x,32top: item.y,33width: item.width,34transform: 'rotate(' + item.rotation + 'deg)',35}}36onMouseDown={handleMouseDown}37onMouseMove={handleMouseMove}38onMouseUp={handleMouseUp}39>40{item.type === 'image' && (41<img src={item.content} alt='' draggable={false} />42)}43{item.type === 'color' && (44<div className='color-swatch' style={{ background: item.content }} />45)}46{item.type === 'text' && (47<p className='board-text'>{item.content}</p>48)}4950<button className='delete-item' onClick={() => onDelete(item.id)}>x</button>51</div>52);53}
Step 3: The Toolbar
1function Toolbar({ onAddItem }) {2const [showColorPicker, setShowColorPicker] = useState(false);34const addImage = () => {5const url = prompt('Paste an image URL:');6if (url) {7onAddItem({8type: 'image',9content: url,10width: 200,11height: 250,12rotation: Math.random() * 6 - 3, // random tilt between -3 and 313});14}15};1617const addText = () => {18const text = prompt('What do you want to add?');19if (text) {20onAddItem({21type: 'text',22content: text,23width: 180,24height: 'auto',25rotation: Math.random() * 4 - 2,26});27}28};2930const addColor = (color) => {31onAddItem({32type: 'color',33content: color,34width: 80,35height: 80,36rotation: Math.random() * 8 - 4,37});38setShowColorPicker(false);39};4041const presetColors = [42'#F4A7BB', '#C4B8E8', '#A8D8EA', '#F0D9A0',43'#F2A5C0', '#F5C2D0', '#FEF1C7', '#957DAD',44'#FF6B6B', '#4ECDC4', '#2D2D2D', '#FFFFFF',45];4647return (48<div className='toolbar'>49<button onClick={addImage}>๐ผ๏ธ Image</button>50<button onClick={addText}>โ๏ธ Text</button>51<button onClick={() => setShowColorPicker(!showColorPicker)}>52๐จ Color53</button>5455{showColorPicker && (56<div className='color-grid'>57{presetColors.map(color => (58<button59key={color}60className='color-option'61style={{ background: color }}62onClick={() => addColor(color)}63/>64))}65</div>66)}67</div>68);69}
Step 4: The Full Board
1function MoodBoard() {2const [items, setItems] = useState([]);3const [boardName, setBoardName] = useState('My Mood Board');45const addItem = (itemData) => {6setItems(prev => [...prev, {7...itemData,8id: Date.now(),9x: 100 + Math.random() * 200,10y: 100 + Math.random() * 200,11}]);12};1314const moveItem = (id, position) => {15setItems(prev => prev.map(item =>16item.id === id ? { ...item, ...position } : item17));18};1920const deleteItem = (id) => {21setItems(prev => prev.filter(item => item.id !== id));22};2324const saveBoard = () => {25const data = { name: boardName, items };26localStorage.setItem('moodboard', JSON.stringify(data));27};2829return (30<div className='mood-board-app'>31<header className='board-header'>32<input33value={boardName}34onChange={e => setBoardName(e.target.value)}35className='board-name-input'36/>37<button onClick={saveBoard} className='save-btn'>38Save Board39</button>40</header>4142<Toolbar onAddItem={addItem} />4344<div className='canvas'>45{items.map(item => (46<BoardItem47key={item.id}48item={item}49onMove={moveItem}50onDelete={deleteItem}51/>52))}53{items.length === 0 && (54<p className='empty-canvas'>55Click the buttons above to start adding to your board โจ56</p>57)}58</div>59</div>60);61}
Level Up Ideas
- Multiple boards โ save and switch between different mood boards
- File upload โ drag images from your computer instead of pasting URLs
- Resize handles โ drag corners to resize items
- Layers โ bring items forward or send them backward
- Export as image โ save your board as a PNG to share
- Collaborative โ share a board link and build together in real-time
๐ฌ Denise says
This project teaches you drag-and-drop interactions, dynamic positioning, state management with arrays, and localStorage โ all real skills that show up in professional apps. And you end up with something beautiful that you can use for your next project, room makeover, or event. Building pretty things that teach you real skills? That's the vibe.
Photo coming soon โจ
Want to keep going?
Tell me what you want to build next and I'll help you write the code.
Start Building โจ