📌 day 2: a shared pinboard for your photo cutouts
today’s theme was “maps” and i immediately thought of those cork pinboards with photos and strings connecting places. i wanted to build something where you could grab a photo from your camera roll, use that iOS cutout feature (you know, the wooOooOomP one), and pin it to a shared board. originally i was going to use actual location data but getting camera permissions and location permissions and all that just seemed… hard. so instead: everyone pins their cutouts and moves stuff around together.
is this very maps? no. oh well.
a wall-to-wall corkboard where you upload any image, server removes the background, adds a random photo-style background and washi tape, and everyone can drag everything around.
the web tech
the corkboard itself
- seamless corkboard texture as a full-viewport
background-imagewithbackground-size: cover position: fixedon the main element fills the entire screenoverflow: hiddenkeeps everything on the board
the upload flow
- click “Add Pin” button
- choose any image from your device
- add a label to describe it
- appears on the board with randomized photo styling
photo styling with randomized backgrounds & washi tape
every upload gets wrapped in a polaroid-style photo frame:
<div class="sticker-image-wrapper" style="background: #FAFAFA">
<div class="washi-tape washi-tape-left" style="background: #FFB3D9"></div>
<div class="washi-tape washi-tape-right" style="background: #B5EAD7"></div>
<img src="..." />
</div>
the server randomly picks:
- a subtle background color from 6 off-white tints
- two washi tape colors from a pastel palette
- a starting position on the board (avoiding edges)
the washi tape sits at the top corners with slight rotation:
.washi-tape-left {
top: -8px;
left: 20px;
transform: rotate(-8deg);
}
.washi-tape-right {
top: -8px;
right: 20px;
transform: rotate(8deg);
}
draggable everything
the drag system works for the sticky note, uploaded photos, everything:
function makeDraggable(element) {
element.addEventListener('mousedown', startDrag);
element.addEventListener('touchstart', startDrag, { passive: false });
}
key points:
- track
offsetXandoffsetYwhen drag starts so elements don’t jump - constrain positions to viewport:
Math.max(0, Math.min(newX, maxX)) - support both mouse and touch for mobile
- save positions to server on drop
- sync positions every 2 seconds so everyone sees moves in near-realtime