Back to selected work

After watching our first online karaoke event depend on a crowded chat, an improvised spreadsheet, and one DJ's memory, I saw an opportunity for a purpose-built product. Before our second event, I designed and AI-engineered ShareQ: a real-time queue that helped singers request tracks, gave hosts a reliable running order, and turned more than 100 song records into a shared memory of the night.

My role
Product strategy, UX/UI design, AI-assisted frontend and backend engineering, testing, and launch
Timeline
Live MVP designed and built over one weekend, followed by post-event iteration
Validation
2 focused testers, informal community checks, and live use at an event with approximately 20 attendees
Outcome
One live community event and an event history containing more than 100 songs, including manually recovered records
Built with
Node.js, Express, Socket.IO, JavaScript, AI-assisted development, Git, and Render
Current ShareQ room showing the song request form, now-playing area, reactions, shared queue, members, messages, and activity feed
The current ShareQ room. Participants and hosts work from the same live state, while the interface gives each role the controls and information it needs.

The first event ran on chat and memory

Our online community's first karaoke event lasted for roughly ten hours. It was joyful, but the operating model was improvised.

People requested songs in the same chat used for reactions and general conversation. Several requests could arrive almost simultaneously, then disappear as new messages pushed them upward. Whoever acted as DJ had to search YouTube Music or Spotify, find the right accompaniment, remember the order, and keep track of who was supposed to sing next.

Playing a track was also difficult for less technical participants. A singer might need to find a video, share their screen, expose the correct audio source, find readable lyrics, and stop sharing afterward. Each handoff interrupted the event.

I eventually stepped in as DJ for several hours. I had YouTube Music Premium and a synchronized lyrics extension, so I could give singers a more consistent backing track and readable lyrics. I was also singing, monitoring the chat, and occasionally helping manage the crowd.

The experience revealed the real system: the DJ had become human middleware between chat, music search, playback, lyrics, screen sharing, and the social dynamics of the room.

The queue did not exist anywhere the group could trust. It lived across the chat, a spreadsheet, and the DJ's memory.

A spreadsheet recorded songs, but it did not manage karaoke

During the first event, I found an online Excel-style tool and created a shared list. It gave us columns for the song, original artist, and intended singer. That was better than memory, but it treated the event as data entry rather than a live social experience.

Three problems remained:

  1. The queue had no meaningful state. A row did not clearly communicate what was playing, what was next, what had been skipped, or what had already been performed.
  2. Assignment was mistaken for consent. Community members playfully added songs for one another. A person could suddenly find multiple songs assigned to them even if they did not want to sing.
  3. The event had no memory. When I arrived late, I could not answer a simple question: what had already been sung, and by whom?

The third issue was not something participants had explicitly requested. It was a product opportunity I recognized from my own experience. A queue could solve the immediate coordination problem, but a history could help late arrivals understand the event and give the community something to revisit afterward.

From a shared document to ShareQ

The name came directly from the workaround. The first event used a shared spreadsheet. The second needed a shared queue. Combining those ideas produced ShareQ.

The product question became:

How might we let a community coordinate a live karaoke queue without making one DJ remember everything, while preserving the consent and playful energy that make karaoke social?

This framing prevented me from building a generic music platform. ShareQ did not need to replace YouTube Music, Spotify, voice chat, or screen sharing. It needed to become the coordination layer between them.

A fixed event made speed part of the design problem

The second karaoke event gave me a hard deadline. I had one weekend to turn an observed problem into something people could actually use together.

I used Antigravity as an implementation partner. I translated the experience into flows, states, permissions, responsive rules, and detailed acceptance criteria. The AI generated and modified code; I directed the product, evaluated the interface, reproduced failures, and decided whether each implementation matched the intended behavior.

My working loop was rapid but concrete:

  1. Identify a failure or opportunity from the event workflow.
  2. Specify who needed what information, in which state, and why.
  3. Ask the AI to implement the smallest testable change.
  4. Inspect the result in the browser, often at multiple viewport sizes.
  5. Correct interaction logic, hierarchy, copy, and edge cases.
  6. Commit, deploy to the development environment, and test again.

This process let me move from idea to a working real-time product quickly. It also exposed the limits of AI-generated implementation. Antigravity sometimes reported a task as complete when the page was structurally broken or the requested behavior worked only in one state. I learned not to treat a confident completion summary as evidence.

After broken layouts and deployment regressions, I tightened the process: local verification before deployment, a separate development branch and server, small commits for individual changes, explicit dev-versus-master release notes, and automated tests for critical flows. AI increased my implementation speed; product judgment and verification kept that speed from becoming uncontrolled risk.

Designing one shared system for three different needs

ShareQ had to work for active singers, the DJ or co-host, and participants who mostly wanted to watch the event unfold. Giving everyone the same controls would create clutter and invite mistakes, so I designed a shared state with different levels of agency.

Everyone sees the same event, but permissions reflect each person's responsibility.

Decision 1: Remove account setup from a temporary social event

This was a community event, not a service people needed to adopt permanently. Requiring account creation would add friction at exactly the moment someone wanted to sing.

Participants instead chose a recognizable nickname and avatar, then joined with a short room code or shared link. The lightweight identity was enough to connect a person to their requests, reactions, and permissions without introducing passwords or profiles.

ShareQ onboarding screen with nickname, avatar, join-room, and create-room controls
Identity and entry are combined into one screen. The amount of setup matches the temporary nature of the event.
ShareQ create-room screen explaining the generated room ID and shareable link
The host sees what will happen before creating a room: a unique code and a link that can be sent directly to the community.

Decision 2: Let participants reduce the DJ's search work

A song request captured the title, original artist, intended singer, and an optional accompaniment link. The link was not extra metadata for its own sake. During the first event, finding the correct track repeatedly interrupted the DJ.

When participants supplied a YouTube link, the DJ could open the intended accompaniment directly instead of interpreting an ambiguous title and searching during the event. This moved a small piece of work to the person who already knew which version they wanted.

The interface kept the request form beside the queue. Participants could act and immediately verify the result in one context, instead of submitting into an invisible system.

Decision 3: Turn assigning a song into a consent-based request

The spreadsheet allowed anyone to put another person's name into a row. That was socially playful, but structurally coercive. The interface treated a joke, suggestion, and commitment as the same action.

In ShareQ, dedicating a song to someone created a request rather than an automatic queue entry. The recipient could accept or decline it. Only an accepted song entered the performance queue.

This was one of the clearest examples of product logic coming directly from observed behavior. It preserved the fun of challenging a friend while returning control to the person expected to perform. A tester specifically appreciated this consideration, and community members used the feature during the live event.

Decision 4: Separate personal messages from ambient activity

An early layout placed system history below the central queue. It recorded events, but it competed with the primary task and made the interface feel like a collection of panels.

Early two-column ShareQ dashboard with song request controls on the left and the current song and queue on the right
The early dashboard established the core request and playback workflow, but it did not yet give the room's social activity a clear home.

I reframed notifications into two information types:

  • Messages contained direct requests that required one person's attention, such as a song dedication that needed an accept or decline decision.
  • Activity contained ambient room events, such as someone adding, prioritizing, deleting, or advancing a song.

On large screens, I moved both into a persistent third column inspired by the rhythm of a Twitch chat. The goal was not to imitate streaming aesthetics. It was to make the room feel inhabited while keeping operational events out of the queue.

Annotated ShareQ screenshot with the activity panel circled and an arrow pointing toward a new right-side column
My visual direction moved activity out of the queue column and into a dedicated social region. The annotation communicates both placement and the reason for reclaiming the primary workflow.

I also reduced the visual weight of activity filters, shortened timestamps to 24-hour hour-and-minute values, placed time after the event text, and tightened row spacing. These details kept the feed readable without letting it become the visual protagonist.

Decision 5: Change the information architecture on mobile, not only the dimensions

A persistent third column made sense on a desktop display, but stacking messages and activity beneath the queue on mobile created a very long page and allowed secondary information to dominate the screen.

The mobile design collapsed that content into a notification bell. Direct requests could trigger a toast and unread badge; tapping the bell opened a temporary drawer containing messages and activity. This preserved awareness without forcing every participant to scroll through an event log.

ShareQ responsive iteration where messages are stacked beneath the main queue and extend the page vertically
A failed responsive iteration simply stacked desktop regions. It technically fit the width, but produced the wrong hierarchy for a phone.
ShareQ mobile interface with a floating drawer showing messages and filtered activity
The revised mobile pattern uses progressive disclosure: the main queue remains focused while the bell provides access to personal and ambient updates.

This distinction became one of the project's most important responsive lessons: adaptation is not shrinking. It is deciding what should remain persistent when attention and space become constrained.

Decision 6: Make the current performance feel alive

The now-playing area needed to answer three questions at a glance: what is playing, who is singing, and what can the room do right now?

I gave the song and performer clear visual priority, used the requester's avatar as a slowly rotating focal point, and placed the audio waveform opposite it to balance the composition. Reactions remained close to the performance state so applause, roses, eggs, and shoes felt connected to the current singer rather than like unrelated controls.

I repeatedly adjusted this area after seeing implementation details that were technically correct but semantically wrong. For example, a generic record animation became the participant's rotating avatar, and then required further correction when uploaded image avatars fell back to a default emoji. These iterations were small visually, but important socially: the interface needed to represent the actual person participating.

Current ShareQ now-playing panel showing a song, performer avatar, reaction controls, and upcoming queue
The current performance state balances identity, song information, lightweight audience participation, and the next operational action.

Decision 7: Treat history as community memory, not an admin log

The completed-song history answered the question I had when arriving late: what happened before I got here?

The event export extended that idea beyond the live interface. It preserved the playlist, performers, timestamps, and lightweight statistics in a standalone HTML record. For the DJ, this created operational traceability. For the community, it acted as an event diary.

Statistics such as the most active singer, most requested artists, and songs receiving the most reactions were designed to make the archive enjoyable to revisit. They were not necessary to operate the queue, so they remained secondary to the live workflow.

Current ShareQ statistics view with top singer, requested artists, member list, and activity history
History and statistics transform transient queue activity into a record the community can revisit. This English version was added after the event.

Testing in increasingly realistic conditions

I did not run a formal usability study. With a fixed event approaching, I used a staged validation process that increased in realism.

First, I gave a complete screen-shared walkthrough to a community member who had attended the original event. They understood the context immediately, responded enthusiastically to a tool designed for this specific situation, reviewed the visual and functional direction, and later agreed to help co-host.

Second, I sent the Render deployment to another community member with programming experience. They exercised the functions remotely and gave me a more technically informed check of the working product.

Before launch, I invited several other members who happened to be online to open the URL and try the interface. Their feedback was informal, but it tested whether less technical participants could enter and orient themselves without a detailed explanation.

The final and most consequential test was the live event itself.

What live use validated

Approximately 20 community members attended the second event. Active singers and song requesters were the primary ShareQ users. Some listeners stayed entirely inside the voice and chat application, which revealed that ShareQ was a companion for active participation rather than a destination every attendee needed to keep open.

Several intended behaviors appeared in real use:

  • Singers submitted requests into the shared queue.
  • Participants supplied accompaniment URLs, reducing search work for the DJ.
  • Members used the consent-based song dedication flow.
  • The queue and reconstructed history contained more than 100 songs.
  • A community member independently kept a backup list when data was lost, demonstrating that preserving the running order genuinely mattered.

These observations are more meaningful than saying participants “liked” the product. They show which parts became embedded in the event's actual coordination.

The live failure that changed my definition of UX

The launch was not flawless. Early in the event, a critical bug repeatedly cleared song-ordering history after several minutes. I joined after the event had started, diagnosed and fixed the issue during the session, then manually reconstructed missing entries from a song list that another member had kept in a notepad.

The technical fix did not instantly restore adoption. Some participants returned to ShareQ, but fewer people used it after the interruption. The product had lost something more important than data: trust in the queue.

That experience changed how I evaluate live products. Persistence, backup, observability, and recovery are not invisible engineering concerns when a group depends on shared state. They are part of the interaction design.

It also changed how I worked with AI. A passing interface and a confident implementation summary were not sufficient. I needed tests that exercised state over time, explicit recovery behavior, and verification in the environment where the product would run.

After the event, I strengthened the engineering foundation through modular frontend and backend code, automated integration and browser tests, clearer deployment configuration, and SQLite persistence. These later improvements should not be mistaken for capabilities of the original live MVP. They represent what I learned from operating it.

Shipping the product was not the same as introducing it

I intentionally kept my personal credit subtle because I wanted ShareQ to feel like a community tool. After the event, a member told me that many participants probably did not realize I had created it.

At first, that felt like a recognition problem. In retrospect, it was also a product communication problem. If people did not know who made the tool or why it existed, they were less likely to understand its connection to the first event, know where to send feedback, or recognize that its behavior could be changed for them.

I would keep the ShareQ identity, but launch it differently: a brief explanation of the problem it addresses, a short walkthrough of the consent and queue model, visible but restrained creator credit, and a clear feedback channel.

What was added after the event

The community event used the original Chinese interface. I later added English localization so the product and its design reasoning could be understood by a broader portfolio audience.

Localization required more than translating the obvious headings. I audited visible text, placeholders, generated notifications, title attributes, empty states, and persisted language state. The first AI-assisted attempt left untranslated strings; the second pass treated language as a system concern and verified the interface in both modes.

This distinction matters: the English version demonstrates continued ownership and engineering iteration, but it was not evidence from the original event.

Outcome and reflection

ShareQ did not prove that every karaoke participant needs a standalone queue. It demonstrated something more specific:

  • Active singers and hosts benefited from a shared coordination layer.
  • Consent changed a playful but potentially uncomfortable behavior into a respectful interaction.
  • Performance history created value beyond the immediate queue.
  • Passive listeners needed little reason to leave the community chat.
  • A reliability failure could erase adoption faster than a feature could create it.

The project shows how I work across product design and engineering. I noticed an opportunity inside an ordinary community experience, translated social behavior into interaction rules, used AI to reach a working product quickly, and stayed accountable for whether the implementation actually worked.

The speed mattered because the event would not wait. The judgment mattered because speed alone produced fragile results.

ShareQ remains available at shareq.chell.ca. Before another live event, I would run a longer state-persistence test, give co-hosts an explicit recovery path, create an automatic backup, and measure where participants still leave ShareQ to coordinate in chat. I would also test whether lightweight activity notifications could give listeners a reason to engage without requiring them to keep another full interface open.