Brew Journal
A beautiful, offline-first coffee logbook and brewing companion designed to track, refine, and perfect your daily coffee rituals.
A fully functioning instance of the application is available at brew.adityagupta.dev.
Screenshots
Screenshots coming soon!
Features
- Coffee Bean Inventory & Recipes: Keep track of your coffee beans, including roasters, roast levels, origins, processing methods, and personal tasting notes. Save custom brewing parameters for every bean.
- Detailed Brew Logging: Record every brewing session with precise details: brew method (Pour Over, Espresso, Cold Brew, etc.), grind size, water temperature, brew ratio, and brew time. Grade your cups with detailed taste notes and reviews.
- Offline-First Sync Engine: Fully functional offline using local browser storage (
localStorage). Automatically merges and syncs to a PostgreSQL database via the Express backend when connectivity is restored, using a conflict-resolution system. - Mobile & PWA Ready: Designed with a sleek, mobile-first responsive layout. Features a custom install prompt modal (including iOS specific guidelines) so you can run it as a standalone app.
- Modern Dark & Light Mode: Clean, warm, custom-tailored interface matching the espresso color palette. Persistent theme switching based on user preference.
- Secure User Accounts: Personal user profiles backed by JSON Web Tokens (JWT) and
bcryptpassword hashing, plus backend API rate-limiting.
Architecture Overview
The codebase is split into two main sections:
- Frontend: A React application located in the root directory, built with Vite. Key files include:
- package.json (dependencies and scripts)
- src/App.jsx (routing and layout)
- src/AuthContext.jsx (authentication state and backend communication)
- Backend: An Express application located in the server/ directory, written in TypeScript. Key files include:
- server/package.json (backend dependencies and scripts)
- server/src/index.ts (Express application setup, routes, and authentication middleware)
- server/src/db.ts (PostgreSQL connection and table initialization)
Prerequisites
Make sure you have the following installed on your system:
- Node.js (v18.x or higher recommended)
- npm (v9.x or higher)
- PostgreSQL (v14 or higher)
Getting Started
1. Database Setup (PostgreSQL)
You need a running PostgreSQL database instance. Follow the steps below based on your operating system:
Installing PostgreSQL
Linux (Debian/Ubuntu)
sudo apt update
sudo apt install postgresql postgresql-contrib
The PostgreSQL service should start automatically. If not, start it with:
sudo systemctl start postgresql
sudo systemctl enable postgresql
macOS (using Homebrew)
brew install postgresql
brew services start postgresql
Windows
Download and run the interactive installer from the Official PostgreSQL Downloads page.
Creating the Database and User
-
Log into the PostgreSQL interactive terminal as the superuser
postgres:sudo -i -u postgres psql(On macOS/Windows, open your terminal/command prompt and run
psql postgresor use a graphical tool like PgAdmin). -
Create a database user with a secure password:
CREATE USER brew_user WITH PASSWORD 'your_secure_password'; -
Create the database and set its owner to
brew_user. Setting the owner guarantees that the user has full table creation privileges on the defaultpublicschema:CREATE DATABASE brew OWNER brew_user; -
Exit the PostgreSQL shell:
\q
Tip
Troubleshooting "Permission denied for schema public" (PostgreSQL 15+): If you already created the database without setting
brew_useras the owner and encounter this error, log in as the superuser (postgres), connect to thebrewdatabase, and explicitly grant the schema privileges:\c brew GRANT ALL ON SCHEMA public TO brew_user;
Note
Database tables (such as
users) are initialized automatically when you start the backend server, as defined in server/db.js.
2. Backend Setup
-
Navigate to the backend directory:
cd server -
Create a server/.env file by copying the template server/.env.example:
cp .env.example .env -
Open server/.env and configure the environment variables:
PORT=5000 DATABASE_URL=postgresql://brew_user:your_secure_password@localhost:5432/brew JWT_SECRET=your_jwt_secret_hereReplace
your_secure_passwordwith the password you set during the database setup. -
Install dependencies and start the backend server:
npm install npm startThe backend should start and display:
Database initialized Server running on port 5000
3. Frontend Setup
-
Open a new terminal window/tab and navigate to the project root directory:
cd /home/sortedcord/Projects/brew -
Install frontend dependencies:
npm install -
Start the Vite development server:
npm run dev -
Open your browser and navigate to the local URL printed in the console (usually
http://localhost:5173).
Production Deployment
When deploying the Brew application to a production environment, follow these guidelines for security, reliability, and performance:
1. Database (PostgreSQL)
- Restricted Access: Do not use superuser accounts (such as
postgres) for backend application connections. Instead, use a restricted role with standard read/write permissions. - Managed Databases: Use a managed database service (e.g., Supabase, Neon, AWS RDS, GCP Cloud SQL) to leverage automated backups, scaling, and high-availability.
- SSL Connection: Enforce encrypted database connections by appending SSL options to the connection string (e.g.,
?sslmode=require).
2. Backend Server Setup
- Environment Variables: In your production environment, set the following environment variables:
NODE_ENV=productionPORT=8080(or whichever port is provided by your host)DATABASE_URL=postgresql://<db_user>:<db_password>@<db_host>:<db_port>/<db_name>?sslmode=requireJWT_SECRET=your_long_random_production_secret(generate a secure 32-byte key usingopenssl rand -base64 32)
- Process Management: Compile TypeScript and use a process manager like PM2 to run the backend node process, keep it alive, and handle automatic clustering or restarts:
# Install PM2 globally npm install -g pm2 # Build the project npm run build --prefix server # Start the backend server pm2 start server/dist/index.js --name "brew-backend" - Restrict CORS: In server/src/index.ts, configure the
corsmiddleware to only accept requests from your frontend production domain:app.use(cors({ origin: 'https://yourfrontenddomain.com' }));
3. Frontend Build & Hosting
- Build the static bundle: Run the build script in the root directory to generate optimized production assets:
This generates static HTML, CSS, and JS files in the
npm run builddist/directory. - Hosting:
- Deploy the static files from the
dist/directory to static hosting platforms like Vercel, Netlify, Cloudflare Pages, or AWS S3/CloudFront. - Alternatively, if using a VPS, serve the
dist/directory using Nginx and proxy API traffic:server { listen 80; server_name yourfrontenddomain.com; # Serve static frontend location / { root /var/www/brew/dist; try_files $uri $uri/ /index.html; } # Proxy API requests to backend server location /api/ { proxy_pass http://localhost:5000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } }
- Deploy the static files from the
Important
HTTPS Required for PWAs: For security reasons, web browsers will only install Progressive Web Apps (PWAs) and register Service Workers when served over a secure connection (
HTTPS). Make sure to set up an SSL certificate (e.g., via Let's Encrypt / Certbot) for your production deployment domain. Local development onlocalhostor127.0.0.1is exempt and will work over HTTP.