Explore
How we shipped Excellance in under 4 weeks

How we shipped Excellance in under 4 weeks

A sales training platform built with Vue 3, Nuxt, and Firebase — from a rough brief to a working product. What we built, how we approached it, and what we learned.

Excellance is a sales training platform for enterprise teams. The founder, Jay Sriskhantan, came to us with a clear vision and a tight timeline — he needed a working product he could demo to enterprise clients before the end of the quarter.

This is the story of how we went from a rough brief to a functional platform in under four weeks.


The brief

Jay had a strong concept: an interactive learning platform where sales teams could complete structured training modules, track their progress, and managers could see team-wide reporting. He had wireframes, a design direction, and Firebase already set up for his backend.

What he didn't have: a frontend team. His backend developer was solid but had never touched Vue. He needed someone who could take his vision and build the product interface without hand-holding.

The initial brief was:

  • Learner dashboard with module progress tracking
  • Module content viewer (video + text + quizzes)
  • Manager reporting view (team progress, completion rates)
  • Authentication (email/password)
  • Mobile responsive

Week 1: Setup and core structure

The first task was onboarding — understanding the Firebase data model, the existing backend logic, and agreeing on naming conventions.

Jay had structured Firestore reasonably well but with some patterns that would have caused problems at scale. We flagged two data model issues before writing a line of frontend code:

  1. The module completion state was being stored at the top level rather than in a subcollection, which would make querying painful as content grew
  2. The quiz responses had no timestamp, which would make the reporting feature harder to build later

Jay fixed both on his side before we started building. That decision saved us a rewrite later.

The first week covered:

  • Nuxt 3 project setup with TypeScript and Tailwind
  • Firebase composables (auth state, Firestore reads/writes)
  • Route structure and navigation
  • Base component library (buttons, cards, badges, layout)

Week 2: The learner experience

The learner dashboard and module viewer were the core of the product. We built these in parallel — the dashboard for progress overview, the module viewer for the actual training content.

The module viewer needed to handle three content types: video (hosted on Vimeo), rich text, and interactive quizzes. We built a content renderer that handled all three via a contentType field in the module document.

The quiz component was the most complex piece. It needed to:

  • Render different question types (multiple choice, ranking, free text)
  • Validate answers and show explanations
  • Save responses to Firestore in real-time
  • Block module completion until all required questions were answered

This was done in a single week. The key was having a clean composable structure from day one — useModuleProgress, useQuizState, useUserEnrollment — so the UI components stayed thin and testable.


Week 3: Manager reporting

The reporting view was harder than expected. Not because of the UI — that was straightforward — but because the aggregation queries needed to be efficient enough to load in under two seconds for a team of 30+ learners.

Firebase has no server-side aggregation for Firestore reads, which means you either fetch all the data client-side and aggregate there (slow, expensive) or you maintain denormalised aggregates in Firestore updated by Cloud Functions.

We recommended the second approach and implemented a simple Cloud Functions trigger that updated team completion stats whenever a learner completed a module. This added a day to the timeline but made the reporting view instant.

The reporting dashboard showed:

  • Team completion rate per module
  • Individual learner progress
  • Time-to-completion averages
  • Overdue completions

Week 4: Polish, auth flows, and mobile

The final week was about making the product feel finished. Authentication edge cases (password reset, email verification), mobile layout refinements, loading states, empty states, and error handling.

Jay did a full QA pass and sent back 11 revision requests. None were "wrong" — they were refinements. Sharper typography, better spacing on mobile, a more confident empty state for the reporting view when no data existed yet.

All 11 were done within two days.


What Jay said

"This saved me weeks of development time. Incredible value!"

The thing Jay highlighted most in follow-up conversations wasn't speed — it was predictability. He always knew what was being worked on, what was coming next, and nothing was blocked waiting for decisions from him unless he specifically needed to make one.


What made this work

Looking back, three things made this project go well:

1. A clean brief. Jay knew what he wanted. The wireframes weren't perfect but they were specific enough that we could start building without a lengthy discovery phase.

2. A working backend. Firebase was already set up. We didn't have to architect the data layer — we worked within it (and improved two things before we started).

3. Trusting async. Jay didn't want daily calls. He added context to tasks on the board, reviewed work when it was ready, and gave feedback via comments. No synchronisation overhead.

If you're building a product and need a frontend team that can move like this, get in touch.