<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sanket Golekar</title>
    <description>The latest articles on DEV Community by Sanket Golekar (@sanket_golekar_ecc1958b41).</description>
    <link>https://dev.to/sanket_golekar_ecc1958b41</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3839376%2F0900e0cd-128c-4151-a763-99210374d767.jpg</url>
      <title>DEV Community: Sanket Golekar</title>
      <link>https://dev.to/sanket_golekar_ecc1958b41</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sanket_golekar_ecc1958b41"/>
    <language>en</language>
    <item>
      <title>How I built a work-friendly cafe finder PWA for my city (MERN, zero budget, solo dev)</title>
      <dc:creator>Sanket Golekar</dc:creator>
      <pubDate>Mon, 23 Mar 2026 07:00:27 +0000</pubDate>
      <link>https://dev.to/sanket_golekar_ecc1958b41/how-i-built-a-work-friendly-cafe-finder-pwa-for-my-city-mern-zero-budget-solo-dev-25b8</link>
      <guid>https://dev.to/sanket_golekar_ecc1958b41/how-i-built-a-work-friendly-cafe-finder-pwa-for-my-city-mern-zero-budget-solo-dev-25b8</guid>
      <description>&lt;p&gt;For the past few months, I've been working from different cafes across Chandigarh every weekday and I'm surprised to see that a lot of people in the city prefer working from cafes.&lt;/p&gt;

&lt;p&gt;But there's one problem I noticed, majority of people work from only 2 popular cafes in the city because they don't know about other work friendly cafes, which results in these cafes being crowded most of the times. Many cafes which students and people working remotely&lt;br&gt;
visit have no proper WiFi or worse, they don't welcome you working from their cafes.&lt;/p&gt;

&lt;p&gt;So I spent the last 3 months fixing this.&lt;/p&gt;

&lt;p&gt;I started building an app which shows all the work friendly cafes in Chandigarh with personally tested WiFi speeds, number of power outlets for charging, sat there working long enough to honestly judge the noise levels. Everything is verified personally by me and updated regularly.&lt;/p&gt;

&lt;p&gt;The result is &lt;a href="https://basebrew.in" rel="noopener noreferrer"&gt;BaseBrew&lt;/a&gt;, a free work friendly cafe discovery platform PWA built specifically for Chandigarh &lt;br&gt;
tricity. Here's what I built, how I built it, and &lt;br&gt;
the gotchas I ran into along the way.&lt;/p&gt;

&lt;p&gt;Just open &lt;a href="https://basebrew.in" rel="noopener noreferrer"&gt;BaseBrew&lt;/a&gt; on your phone.&lt;/p&gt;

&lt;p&gt;Search filters you can use to find the cafe of &lt;br&gt;
your choice:&lt;/p&gt;

&lt;p&gt;→ WiFi Speed (actual Mbps, personally tested by me)&lt;br&gt;
→ Power Outlets availability + outlet count&lt;br&gt;
→ Noise levels (quiet / moderate / lively)&lt;br&gt;
→ Opening and closing hours&lt;br&gt;
→ Sector filters (Sector 8, 35, 22, 7, Elante etc)&lt;br&gt;
→ Price range (budget / mid / premium)&lt;br&gt;
→ Near Me filter (shows cafes closest to &lt;br&gt;
  your location)&lt;br&gt;
→ I'm Working Here — check in when you're at &lt;br&gt;
  a cafe, shows how many people are working &lt;br&gt;
  there right now&lt;/p&gt;

&lt;p&gt;24 verified cafes in Chandigarh are live right &lt;br&gt;
now. Adding more every week if the cafes match &lt;br&gt;
our work friendly criteria.&lt;/p&gt;

&lt;p&gt;The app is 100% free, no ads, no paywall.&lt;/p&gt;

&lt;p&gt;Now let me get into how I actually built this: &lt;br&gt;
the stack decisions, the architecture, and the bugs that cost me the most time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why MERN?&lt;/strong&gt;&lt;br&gt;
I'm a solo developer, having one language across the entire stack is a huge productivity advantage. MongoDB's flexible schema worked well for cafe data since every cafe has different attributes. Atlas M0 free tier handles the current scale comfortably.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why PWA over a native app?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The honest reason: I didn't want to pay ₹10,000 for app store fees before validating the idea.&lt;/p&gt;

&lt;p&gt;But the more I built it the more it made sense. No app store review delays. Instant updates the moment I push to main. Works offline. Installs to home screen. For India's Android dominant &lt;br&gt;
market, PWA install rates are surprisingly strong.&lt;/p&gt;

&lt;p&gt;I used vite plugin pwa with Workbox's injectManifest strategy instead of the simpler generateSW strategy. It's more work to set up but gives you full control over the service worker, which I needed for custom push notification handling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Vercel + Render?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Total monthly infrastructure cost: ₹0.&lt;/p&gt;

&lt;p&gt;Vercel handles the frontend — auto-deploys on every push to main, global CDN, zero config. Render hosts the Express backend on their free tier.&lt;/p&gt;

&lt;p&gt;The catch with Render free tier is cold starts. First request after inactivity takes around 50 seconds. My fix: UptimeRobot pings the /health endpoint every 5 minutes. Free, takes 2 minutes to set up, completely solves the problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why not Next.js?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I considered it for SSR and SEO benefits. Decided against it because I already knew Vite + React well and solo maintainability mattered more than marginal SSR gains at MVP stage.&lt;/p&gt;

&lt;p&gt;I solved the SEO problem a different way, react-helmet-async for unique title and meta description on every route, a dynamic sitemap &lt;br&gt;
served directly from Express hitting MongoDB so it's always current, and JSON-LD schema markup on every cafe page. Ended up with &lt;br&gt;
Lighthouse SEO score of 100 in production.&lt;/p&gt;

&lt;p&gt;These are the bugs that cost me the most time. Sharing them so you don't lose the same hours.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mongoose mapped 'Cafe' to 'caves'&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Mongoose has an irregular pluralisation rule. My 'Cafe' model was being mapped to a MongoDB collection called 'caves' — not 'cafes'. &lt;br&gt;
Everything appeared to work fine but data was being written to and read from the wrong collection entirely.&lt;/p&gt;

&lt;p&gt;Lost a lot of time to this one before I figured out what was happening.&lt;/p&gt;

&lt;p&gt;Fix: explicitly set the collection name in schema options:&lt;/p&gt;

&lt;p&gt;const CafeSchema = new mongoose.Schema({...}, &lt;br&gt;
  { collection: 'cafes' })&lt;/p&gt;

&lt;p&gt;Worth watching for with any model name that has an irregular plural form.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VAPID key mismatch silently broke all push notifications&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Push notifications worked perfectly in development. In production — nothing. No errors, no logs, just complete silence.&lt;/p&gt;

&lt;p&gt;Root cause: I had generated different VAPID key pairs on Vercel and Render. The browser stores the public key at subscription time. When the server uses a different private key to sign the push, the push service rejects it silently, no error thrown, nothing in the logs.&lt;/p&gt;

&lt;p&gt;Fix: generated one matched VAPID pair, set both public and private keys as environment variables on both platforms. Then wipe all existing push subscriptions from MongoDB and make users resubscribe. The mismatch is a silent killer, if push ever stops working with no obvious reason, check this first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;iOS Web Push is not what it looks like&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;iOS 16.4+ technically supports Web Push. In practice it's a different story.&lt;/p&gt;

&lt;p&gt;The PWA must be installed to the home screen before push works at all. The user must grant permission after install, not before. Safari &lt;br&gt;
handles the permission flow completely differently from Chrome. And even after all that, reliability is inconsistent.&lt;/p&gt;

&lt;p&gt;I spent a week trying to get iOS push working properly before accepting it as a known limitation. For India's market this turned out to not matter, Android is the dominant platform and Android push works perfectly. Don't let iOS Web Push block your launch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;React SPA is invisible to Google on day one&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A standard React SPA serves a nearly empty HTML file and injects content via JavaScript. Googlebot can render JavaScript but does it &lt;br&gt;
slowly and inconsistently. On launch day the cafe pages were essentially invisible to Google.&lt;/p&gt;

&lt;p&gt;The fix stack I used:&lt;/p&gt;

&lt;p&gt;→ react-helmet-async, unique title and meta &lt;br&gt;
  description on every route. Single highest &lt;br&gt;
  impact SEO change you can make on a React app.&lt;/p&gt;

&lt;p&gt;→ Dynamic sitemap from Express, a route that &lt;br&gt;
  queries MongoDB and generates sitemap.xml &lt;br&gt;
  on request. Always current, never stale, &lt;br&gt;
  updates automatically when you add new cafes.&lt;/p&gt;

&lt;p&gt;→ JSON-LD schema markup, CafeOrCoffeeShop &lt;br&gt;
  schema on every cafe page with rating, &lt;br&gt;
  opening hours, and address. Eligible for &lt;br&gt;
  rich results in Google Search.&lt;/p&gt;

&lt;p&gt;→ vercel.json rewrites, ensures all routes &lt;br&gt;
  return index.html so direct navigation &lt;br&gt;
  doesn't 404.&lt;/p&gt;

&lt;p&gt;Result: Lighthouse SEO score of 100 in production. First organic impressions appearing in Google Search Console within 2 weeks of &lt;br&gt;
launch.&lt;/p&gt;

&lt;p&gt;Here's the full stack if you want the quick overview:&lt;/p&gt;

&lt;p&gt;Frontend: Vite + React 18 + Tailwind CSS + vite-plugin-pwa + deployed on Vercel.&lt;br&gt;
Backend: Node.js + Express 4 + Mongoose 8,deployed on Render free tier.&lt;br&gt;
Database: MongoDB Atlas M0 (free tier).&lt;br&gt;
Media: Cloudinary with f_auto + q_auto for automatic WebP optimisation.&lt;br&gt;
Auth: JWT + bcryptjs + Google OAuth via Passport.&lt;br&gt;
Push: web-push npm package with VAPID keys, zero third party cost.&lt;br&gt;
Total monthly cost: ₹0.&lt;/p&gt;

&lt;p&gt;I posted about BaseBrew on r/Chandigarh last week, first ever Reddit post, 24 day old account with 1 karma when I woke up that morning.&lt;/p&gt;

&lt;p&gt;24 hour results:&lt;br&gt;
→ 13,000 views&lt;br&gt;
→ 92 upvotes, 96% upvote ratio&lt;br&gt;
→ #1 post on r/Chandigarh&lt;br&gt;
→ 53 organic private shares&lt;br&gt;
→ 70 comments&lt;/p&gt;

&lt;p&gt;The 53 private shares surprised me most, that means 53 people saw BaseBrew and immediately thought of a specific person to send it to. &lt;br&gt;
That's the word of mouth signal I was building toward.&lt;/p&gt;

&lt;p&gt;Current: 12 signups, 57 PWA installs.&lt;/p&gt;

&lt;p&gt;Next up:&lt;/p&gt;

&lt;p&gt;→ Cowork Sessions — post intentional work &lt;br&gt;
  sessions at a cafe, other users request to &lt;br&gt;
  join, host approves. The trust model is the &lt;br&gt;
  most interesting engineering problem I've &lt;br&gt;
  designed so far.&lt;br&gt;
→ Play Store + App Store via PWABuilder TWA&lt;br&gt;
→ Delhi NCR expansion once Chandigarh hits &lt;br&gt;
  500+ MAU&lt;/p&gt;

&lt;p&gt;Building this entirely in public. If you're working on a hyperlocal product, have questions about the PWA setup, VAPID push implementation, GeoJSON Near Me search, or the React SPA SEO &lt;br&gt;
approach, drop them in the comments. Happy to answer everything.&lt;/p&gt;

&lt;p&gt;visit &lt;a href="https://basebrew.in" rel="noopener noreferrer"&gt;BaseBrew&lt;/a&gt; if you're &lt;br&gt;
ever in Chandigarh.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>node</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
