WellAlly Logo
WellAlly康心伴
Development

From Wearable to Web: Building a Health Data PWA with Next.js & Chart.js

Learn how to build a responsive, offline-first Progressive Web App (PWA) for your wearable health data. This guide covers fetching API data, local storage with IndexedDB, and creating interactive dashboards with Next.js and Chart.js.

W
2025-12-11
9 min read

In an era of fitness trackers and health-monitoring smartwatches, the ability to visualize and analyze personal health data has become increasingly valuable. This article will guide you through the process of building a Progressive Web App (PWA) to display wearable health data. We'll explore the architecture of a Next.js application that fetches data from a third-party API, caches it locally with IndexedDB, and presents it in an interactive dashboard using Chart.js.

This project will demonstrate how to create a fast, reliable, and installable web application that feels like a native app. By the end, you'll have a solid understanding of how to integrate these technologies to build powerful data-driven applications.

Prerequisites:

  • A solid understanding of React and Next.js.
  • Familiarity with JavaScript (ES6+).
  • Node.js and npm (or yarn) installed on your machine.

Understanding the Problem

While many wearables come with their own apps, you might want to create a custom dashboard that aggregates data from multiple sources or visualizes it in a unique way. The challenge lies in creating a web application that is not only visually appealing but also performant and accessible, even with a spotty internet connection.

A PWA is the perfect solution for this scenario. PWAs are web apps that can be "installed" on your device, work offline, and offer a user experience on par with native applications. By leveraging the power of Next.js for server-side rendering and the flexibility of Chart.js for data visualization, we can build a top-tier health data dashboard.

Prerequisites

Before we begin, make sure you have a Next.js project set up. If not, you can create one with the following command:

code
npx create-next-app@latest wearable-health-pwa
Code collapsed

Next, we'll need to install the necessary packages for our PWA, charts, and local database:

code
npm install next-pwa chart.js react-chartjs-2 dexie
Code collapsed
  • next-pwa: A library that simplifies the process of turning your Next.js app into a PWA.
  • chart.js and react-chartjs-2: For creating beautiful and interactive charts.
  • dexie: A wrapper for IndexedDB that makes it much easier to work with.

Step 1: Turning Your Next.js App into a PWA

The first step is to configure our Next.js application to be a PWA. The next-pwa package handles most of the heavy lifting for us.

What we're doing

We'll configure next.config.js to use next-pwa and create a manifest.json file to define our PWA's properties.

Implementation

  1. Configure next.config.js:

    code
    // next.config.js
    const withPWA = require('next-pwa')({
      dest: 'public'
    })
    
    module.exports = withPWA({
      // next.js config
    })
    
    Code collapsed
  2. Create manifest.json: In your public directory, create a manifest.json file. This file provides information about your application, such as its name, icons, and start URL.

    code
    {
      "name": "Wearable Health PWA",
      "short_name": "HealthPWA",
      "icons": [
        {
          "src": "/icon-192x192.png",
          "sizes": "192x192",
          "type": "image/png"
        },
        {
          "src": "/icon-512x512.png",
          "sizes": "512x512",
          "type": "image/png"
        }
      ],
      "theme_color": "#ffffff",
      "background_color": "#ffffff",
      "start_url": "/",
      "display": "standalone"
    }
    
    Code collapsed

    You'll need to add your own icons in the public folder.

  3. Link the manifest: In your pages/_document.js (or app/layout.tsx for the App Router), add a link to the manifest file in the <Head>:

    code
    import { Html, Head, Main, NextScript } from 'next/document'
    
    export default function Document() {
      return (
        <Html>
          <Head>
            <link rel="manifest" href="/manifest.json" />
          </Head>
          <body>
            <Main />
            <NextScript />
          </body>
        </Html>
      )
    }
    
    Code collapsed

Step 2: Setting Up IndexedDB with Dexie.js

To store our health data locally, we'll use IndexedDB. Dexie.js provides a more developer-friendly API for working with IndexedDB.

What we're doing

We'll create a database schema using Dexie to define our data stores.

Implementation

Create a new file db.js in your project's root directory:

code
// db.js
import Dexie from 'dexie';

export const db = new Dexie('wearableHealthDB');
db.version(1).stores({
  healthData: '++id, date, steps, heartRate' // Primary key and indexed properties
});
Code collapsed

This code creates a database named wearableHealthDB with a table healthData that will store our health metrics.

Step 3: Fetching Data from a Third-Party API

For this example, we'll simulate fetching data from a wearable's cloud API. We'll use Next.js's server-side rendering capabilities to fetch this data.

What we're doing

We'll create a mock API route and then use getServerSideProps to fetch data and pass it to our page. This ensures the data is available on the initial page load, which is great for SEO and perceived performance.

Implementation

  1. Create a mock API route (optional, for demonstration): In pages/api/health-data.js:

    code
    // pages/api/health-data.js
    export default function handler(req, res) {
      res.status(200).json([
        { date: '2023-10-26', steps: 8500, heartRate: 72 },
        { date: '2023-10-27', steps: 9200, heartRate: 75 },
        // ... more data
      ]);
    }
    
    Code collapsed
  2. Fetch data with getServerSideProps: In your main page file (e.g., pages/index.js):

    code
    // pages/index.js
    import { db } from '../db';
    
    export async function getServerSideProps() {
      // In a real app, you'd fetch from an external API
      const res = await fetch('http://localhost:3000/api/health-data');
      const healthData = await res.json();
    
      // Store the fetched data in IndexedDB
      try {
        await db.healthData.bulkPut(healthData);
      } catch (error) {
        console.error("Failed to save data to IndexedDB", error);
      }
    
      return { props: { initialHealthData: healthData } };
    }
    
    Code collapsed

Step 4: Building the Dashboard with Chart.js

Now for the exciting part: visualizing the data!

What we're doing

We'll create a responsive line chart to display the user's step count over time. We'll use the react-chartjs-2 library, which provides React components for Chart.js.

Implementation

  1. Create a chart component: In a new file components/StepsChart.js:

    code
    // components/StepsChart.js
    import { Line } from 'react-chartjs-2';
    import {
      Chart as ChartJS,
      CategoryScale,
      LinearScale,
      PointElement,
      LineElement,
      Title,
      Tooltip,
      Legend,
    } from 'chart.js';
    
    ChartJS.register(
      CategoryScale,
      LinearScale,
      PointElement,
      LineElement,
      Title,
      Tooltip,
      Legend
    );
    
    export const StepsChart = ({ data }) => {
      const chartData = {
        labels: data.map(d => d.date),
        datasets: [
          {
            label: 'Daily Steps',
            data: data.map(d => d.steps),
            borderColor: 'rgb(75, 192, 192)',
            tension: 0.1,
          },
        ],
      };
    
      return <Line data={chartData} />;
    };
    
    Code collapsed
  2. Render the chart on the page: In pages/index.js:

    code
    // pages/index.js
    import { StepsChart } from '../components/StepsChart';
    import { db } from '../db';
    import { useLiveQuery } from 'dexie-react-hooks';
    
    // ... getServerSideProps from before
    
    export default function HomePage({ initialHealthData }) {
      const healthData = useLiveQuery(() => db.healthData.toArray(), [], initialHealthData);
    
      return (
        <div>
          <h1>Your Health Dashboard</h1>
          <StepsChart data={healthData} />
        </div>
      );
    }
    
    Code collapsed

    We're using useLiveQuery from Dexie's React hook library (dexie-react-hooks, which you'll need to install) to get real-time updates from our IndexedDB.

Putting It All Together

With these pieces in place, we have a PWA that:

  1. Is installable and has an app-like feel.
  2. Fetches health data from an API on the server.
  3. Stores that data locally in IndexedDB.
  4. Displays the data in a responsive chart.
  5. Can work offline by reading from the local database.

Performance Considerations

  • Server-Side Rendering (SSR): By using getServerSideProps, the initial data is fetched on the server, leading to a faster first contentful paint.
  • Code Splitting: Next.js automatically splits your code, so only the necessary JavaScript is loaded for each page.
  • Caching: The PWA's service worker will cache static assets, making subsequent visits much faster.

Security Best Practices

  • Environment Variables: Store API keys and other sensitive information in environment variables (.env.local) and access them on the server-side.
  • HTTPS: PWAs require HTTPS, which ensures that data transmitted between the client and server is encrypted.

Production Deployment Tips

  • When deploying your Next.js PWA, ensure your hosting provider supports Node.js environments.
  • Platforms like Vercel and Netlify offer seamless deployment for Next.js applications.

Alternative Approaches

  • Static Site Generation (SSG): If the health data doesn't change frequently, you could use getStaticProps to fetch the data at build time, resulting in an even faster application.
  • Client-Side Fetching: For highly dynamic data, you could fetch it on the client-side within a useEffect hook.

Conclusion

You've now seen how to build a sophisticated Progressive Web App with Next.js, Chart.js, and IndexedDB. This architecture provides a robust foundation for creating high-performance, data-driven applications that work seamlessly online and off.

The next steps could be to add more charts for different health metrics, implement user authentication to fetch personalized data, or add push notifications to remind users to check their progress.

Resources

#

Article Tags

reactnextjspwadatavisualizationhealthtech
W

WellAlly's core development team, comprised of healthcare professionals, software engineers, and UX designers committed to revolutionizing digital health management.

Expertise

Healthcare TechnologySoftware DevelopmentUser ExperienceAI & Machine Learning

Found this article helpful?

Try KangXinBan and start your health management journey

© 2024 康心伴 WellAlly · Professional Health Management