<?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: KickDown</title>
    <description>The latest articles on DEV Community by KickDown (@kickz1nn).</description>
    <link>https://dev.to/kickz1nn</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4199022%2Fe30f6231-f964-401a-9f77-7d61ea40585d.jpg</url>
      <title>DEV Community: KickDown</title>
      <link>https://dev.to/kickz1nn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kickz1nn"/>
    <language>en</language>
    <item>
      <title>Building AquaSmart: A Water Consumption Monitoring App with Next.js and PostgreSQL</title>
      <dc:creator>KickDown</dc:creator>
      <pubDate>Wed, 21 Oct 2026 19:13:50 +0000</pubDate>
      <link>https://dev.to/kickz1nn/building-aquasmart-a-water-consumption-monitoring-app-with-nextjs-and-postgresql-5bgi</link>
      <guid>https://dev.to/kickz1nn/building-aquasmart-a-water-consumption-monitoring-app-with-nextjs-and-postgresql-5bgi</guid>
      <description>&lt;p&gt;How I built a web application to track shower water and energy consumption, explore usage history, and encourage more sustainable habits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Water and energy consumption are part of our daily lives, but it is not always easy to understand how much we use during a simple activity like taking a shower.&lt;/p&gt;

&lt;p&gt;That is the idea behind &lt;strong&gt;AquaSmart&lt;/strong&gt;, an academic project focused on sustainability and technology. The goal is to build a platform that helps users understand their shower consumption through measurements, historical data, and visual indicators.&lt;/p&gt;

&lt;p&gt;I'm currently studying Computer Engineering, and this project has been a great opportunity to apply what I'm learning about web development, backend architecture, databases, and deployment.&lt;/p&gt;

&lt;p&gt;The application is already deployed, with its main pages and backend functionality working. The physical integration with an ESP32 and sensors is still a future step.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is AquaSmart?
&lt;/h2&gt;

&lt;p&gt;AquaSmart is a web application designed to organize and analyze shower consumption data.&lt;/p&gt;

&lt;p&gt;The current application includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dashboard:&lt;/strong&gt; an overview of consumption data and shower sessions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Session management:&lt;/strong&gt; start, track, and finish shower sessions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consumption history:&lt;/strong&gt; access previously recorded sessions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Charts:&lt;/strong&gt; visualize consumption information over time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customizable settings:&lt;/strong&gt; configure water and electricity costs, as well as a target shower duration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;REST API:&lt;/strong&gt; endpoints for sessions, measurements, history, and settings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistent storage:&lt;/strong&gt; save application data in a PostgreSQL database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Progressive Web App support:&lt;/strong&gt; foundational PWA features for compatible devices.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The idea is to build the software foundation first and then connect it to physical sensors for real-world measurements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technology Stack
&lt;/h2&gt;

&lt;p&gt;Here are the main technologies I used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js 16&lt;/strong&gt; — application framework and backend API routes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React 19&lt;/strong&gt; — user interface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript&lt;/strong&gt; — type safety and maintainable code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSS Modules&lt;/strong&gt; — component-specific styling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recharts&lt;/strong&gt; — charts and data visualization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prisma ORM 7&lt;/strong&gt; — database access and schema management.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PostgreSQL&lt;/strong&gt; — relational data storage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Neon&lt;/strong&gt; — managed PostgreSQL database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vercel&lt;/strong&gt; — application deployment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I chose this stack to keep the frontend and backend in one project while maintaining a clear separation between the different responsibilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Structuring the Backend
&lt;/h2&gt;

&lt;p&gt;One of the most interesting parts of this project has been organizing the backend.&lt;/p&gt;

&lt;p&gt;Instead of putting all the business logic directly inside API route handlers, I separated the code into modules.&lt;/p&gt;

&lt;p&gt;The main modules are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;sessions&lt;/code&gt;: creates, retrieves, and finishes shower sessions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;measurements&lt;/code&gt;: validates and stores consumption measurements.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;history&lt;/code&gt;: retrieves historical session data.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dashboard&lt;/code&gt;: provides aggregated information for the dashboard.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;settings&lt;/code&gt;: manages user-configurable consumption parameters.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each module follows a structure that separates route handling, business logic, database access, and validation.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
├── app/
│   └── api/
│       ├── dashboard/
│       ├── health/
│       ├── history/
│       ├── sessions/
│       └── settings/
├── lib/
│   └── prisma.ts
└── modules/
    ├── dashboard/
    ├── history/
    ├── measurements/
    ├── sessions/
    └── settings/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This organization makes the code easier to navigate and gives each part of the application a clear responsibility.&lt;/p&gt;

&lt;p&gt;It also makes future changes easier. For example, the way measurements are received can evolve without requiring all the business logic to be rewritten inside the API handlers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Designing the Database
&lt;/h2&gt;

&lt;p&gt;AquaSmart uses PostgreSQL with Prisma to store sessions, measurements, and settings.&lt;/p&gt;

&lt;p&gt;The database currently has three main models.&lt;/p&gt;

&lt;h3&gt;
  
  
  Session
&lt;/h3&gt;

&lt;p&gt;A session represents a shower and stores information such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start and finish timestamps.&lt;/li&gt;
&lt;li&gt;Duration in seconds.&lt;/li&gt;
&lt;li&gt;Total water consumption.&lt;/li&gt;
&lt;li&gt;Total energy consumption.&lt;/li&gt;
&lt;li&gt;Current status.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sessions can be &lt;code&gt;IN_PROGRESS&lt;/code&gt; or &lt;code&gt;COMPLETED&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Measurement
&lt;/h3&gt;

&lt;p&gt;Measurements belong to a session and contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Measurement timestamp.&lt;/li&gt;
&lt;li&gt;Water flow rate in liters per minute.&lt;/li&gt;
&lt;li&gt;Accumulated water volume in liters.&lt;/li&gt;
&lt;li&gt;Electrical power in watts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each measurement is associated with its session through a database relationship.&lt;/p&gt;

&lt;h3&gt;
  
  
  Settings
&lt;/h3&gt;

&lt;p&gt;The settings model stores parameters used by the application, including water cost per cubic meter, electricity cost per kilowatt-hour, and the target shower duration.&lt;/p&gt;

&lt;p&gt;I also use Prisma migrations to track database schema changes, which helps keep the development and deployment environments consistent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling Shower Sessions
&lt;/h2&gt;

&lt;p&gt;Session management involves more than simply creating a database record.&lt;/p&gt;

&lt;p&gt;The backend prevents multiple active sessions from being created concurrently. It uses a PostgreSQL transaction and an advisory lock when starting a session.&lt;/p&gt;

&lt;p&gt;Finishing a session also needs to account for concurrent requests. The repository locks the corresponding session row before checking its status and updating it.&lt;/p&gt;

&lt;p&gt;The finish timestamp is generated by the backend, and the duration is calculated from the difference between the start and finish timestamps.&lt;/p&gt;

&lt;p&gt;This keeps the session lifecycle controlled by the server rather than relying entirely on values provided by the client.&lt;/p&gt;

&lt;p&gt;These details were useful learning experiences because they showed me how database transactions and locking mechanisms can help protect data consistency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the REST API
&lt;/h2&gt;

&lt;p&gt;The API is implemented with Next.js Route Handlers.&lt;/p&gt;

&lt;p&gt;Some of the available endpoints include:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/dashboard&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Retrieve dashboard data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/sessions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List sessions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;POST&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/sessions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Start a session&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/sessions/active&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Retrieve the active session&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/sessions/[id]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Retrieve a specific session&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PATCH&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/sessions/[id]/finish&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Finish an active session&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;POST&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/sessions/[id]/measurements&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Record measurements&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/history&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Retrieve session history&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/settings&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Retrieve settings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PATCH&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/settings&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Update settings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/health&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Check database connectivity&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The measurements endpoint accepts batches containing between 1 and 100 measurements. The backend validates the payload, including numeric values and timestamps, before processing it.&lt;/p&gt;

&lt;p&gt;I also added a health endpoint that checks whether the application can connect to the database. This is useful when diagnosing deployment and connectivity issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deployment and Database Connectivity
&lt;/h2&gt;

&lt;p&gt;Deploying the application was another important part of the process.&lt;/p&gt;

&lt;p&gt;AquaSmart is hosted on Vercel, with PostgreSQL provided by Neon.&lt;/p&gt;

&lt;p&gt;During deployment, I encountered an issue related to Prisma Client generation. The solution was to run Prisma generation as part of the build process:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"prisma generate &amp;amp;&amp;amp; next build"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also had to configure &lt;code&gt;DATABASE_URL&lt;/code&gt; in the appropriate Vercel environments so the application could connect to the database.&lt;/p&gt;

&lt;p&gt;These issues helped me understand that a project can work locally and still fail during deployment because of differences in environment variables, generated files, or build configuration.&lt;/p&gt;

&lt;p&gt;Getting the application deployed and verifying that the database-backed features worked was an important milestone.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;Building AquaSmart has given me practical experience with several areas of software development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backend architecture:&lt;/strong&gt; Separating routes, services, repositories, and validation helped me understand how to organize application logic as a project grows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Database consistency:&lt;/strong&gt; Working with Prisma, migrations, transactions, and row locking introduced me to important considerations when multiple requests interact with the same data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;API design:&lt;/strong&gt; Implementing endpoints for sessions, measurements, history, and settings helped me practice request validation and HTTP response handling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deployment:&lt;/strong&gt; Configuring the production database and resolving build issues taught me that deployment is part of development, not just the final step.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sustainability and technology:&lt;/strong&gt; The project gave me a way to connect software engineering with a practical problem involving water and energy consumption.&lt;/p&gt;

&lt;p&gt;There is still a lot to improve, but having a working application deployed online gives me a solid foundation to build on.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;The next major milestone is integrating the application with physical hardware.&lt;/p&gt;

&lt;p&gt;The planned setup involves an ESP32 and sensors that can provide measurements related to water flow and electrical consumption. Those measurements could then be sent to the backend and used to update the dashboard and session history.&lt;/p&gt;

&lt;p&gt;This integration has not been completed yet. For now, AquaSmart provides the software foundation, database models, and API endpoints needed to support that future work.&lt;/p&gt;

&lt;p&gt;Other potential improvements include automated tests, stronger authentication, and additional consumption analytics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try AquaSmart
&lt;/h2&gt;

&lt;p&gt;The project is available here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub repository:&lt;/strong&gt; &lt;a href="https://github.com/Kickz1nn/aquasmart" rel="noopener noreferrer"&gt;AquaSmart source code&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live demo:&lt;/strong&gt; &lt;a href="https://aquasmart-fawn.vercel.app" rel="noopener noreferrer"&gt;Try AquaSmart&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AquaSmart is an ongoing academic project, and I'm looking forward to improving it as I continue learning about backend development, databases, and embedded systems.&lt;/p&gt;

&lt;p&gt;If you have suggestions about the architecture, API design, or future hardware integration, I'd be happy to hear your feedback!&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>nextjs</category>
      <category>typescript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
