DEV Community

Daniel for Datalaria

Posted on Originally published at datalaria.com

Project LifeOps (Part 5): 24/7 Zero-Cost Cloud Deployment ($0/month), Mobile Optimization, and PWA

We have arrived at the grand finale of our engineering series. Across the four previous installments, we designed the database architecture and FastAPI backend, crafted the Glassmorphism Dark Mode React interface, built the interactive fitness, reading, cinema, and Kanban modules, and developed the in-memory Word and Excel reporting engine.

Yet in software development, a sobering pattern exists: countless extraordinary personal projects wither and die on localhost:3000 or localhost:8000.

The obstacle is almost always the same: production cloud deployment is often perceived as a labyrinth of daunting server configurations, mounting database subscription fees, or the burden of maintaining live virtual machines. And when aiming to bring web apps to smartphones, developers frequently encounter costly gatekeepers: Apple Developer fees ($99/year), Google Play fees, opaque store review cycles, and massive hybrid frameworks.

In this final installment, we demonstrate a far more elegant, sustainable path:

  1. Deploying the entire full-stack architecture 24/7 at exactly $0.00/month.
  2. Seamlessly handling free cloud container sleep cycles (cold-starts) on the client side.
  3. Engineering an ultra-ergonomic touch experience optimized for modern smartphones (Android / Samsung Galaxy and iPhone).
  4. Transforming the application into an installable Progressive Web App (PWA) added directly to home screens.

[!TIP]
Test the live app: You can explore the final production release of LifeOps at https://datalaria.com/apps/lifeops/.


πŸ—ΊοΈ Complete LifeOps Series Roadmap

With this post, the full 5-part blueprint is complete:

  1. 🟒 Part 1: Personal Operating System Architecture and FastAPI + Supabase Backend
  2. 🟒 Part 2: React Frontend with Glassmorphism, 360° Dashboard, and Design System
  3. 🟒 Part 3: Core Interactive Modules: Fitness, Library, Cinema, and Professional Kanban Board
  4. 🟒 Part 4: Executive Word (.docx) Reporting Engine and Multi-Sheet Excel (.xlsx) Export
  5. 🟒 Part 5 (This article): 24/7 Zero-Cost Cloud Deployment ($0/month), Mobile UX, and PWA

1. Production Cloud Topology ($0/month) 🌐☁️

To guarantee that LifeOps remains online 24/7 without recurring cloud invoices, we strategically leverage the most generous free tiers available:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                       CLIENT DEVICE                         β”‚
β”‚           Web Browser / Installed Home Screen PWA           β”‚
β”‚            https://datalaria.com/apps/lifeops/              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               β”‚
                               β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚               FRONTEND: Netlify Edge CDN ($0/month)         β”‚
β”‚   β€’ Vite build with Rollup Code Splitting (vendor-*)        β”‚
β”‚   β€’ Instant global edge delivery via Gzip / Brotli          β”‚
β”‚   β€’ Transparent proxy rewrite under Datalaria domain        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               β”‚
            JWT Bearer Tokens  β”‚  HTTPS REST Calls
                               β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚               BACKEND: Render.com Web Service ($0/month)    β”‚
β”‚   β€’ FastAPI + Uvicorn container (Python 3.11 / 3.13)        β”‚
β”‚   β€’ Endpoint: https://lifeops-api.onrender.com              β”‚
β”‚   β€’ Anti-DoS Rate Limiting (slowapi) + Strict CORS          β”‚
β”‚   β€’ Auto-spins down after 15 minutes of inactivity          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               β”‚
                               β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              DATABASE: Supabase Cloud ($0/month)            β”‚
β”‚   β€’ Managed PostgreSQL 15+ database instance                β”‚
β”‚   β€’ Isolated `lifeops` schema with Row Level Security (RLS) β”‚
β”‚   β€’ Cryptographic JWT session validation                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Enter fullscreen mode Exit fullscreen mode

1.1. Vite Bundle Optimization (vite.config.js)

To guarantee sub-second initial loads across 4G and 5G mobile networks, we configured Rollup manual chunking:

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  base: './', // Enables serving the SPA from any nested route (/apps/lifeops/)
  build: {
    rollupOptions: {
      output: {
        manualChunks(id) {
          if (id.includes('node_modules')) {
            if (id.includes('react') || id.includes('react-dom') || id.includes('react-router-dom')) {
              return 'vendor-react';
            }
            if (id.includes('lucide-react')) {
              return 'vendor-icons';
            }
            if (id.includes('@supabase')) {
              return 'vendor-supabase';
            }
            return 'vendor-libs';
          }
        },
      },
    },
    chunkSizeWarningLimit: 600,
  },
});
Enter fullscreen mode Exit fullscreen mode

By segmenting vendor-react and @supabase, user browsers permanently cache stable external dependencies. When application features update, visitors download only a lightweight diff of new business logic.


2. Conquering Cold-Starts: Client-Side Resilience πŸ›‘οΈβ±οΈ

The only operational tradeoff on Render's free tier is container hibernation after 15 minutes of zero traffic.

When an end-user opens LifeOps after hours of downtime, the first HTTP request requires 25 to 45 seconds while Render allocates a container and initializes Uvicorn. Without proactive client-side handling, users face gateway timeouts (HTTP 504) or frozen interfaces.

In LifeOps, we turned this limitation into an informative, guided user experience:

// lifeops-app/src/components/Dashboard/SystemHealth.jsx
const checkHealth = async (isAutoRetry = false) => {
  setLoading(true);
  if (!isAutoRetry) setError(null);

  try {
    const data = await api.getHealth();
    setHealth(data);
    setError(null);
  } catch (err) {
    setError(err.message || 'Connecting to API...');

    // Auto-retry loop up to 3 times with 6-second delay while Render awakens
    if (retryCount < 3) {
      setTimeout(() => {
        setRetryCount((prev) => prev + 1);
      }, 6000);
    }
  } finally {
    setLoading(false);
  }
};
Enter fullscreen mode Exit fullscreen mode

What happens behind the scenes?

  1. The initial health check dispatches a wake-up ping to the backend.
  2. The UI renders a friendly, transparent notification: "Render instance waking up (Cold start)... retrying automatically".
  3. The frontend retries in the background every 6 seconds without interrupting client navigation.
  4. As soon as FastAPI responds with HTTP 200, the badge shifts to green ("FastAPI Online β€’ Supabase Connected"), fetching data without requiring a manual page refresh.

Account settings and cloud infrastructure panel connected to Render and Supabase


3. Thumb-Accessible Mobile Ergonomics (Android & iOS) πŸ“±πŸ‘

Over 70% of daily interactions with a personal operating system occur on smartphones: logging a workout right after a run, cataloging a book during a commute, or reviewing Kanban deliverables from the couch.

On a 6.5-inch device held in one hand, forcing the user's thumb to reach all the way to the top-left corner for a hamburger menu is poor ergonomic design.

We anchored the mobile user experience on three ergonomic pillars:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ πŸ“± SMARTPHONE VIEWPORT (<= 768px)                           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  [Top Header]: LifeOps Logo      [Locale ES/EN] [User Icon] β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚ πŸͺŸ FLOATING MODAL (React Portal)                      β”‚  β”‚
β”‚  β”‚ ───────────────────────────────────────────────────── β”‚  β”‚
β”‚  β”‚ [=== Drag Handle: slide down to dismiss ===]          β”‚  β”‚
β”‚  β”‚                                                       β”‚  β”‚
β”‚  β”‚  Title: Log Workout Session                           β”‚  β”‚
β”‚  β”‚  β€’ 16px font inputs (prevents iOS Safari auto-zoom)   β”‚  β”‚
β”‚  β”‚  β€’ Smooth touch scroll (touch-action: pan-y)          β”‚  β”‚
β”‚  β”‚                                                       β”‚  β”‚
β”‚  β”‚ ───────────────────────────────────────────────────── β”‚  β”‚
β”‚  β”‚ [πŸ“Œ STICKY FOOTER ACTIONS: [ Cancel ] [ Save Record ]]β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                                             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ πŸ“Œ FIXED BOTTOM NAVIGATION BAR (Height: 64px)               β”‚
β”‚ [ πŸ“Š Dashboard ] [ πŸƒ Personal ] [ πŸ’Ό Tasks ] [ βš™οΈ Settings ]β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Enter fullscreen mode Exit fullscreen mode

3.1. Fixed Bottom Navigation Bar (BottomNav.jsx)

Stationed permanently along the screen footer (position: fixed; bottom: 0; z-index: 1000;), it houses 5 prominent touch targets (48x48px touch bounding boxes following Apple and Google accessibility standards), allowing instantaneous section transitions with a thumb tap.

Smartphone mobile viewport featuring the thumb-accessible fixed bottom navigation bar

3.2. Off-Canvas Sliding Drawer

The primary navigation sidebar (Sidebar.jsx) switches behavior based on screen real estate:

  • On Desktop (> 768px): Expands to 260px or collapses to a slim 72px icon bar with floating tooltips, persisted in localStorage.
  • On Mobile (<= 768px): Becomes an Off-Canvas drawer sliding in over a frosted backdrop (backdrop-filter: blur(8px)), auto-dismissing on link navigation.

Off-canvas mobile sliding drawer over frosted glass backdrop with quick links and system status

3.3. Viewport-Anchored Modals with React.createPortal (Modal.jsx)

Form modals in mobile CSS are notorious for layout bugs: getting clipped by ancestor containers, misaligning behind virtual keyboards, or burying save buttons beneath the fold.

In LifeOps, we engineered a clean architectural solution:

// Rendered directly into document.body via React Portal
export function Modal({ isOpen, onClose, title, children }) {
  ...
  if (!isOpen) return null;

  return createPortal(
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal-content" onClick={(e) => e.stopPropagation()}>
        {/* Touch drag handle for swipe-to-close */}
        <div className="modal-drag-handle-area" onTouchStart={handleTouchStart} onTouchMove={handleTouchMove} onTouchEnd={handleTouchEnd}>
          <div className="modal-drag-pill" />
        </div>
        <div className="modal-header">...</div>
        <div className="modal-body">{children}</div>
      </div>
    </div>,
    document.body
  );
}
Enter fullscreen mode Exit fullscreen mode
/* Precise Mobile Viewport Anchoring (Modal.css) */
@media (max-width: 768px) {
  .modal-backdrop {
    padding: 12px 10px calc(64px + 12px) 10px; /* Terminates exactly above the bottom nav */
    height: 100dvh; /* Dynamic Viewport Height handles mobile address bars */
  }

  .modal-body {
    touch-action: pan-y !important; /* Smooth touch gesture scrolling */
  }

  .form-group input, .form-group select {
    font-size: 16px !important; /* Prevents unwanted iOS Safari viewport auto-zooming */
  }

  /* Action buttons remain permanently docked in view */
  .form-actions {
    position: sticky !important;
    bottom: 0 !important;
    background: #111827 !important;
    z-index: 30;
  }
}
Enter fullscreen mode Exit fullscreen mode

With createPortal, modals break free from ancestor stacking contexts. And thanks to calc(64px + 12px) and sticky footers, the Cancel and Save buttons remain permanently anchored in thumb view, regardless of form length.

Touch-friendly mobile modal rendered via React Portal with swipe drag handle and sticky footer actions


4. Progressive Web App (PWA) Transformation πŸ“²βœ¨

For an application to feel native on a mobile device, it must install without store middlemen.

We configured modern meta tags and web app standards in index.html:

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
<meta name="theme-color" content="#111827" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<link rel="icon" type="image/svg+xml" href="favicon.svg" />
Enter fullscreen mode Exit fullscreen mode

Key Benefits as an Installed PWA:

  1. Home Screen Presence: High-resolution branded icon sitting alongside native apps on Android and iOS.
  2. Fullscreen Standalone Mode: Browser URL bars and navigation chrome disappear, reclaiming 15% of vertical screen space.
  3. Status Bar Theming: Device battery and clock bars harmonize seamlessly with the #111827 glassmorphic palette via theme-color.
  4. Instant Updates: New builds deploy live over Git without waiting days for third-party store approvals.

5. Retrospective: Lessons Learned from the LifeOps Blueprint πŸŽ“πŸ’‘

Architecting and engineering LifeOps from the ground up has been one of the most rewarding journeys documented on Datalaria.

To conclude our technical journey, here are the three foundational takeaways:

  1. Relational modeling outperforms flat schemas as telemetry matures: Structuring general events in lifeops.activities with 1-to-1 extension tables (workouts, books, films) and employing JSONB for progress timelines delivered superior maintainability over sprawling, null-riddled tables.
  2. Deliberate design fosters consistent user adherence: Investing in visual polish (Glassmorphism, hardware-accelerated blurs, Outfit typography, and consistent Lucide iconography) transforms daily logging into an enjoyable ritual rather than a chore.
  3. Modern serverless tooling enables $0/month production without compromises: The pairing of FastAPI + Supabase + React (Vite) + Render + Netlify provides reliability, speed, and cryptographic security rivaling commercial SaaS platforms charging $15/month per seat.

Series Conclusion & Complete Index πŸš€

With this fifth installment, the official LifeOps series stands complete. You have access to the complete source code, architectural rationales, and production implementation details step by step.

I invite you to try the live application, experiment with its modules, and draw inspiration to build your own bespoke systems guided by Datalaria's core motto: "Learn by building".


Complete Series Reference & Links πŸ”—

Thank you for following along throughout this series! If you are building your own personal operating systems or have ideas for enhancements, share your insights in the comments below. πŸ‘‡

Top comments (0)