BoardBash Link

November 2025 – March 2026

Nested visual workspace and every creative's first project.

This was the first big project I ever tried to make. It was initially for a class hosted by DTI (a Cornell project team) called Trends in Web Development, but later I decided to finish it off on my own. Here’s the journey I went through to create and market this project!

What is a project that would make me think?

Frankly when I started brainstorming for this project I wanted to make something really simple. But after talking to my project manager Simon and seeing his awesome projects, that he made as a college freshman, I felt like I needed to make something cool too.

But what?

Of course I drew inspiration from my experience as an artist.

PureRef is an app I like to use when I need to find references for a new project. It provides a wide variety of image editing options through a very simplistic and easy to use interface.

The PureRef board I used when I was brainstorming for this personal website
The PureRef board I used when I was brainstorming for this personal website

The one thing I didn’t like, though, was the fact that my boards had to stay on my computer. I wanted a way to edit them on my ipad or phone. This want led to the idea of turning PureRef into a web based application. If it was just a website that let you create infinite boards, I didn’t see the difference from it and figma or google slides. I needed to combine it with something unique.

Que Notion!

I personally used Notion a lot. Not really for the aesthetics, but more for the convenience of nesting ideas easily. That’s when the idea of putting the two together came to me. I thought: being able to map out my ideas in a nested workplace visually instead of using a text-based interface, that’s gold!

More than creating an application that could be useful to me, I was excited about the learning I would undergo as I did the project.

I was excited about figuring out the database structure for the nested boards. How would I manage the complicated relationships between boards and the ripple effect of changing those relationships. I was excited about creating the infinite canvas interface. How would I sync the user’s movement with the database?

These lingering questions told me I had found a project interesting enough for me to create.

Design

The base design for the website
The base design for the website

I wanted to make the design simple, and leave the focus on the infinite canvas. So I made a conscious decision to treat the sidebar not as a collection of the user’s created boards, but their “open” boards. This way users only keep the boards relevant to them on screen. The bottom bar as well, I lowered its opacity when the user isn’t focused on it to reduce clutter.

A look of the actual design, the theme is customizable
A look of the actual design, the theme is customizable

The often forgotten part about creating an interactable infinite canvas is making it mobile friendly. The size of a phone screen can make it difficult to edit items, especially images, which often don’t fit on screen. To solve this I took inspiration from Figma and made the canvas view only when the screen size was too small.

Overall I made purposeful decisions to keep the site simple, while packing it with tons of features perfect for visual designers.

The same board on mobile
The same board on mobile

Development

When I started this project I had no idea how much WORK these apps (Canva, Google Docs, Google Slides, Figma) did to ensure everything looked seamless. Building this site taught me that there was so much more beneath the scenes.

On a high level, my app has three main interconnected features: the overall state, the text and image editor, and the board and block relationship. I’ll break down each in the next sections. Briefly remember I am building this website with this goal in mind: I want to create hierarchical infinite canvas boards with interactable blocks.

Managing State

A simple board needs to constantly sync it’s state with the backend. I had to focus on the board’s state and the opened board’s relationships, Notion’s nested boarding. To do this, I used React’s useContext hooks to propogate this shared state accross all frontend components. I had three big ones: the data context, sidebar context, and editor context.

The data context takes care of api calls with the changing board and block data. This was the primary context; it held the syncing, block metadata (location, size, etc), board data.

The sidebar context keeps track of the currently open boards, pinned boards, and boards that also double as folders.

The editor context deals with the undo and redo stack, block selection, copying blocks onto the clipboard happened here.

A visual to help simplify things
A visual to help simplify things

So the data context focused on both the boards and blocks, containing the actual information polled from the backend. The sidebar context and editor context used ids to interact with the data context. The sidebar context primarly focused on the relationship between boards, while the editor context focused almost entirely on the current active board’s blocks.

This modularization was deliberate. I wanted to focus my useContext hooks on the two main focuses of the app, the boards and the blocks.

I made the Block type an interface so I could easily extend it and add more block types
I made the Block type an interface so I could easily extend it and add more block types

The types look simple, but they took time to perfect.

The idea of treating boards as linked nodes came to me instantly, but I didn’t initially separate blocks from boards. Initially boards were a type of block called BoardBlock. I think keeping it like that could’ve worked, but it grew overcomplicated as I kept thinking about different edge cases.

Boards inherently deal with a different set of responsibilities compared to blocks e.g. sharing, routing, archiving. Since I dealt with them individually so often, it felt smarter to make board its own type.

Text and Image Editor

The infamous toolbar editing bar thingy is another one of those things that look easy to implement but is a pain. Since I wanted the site to be friendly on mobile platforms, I couldn’t rely on keybinds for block edits. So I took inspiration from google docs and decided to use a floating toolbar.

The initial idea was simple: when a user clicks on a block the toolbar becomes visible and the user can use it to interact with the block. It got more complicated when I realized it needed to display different editing options based on the block type, as well as be able to handle multi-block selection.

I eventually decided on a greedy approach. Rather than the intersection, I allowed all the possible editing options appear when multiple blocks types are selected. This way the user wouldn’t have to do extra work with removing the unwanted block types.

What the image editor looks like
What the image editor looks like

The toolbar works together with the editor context and data context. It reads from the editor context the selected IDs and bridges the information gap by getting the block’s actual types from the data context. Every mutation (mirroring, cropping, changing the opacity, etc) is pushed to the history stack on the editor context and then synced with the backend using the data context.

To handle the vast amount of operations associated with each block type, I created an Operation interface. Each operation had a common function “apply” that describes the interaction’s block edit, and these objects are described in files like universal.ts, image.ts, text.ts. This common function returns a partial block type. I did this because I wanted to compile the operations into a list and batch them so they would apply all at once.

In addition to the toolbar, I made a text editor which uses TipTap for its formatting.

What the text editor looks like
What the text editor looks like

Board Block Relationships

I briefly touched on the board and block relationship in the state section, but I want to spend more time explaining it more because it is a very core part of this project.

Essentially, boards need to exist as individual items that appear on the sidebar, and as blocks that appear on another board’s canvas. Rather than use one item, I split this into blocks with the type “board” and gave boards a parentBoardBlockId.

Root boards are identified by null parentBoardBlockIds.
Root boards are identified by null parentBoardBlockIds.

Did I accomplish my goal?

I set out on this project to learn something new and build something cool and I managed to accomplish that! Advertising for this project was rough, but as of July 2026 we managed to reach over 300 users and obtain 2.9k views. It’s not crazy, but pretty good for a first project.

I really enjoyed the process.

Conclusion

Hope you learned something while reading this blog, and feel inspired to create your own project. This is just a very brief overview of certain select components that I felt were cool and fun to share. Of course there’s much more that I didn’t cover.

Finally, I couldn’t accomplish this project alone. I owe the world to my friend Joy for helping out with the shared board links and building this with me!

A sneak peak into the future

I’m taking a pause on this project right now to work on skellysearch. I chatted with some artists and one thing they mentioned that stood out to me was that they wanted a way to quickly photobash new ideas when they were brainstorming for new projects. At my research lab, one of the other undergrads is using SAM and YOLO to quickly segment and identify objects tracked by a user’s gaze. That gave me some new ideas for this project that I think will be very interesting. Stay tuned for future updates!

Project Documentation

A compilation of notes from when I was actually working on the project. It contains designs for the actual application, the landing page, and some pages that never made it onto the site. Hope there’s something of value from my convoluted notebook of thoughts.