DEV Community

Cover image for I Finally Finished Schedio: Turning a 5-Day Hackathon MVP Into a Live Product
Arqam Waheed
Arqam Waheed Subscriber

Posted on

I Finally Finished Schedio: Turning a 5-Day Hackathon MVP Into a Live Product

GitHub “Finish-Up-A-Thon” Challenge Submission

This is a submission for the GitHub Finish-Up-A-Thon Challenge.

A few weeks ago, I built Schedio as a 5-day hackathon project, which was also, unironically, another GitHub challenge.

The idea was simple:

Highlight any text that mentions an event, and turn it into a Google Calendar event in under 5 seconds.

It worked.

Kind of.

The first version could parse highlighted text, open a clean event modal, and write to Google Calendar. I even wrote about that original MVP here:

Schedio: Highlight to Calendar in 5 Seconds

But after the hackathon rush ended, Schedio was still very obviously an MVP.

The demo was cool, but the product was not finished.

The Gemini key was too close to the client. OAuth verification was not done. Billing did not exist. Pro was just an idea. Onboarding was basically “install this and figure it out.”

There was not even a real landing page yet. My original plan was to build one after the Chrome Web Store approval, properly market the extension, get some users, add more features, and slowly turn it into an actual product instead of just a hackathon project sitting in a repo.

The funny part is that the Chrome Web Store launch failed once because I accidentally uploaded the wrong build. I fixed it, submitted it again, and then it got rejected a second time lol.

After that point, uni exams had started, other hackathons came up, and Schedio slowly drifted into that “I’ll finish it later” state. I never really pushed it beyond the original hackathon MVP.

It worked for me, but it was never really out there for everyone else to use.

So for the Finish-Up-A-Thon, I came back to Schedio and tried to do the part of building that usually gets ignored after the fun demo is over — which is TO ACTUALLY FINISH it and put it out there for others.


What I Built

Schedio is an AI-powered Chrome extension that turns natural language into real Google Calendar events.

You can highlight something like:

Team standup Friday 3pm, Room 204

Then right-click and choose Create Event with Schedio, or use the keyboard shortcut. Schedio parses the title, date, time, and location, shows you a quick review modal, and creates the event in Google Calendar when you confirm.

  • No copy-pasting.
  • No switching tabs.
  • No manually typing date fields while trying to remember what the original message said.

The finished version is now a real product, not just a hackathon repo. It has a live Chrome Web Store listing, a landing page at schedio.org, Google OAuth verification approved, Lemon Squeezy approved for payments, a Cloudflare Worker backend, server-side Gemini calls, Supabase-backed users and subscriptions, Free/Pro metering, an in-extension upgrade flow, voice-to-calendar as a Pro feature, first-run onboarding, privacy policy, Terms of Service, rate limiting, input validation, and no baked Gemini key in the client bundle.

The MVP proved the magic.

The finished version makes the magic safe, usable, and shippable.


Demo

Live site: https://schedio.org

Chrome Web Store: https://chromewebstore.google.com/detail/schedio/nlnkjghkddopgocdbhhkefmjbchlpjnc

Original hackathon version repo: https://github.com/ArqamWaheed/schedio

The original hackathon MVP repo is still public, but the current production version is now private because it contains live infrastructure, billing flows, and production authentication logic.

The core flow is still the same as the original MVP: highlight text, trigger Schedio, review the parsed event, and send it to Google Calendar.

But everything around that flow evolved. What started as a hackathon extension slowly turned into a real product and brand, with a proper landing page, onboarding, Pro features, subscriptions, backend infrastructure, and a much more polished overall experience.


The Comeback Story

The original Schedio was built under pressure. I cared about one question: could I make calendar creation feel instant?

That question led to the first version. But when I came back to the project, the question changed. It was no longer just “can this work?” It became:

“What would I need to change before I could confidently give this to strangers and turn it into a real brand?”

That shift basically defined the entire comeback.

The first real finishing moment was getting Schedio live on the Chrome Web Store. The earlier review had failed because I uploaded the wrong non-working build, which is such a small but painful launch mistake. The code can work locally, the demo can be impressive, the idea can be good, and then one bad upload means nobody can actually install it. So I rebuilt, rechecked, uploaded the correct version, and got it listed.

That made the project feel different immediately.

Before, Schedio was something I could show.

Now it was something people could install.

The next big problem was architecture. The MVP had the classic hackathon shortcut: the Gemini API key was too close to the client. With a browser extension, that is not something you can just hand-wave forever. If a key is in the shipped bundle, it is not really secret.

So I moved the AI parsing behind a Cloudflare Worker backend using Hono. The extension now sends highlighted text and the user’s Google token to api.schedio.org/parse. The backend verifies identity, calls Gemini server-side, and returns the parsed event. The Gemini key lives as a Worker secret, not inside the extension.

That was the first moment where Schedio stopped feeling like a clever browser hack and started feeling like infrastructure. The product still felt simple from the outside, but the trust boundary had completely changed.

Once the backend existed, I could finally turn Schedio into a Free/Pro product. Free users get a monthly event cap. Pro users get unlimited events and access to the voice feature. The important part is that the limit is enforced server-side before Gemini is called, so over-limit users do not cost an API request.

I also made the quota harder to game. The monthly bucket comes from the server’s UTC clock, not the client’s local date, and usage increments through an atomic Postgres function so concurrent highlights do not lose updates.

That is not the flashiest part of the project, but it is exactly the kind of thing that separates a demo from a product. A demo only needs to work once. A product has to keep working when users do weird things.

Billing was another place where finishing meant doing the boring thing correctly. I used Lemon Squeezy as the Merchant of Record, so Schedio does not touch card numbers, VAT, tax, or PCI directly. The backend has endpoints for checking the current plan, creating a personalized checkout link, and handling subscription webhooks.

The checkout flow embeds the verified Schedio user ID into Lemon Squeezy custom data. That way, when the webhook comes back, the subscription can be attached to the exact right Google account.

I almost made the obvious mistake of putting a raw “Buy Pro” link on the website. But the website does not know who the user is. Identity lives inside the extension. A raw checkout link from the marketing page could create an orphaned payment that the backend cannot map to anyone.

So the website sells the product, but the actual upgrade flow starts inside the extension, where the user is already authenticated.

The biggest new feature I added was voice-to-calendar. Instead of highlighting text, Pro users can speak an event into the popup. The backend sends the raw audio to Gemini 2.5 Flash multimodal, and Gemini transcribes and extracts the event in one call. No separate speech-to-text step. No transcript first, parse second.

Just speech into calendar structure.

I made voice a real Pro anchor, not a fake paywall. I could have used the free Web Speech API, but the multimodal approach was more accurate and has real marginal cost. So the server enforces the Pro gate before audio reaches Gemini. Free users get a 403 PRO_REQUIRED before the expensive work happens.

That felt like a real product decision: the feature is better, it costs something, and the paywall protects the cost center before the bill is created.

The next problem was onboarding. The MVP dropped users into the product and expected them to discover the context menu or shortcut. That is fine when the builder is the user, but for others, it is terrible for a new install.

So I built a first-run onboarding tab that opens on install. It shows the core habit: highlight text, right-click, review the event, connect Google Calendar. I wanted the tour to appear once without adding a new storage permission, so I used Chrome’s runtime.onInstalled event with reason === "install". That fires once per install, so there is no extra permission and no extra state to manage.

I also moved sign-in earlier, but carefully. The onboarding ends with a clear Connect Google Calendar button, not an automatic OAuth popup. There is also a skip option. The connect ask only appears after the user has seen the value.

Good onboarding is not a wall of text. It is a rehearsal of the product’s best moment.

The landing page also became part of the finishing arc. I shifted it away from technical explanations and focused more on outcomes instead, because that is what actually gets people interested in a product.

I also had to make the marketing honest. Some features are planned but not built yet, like extra calendar providers and bulk event creation. I did not want to delete the ambition, but I also did not want to lie. So unfinished features got “soon” labels, and shipped features were removed from the future roadmap.

That sounds tiny, but it matters. A product page should not make claims the product cannot survive.

The final wall was trust.

Google OAuth verification got approved. Lemon Squeezy approved the store. Those two approvals were the moment Schedio stopped being “works on my machine” and became something distributable and monetizable.

A calendar-writing extension has to earn trust. Google needed the owned domain, hosted privacy policy, write-only scope explanation, demo video, and correct compliance language. Payments needed a real Merchant of Record review. None of that is as fun as building a new AI feature, but that was the actual finish line.

The original version died near this wall. The newer version finally crossed it.


How GitHub Copilot Helped Me

I used GitHub Copilot CLI to generate a large part of the implementation, but I never treated it like autopilot.

The architecture, product decisions, system boundaries, and overall direction were still mine. Copilot was the accelerator, not the driver. I spent most of the project defining flows, structuring prompts carefully, reviewing generated code, and deciding what should or should not exist in the final product.

That mattered more as Schedio evolved from a hackathon MVP into a real product.

The backend migration is a good example. I knew the Gemini key could not stay in the client anymore, but Copilot helped turn that idea into the actual Worker architecture: extension → Cloudflare Worker → Gemini/Supabase/Lemon Squeezy. It helped scaffold routes, tighten request shapes, and keep the extension and backend synced while the architecture evolved.

It also helped with the parts that are easy to ignore when you are moving quickly: webhook verification, quota tracking, atomic usage increments, CORS restrictions, rate limits, generic error handling, and validation layers. None of those make a flashy demo. All of them make the product safer.

Copilot was also surprisingly useful for debugging weird launch issues. The best example was the OAuth bad client id bug. After moving authentication into the real product flow, Google sign-in suddenly broke in development builds. The issue turned out to be Chrome extension IDs: unpacked builds can generate different IDs unless the public extension key is pinned correctly.

Copilot helped trace the extension ID behavior, compare it against the published Web Store ID, and wire the correct key into the manifest so development and production resolved identically. What started as a vague OAuth failure became a clean one-line fix.

It also helped with product consistency outside pure code. While redesigning the Chrome Web Store graphics, Copilot helped identify outdated messaging that still implied users needed their own AI key. But the final product had already removed BYOK entirely. Leaving those images up would have been misleading, so they got rebuilt before launch.

That was the part I did not expect initially. Copilot was not just generating code. It was helping keep the product coherent while the scope kept expanding.

The Terms of Service and SEO work were similar. Copilot helped structure the TOS around the existing privacy policy style, wire the new pages into the build system, and connect everything through the footer and metadata layer. It also helped add Open Graph tags, Twitter cards, sitemaps, robots files, structured data, and asset handling.

The biggest lesson was that Copilot never replaced the decisions. It simply made implementation dramatically faster once the direction was clear.

And most of the important decisions were actually restraint:

  • Do not put a raw checkout link on the website because identity lives in the extension.
  • Do not claim planned features are already shipped.
  • Do not add unnecessary permissions just because they are convenient.
  • Do not process webhooks loosely when strict validation is safer.
  • Do not leak backend internals in API errors.
  • Do not keep a Gemini key in the client just because it is easier.

The MVP was built with speed.

The finished product was built with speed plus restraint.

Once the architecture and product decisions were clear, Copilot accelerated the implementation massively. I still handled the direction, debugging, and review process, but it removed an enormous amount of friction from actually extending and shipping Schedio.

A lot of the final product simply would have taken far longer to build without it.


What I Learned

A hackathon project is about proving the magic.

A finished product is about protecting it.

Schedio already had the magic: highlight text and turn it into a calendar event in seconds. But the comeback was everything around that.

  • Can users install it?
  • Can Google trust it?
  • Can payments map to the right account?
  • Can a free user hit a limit without the UX feeling broken?
  • Can secrets stay secret?
  • Can onboarding teach the habit?
  • Can the website sell without lying?
  • Can the system survive the boring edge cases?

That is what I finished.

And weirdly, that made the project more exciting than the original hackathon version, because now Schedio is not just a demo I can show. It is a product I can actually launch.

The next steps are smarter recurrence, multiple calendars, Outlook/iCloud/CalDAV support, bulk multi-event parsing, Firefox and Edge support, and eventually a Mac/Safari companion app. But the important part is that Schedio is no longer blocked by the boring stuff.

The boring stuff is done.

And that was the real Finish-Up-A-Thon.


What's Next Beyond Development

Now comes the next challenge: distribution

Schedio is finally live, installable, verified, and usable by real people. The engineering side finally feels complete enough to push properly, so my next focus is figuring out how to market it, get feedback from real users, and turn it from a finished side project into something people genuinely rely on.

If anyone has ideas for growth, launch, or distribution strategies for productivity extensions, I would genuinely love to hear them.

Top comments (0)