You are browsing as a guest. Sign up (or log in) to start making projects!

Diqi

@Diqi

Joined June 1st, 2026

  • 13Devlogs
  • 3Projects
  • 1Ships
  • 0Votes
hiiiiii stardance
Open comments for this post

38m logged

OTP UX Fix and SMTP IPv4 Compatibility

Summary This update focused on two main issues in the OTP flow: improving the user experience when the send-code button is pressed, and making the Gmail SMTP fallback more reliable on Railway by forcing IPv4 instead of the blocked IPv6 path.

1) OTP Send Button UX Improvement

Problem

The previous OTP flow allowed users to click the “Send Code” button repeatedly while the backend was still processing the request. This created a poor user experience and could trigger duplicate email sends or repeated requests.

Fix

The frontend button logic was updated so that while the OTP request is in progress:

  • the button is disabled,
  • the text changes to “Sending…”,
  • repeated clicks are prevented,
  • the button returns to “Send Code” after the request finishes,
  • the user receives a clearer success/error message in English.This makes the request flow feel intentional and prevents confusion during slow network conditions.

2) SMTP IPv4 Fix for Railway:

Problem

The app was trying to connect to Gmail SMTP using Railway’s outbound networking stack. Railway was preferring IPv6 resolution for Gmail, which caused outbound connections to fail with unreachable network errors.

Root Cause

The SMTP connection attempted to reach Gmail over IPv6, but the Railway container did not have a working outbound route for that address family. As a result, the backend could not complete the SMTP connection, even though the app code itself was otherwise valid.

Fix

The Nodemailer transport was updated to force IPv4 resolution by setting:
jsfamily: 4
This keeps the existing SMTP host configuration (host: process.env.SMTP_HOST) but forces Node.js to use IPv4 instead of attempting the failing IPv6 route.Additional timeout settings were also added to prevent request hangs:
jsconnectionTimeout: 10000,greetingTimeout: 5000,socketTimeout: 10000,
This ensures that if SMTP is blocked or slow, the backend responds quickly with a clear error instead of leaving the browser hanging with a generic network issue.

Outcome

The OTP flow is now more stable and user-friendly:

  • the button cannot be spam-clicked,
  • users receive better status feedback,
  • the SMTP connection is more resilient in Railway when Gmail is accessed over IPv4.

This patch addresses the UX problem and the deployment-specific SMTP issue without changing the overall app architecture.

0
0
20
Ship Changes requested

I built DuskCoffee, a fullstack web application for a modern coffee shop catalog and guest ordering system. Built with Node.js, Express, and Vanilla JavaScript, paired with a cloud-managed MySQL database on Aiven and live hosting on Railway over HTTPS.

The most challenging part was managing environment configurations, fixing strict SSL connections between Node.js and Aiven MySQL, and setting up proper routing to prevent API errors. I’m really proud of getting a complete cloud database pipeline running smoothly with zero-downtime deployment setup!

To test the project, navigate through the Menu/Products tab to see live data pulled straight from the cloud database, or try out the feedback/contact form

  • 10 devlogs
  • 27h
Try project → See source code →
Open comments for this post

1h 11m 3s logged

Summary : Email delivery system integration (Contact Form + OTP), Railway deployment debugging, and infrastructure troubleshooting.

What’s Complete

  1. Email Service Architecture (Priority-Based Fallback)Status: Fully Integrated & Production-Ready

Contact Form Email Flow

  • File: src/routes/contact.js
  • Priority 1 (Production): Resend API — works on Railway, no outbound restrictions
  • Priority 2 (Local Dev): Nodemailer + Gmail SMTP (port 587, TLS)
  • Format: Visitor name in sender, reply-to set to visitor email for direct Gmail replies
  • Testing: Verified via curl — email successfully delivered to [email protected]

OTP Email Flow

  • File: src/routes/auth.js
  • Priority 1 (Production): Resend API — handles 6-digit OTP codes
  • Priority 2 (Local Dev): Nodemailer + Gmail SMTP
  • Timeout: 5-minute code expiration
  • Verified: Code generation and storage logic working correctly

2. Frontend Contact Form Fix

Status: Resolved Event Binding Issue

  • Problem: DOMContentLoaded event wrapper in contact.js was unreliable because script loads after DOM already ready
  • Solution: Removed wrapper, direct event attachment at script execution- Added: Console debug logging for form submission tracking and error diagnosis
  • Result: Form submission now reliably attaches event listeners and sends fetch requests

3. Railway Deployment Testing*

Status: Contact form working in production

  • Domain: https://duskcoffee-production.up.railway.app
  • Tested by: User (Kaedara) — successfully sent contact message
  • Response logs show: Payload received, message queued, response returned to frontend
  • Email delivery: Via Resend (Nodemailer fallback blocked due to Railway SMTP restrictions)
1
0
5
Open comments for this post

46m 18s logged

Project Goes Live!
Status: Core Architecture Deployed & Live (Railway + Aiven DB).

Whats working perfect:

  • Database Migration & Cloud Infrastructure: Successfully migrated local MariaDB schema to Aiven Managed Cloud MySQL.
  • Backend Deployment: Node.js / Express backend is live on Railway with dynamic port handling and SSL configuration (rejectUnauthorized: false).
  • Catalog APIs: Core catalog endpoints (/api/products/menu & /api/products/beans) are returning 200 OK responses directly from the cloud database.
  • Guest Checkout Schema: Relational database schema refactored to support seamless guest ordering (orders and order_items tables with proper menu_id & product_id key constraints).

Next things to do (Might do later):

  1. Email OTP Verification MechanismCurrent Status: Temporarily disabled.Future Idea: Swapping Resend for Nodemailer with Gmail App Passwords so guests can actually get their verification codes… if I feel like setting up SMTP again.
  2. Order Queue & Confirmation FlowCurrent Status: The database saves transactions fine, but the post-checkout experience is pretty plain right now.Future Idea: Adding a real-time order queue screen (pending $\rightarrow$ paid $\rightarrow$ completed) and an instant digital receipt, assuming I don’t get distracted by another project.
  3. Contact Form MailerCurrent Status: The UI form looks nice, but submit doesn’t send anything yet.Future Idea: Hooking it up to the mailer service whenever I get around to fixing the email pipeline.

Next Steps after that (Maybe)

  • Mess around with Nodemailer in Express routes for OTP.
  • Auto-clear the localStorage cart after checkout.
  • Call it a day and grab an actual coffee
0
0
9
Open comments for this post

2h 39m 49s logged

Summary

Today’s work focused on aligning the project with the intended business flow: guest checkout with email OTP validation, instead of traditional user registration/login. The backend, schema, and cart payload were cleaned up to remove account-based flow and enforce a consistent transaction model.

What changed

  • Removed the account-based auth flow from the project.
    • No more users table in the database.
    • No more login and register endpoints.
  • Kept the guest checkout path as the only legitimate order flow.
    • Customer browses without logging in.
    • Customer enters name, phone, and email on checkout.
    • Email OTP is sent and validated before the order is placed.
  • Fixed the order schema to match the real business model.
    • orders.customer_phone is used as the canonical phone field.
    • orders.total remains the canonical total value.
  • Refined the order item model.
    • order_items now stores either menu_id or product_id, never both.
    • This avoids the earlier issue where product_id was effectively a stringly-typed placeholder and not a real product reference.
  • Resolved cart identity collisions.
    • Menu and product items can share the same numeric id, so the cart now distinguishes them using item_type.
  • Created a separate seed.sql file for catalog data.
    • Schema file now defines structure only.
    • Seed file loads initial menu and product records.

Key architecture decision

The system now follows a single contract:

  • Guest checkout only
  • Email OTP verification required before order placement
  • Orders stored in orders
  • Line items stored in order_items
  • Each order item references either:
    • a menu item, or
    • a product item

This avoids duplicated and confusing legacy fields such as phone, total_amount, and users authentication.

Validation

I verified the JavaScript syntax for the changed backend and cart code:

  • node --check passed for the modified JavaScript files.
  • No editor errors were reported for the updated route and cart logic.

Notes / Follow-up

The remaining operational step is database migration/import:

  • recreate the local MariaDB database
  • import the cleaned schema
  • import the seed file
  • start the app and test the OTP checkout flow end-to-end
0
0
14
Open comments for this post

1h 42m 19s logged

Guest Checkout and email OTP refactor

  • Removed the need for users to create an account before browsing or ordering.

  • Kept the storefront experience frictionless: users can still browse products and add items to the cart without logging in.

  • Added checkout.html

  • Added a checkout flow that collects:
    full name, phone number, email, 6-digit OTP code

  • Added a “Send Code” button in the checkout form to trigger email verification before order placement.

  • Implemented OTP storage with a temporary in-memory map and expiration logic.

  • Added backend endpoints for:sending OTP emailsverifying OTP codessubmitting guest checkout orders after successful validationUpdated the order flow to store guest customer data directly in the database instead of requiring a registered user session.

  • Kept the storefront experience frictionless: users can still browse products and add items to the cart without logging in.

  • REMOVE auth.html

0
0
9
Open comments for this post

nvm, I decided to change the flow from a traditional account creation model to a streamlined Guest Checkout with Email OTP Verification. Users will no longer register or log in to browse and build orders. Verification occurs on-demand right before order placement on checkout.html.

3
1
2
Open comments for this post
Reposted by @Diqi

2h 50m 44s logged

Overview :
Refactored the DuskCoffee client and backend to replace static mockups with a dynamic, data-driven system. Implemented checkout calculations, order submission endpoints, schema updates for order persistence, and a local JSON fallback mechanism for offline development.

File Changes SummaryEdited Files:
checkout.html — Updated UI container structure to support dynamic order rendering.checkout.

js — Added localStorage cart parsing, dynamic item rendering, price computations (subtotal, tax, delivery), and API POST triggers.

menu.html — Removed duplicate static .menu-full-card markup to rely on JavaScript rendering.

script.js — Refactored fetch logic to hit live API endpoints first, falling back to static JSON on failure.

schema.sql — Extended database schema with orders and order_items tables; verified product image paths.

server.js — Mounted orders API route and configured server initialization.

Added Files:
orders.js — Express route handler to process incoming checkout payloads and persist orders to MariaDB.

menu-fallback.json — Static fallback dataset containing all 16 menu items for local development.

checkout.html - Static checkout page but with dynamic/sync data with what item’s user add to cart

0
1
9
Open comments for this post

2h 50m 44s logged

Overview :
Refactored the DuskCoffee client and backend to replace static mockups with a dynamic, data-driven system. Implemented checkout calculations, order submission endpoints, schema updates for order persistence, and a local JSON fallback mechanism for offline development.

File Changes SummaryEdited Files:
checkout.html — Updated UI container structure to support dynamic order rendering.checkout.

js — Added localStorage cart parsing, dynamic item rendering, price computations (subtotal, tax, delivery), and API POST triggers.

menu.html — Removed duplicate static .menu-full-card markup to rely on JavaScript rendering.

script.js — Refactored fetch logic to hit live API endpoints first, falling back to static JSON on failure.

schema.sql — Extended database schema with orders and order_items tables; verified product image paths.

server.js — Mounted orders API route and configured server initialization.

Added Files:
orders.js — Express route handler to process incoming checkout payloads and persist orders to MariaDB.

menu-fallback.json — Static fallback dataset containing all 16 menu items for local development.

checkout.html - Static checkout page but with dynamic/sync data with what item’s user add to cart

0
1
9
Open comments for this post

42m 26s logged

make the contact section look better i thnk, tryna user resend for the logic of sending messages, but it didnt work when i tried it myself for testing. well ill think about that later, i got bigger problem here, how to deploy this thing as full stack web 😭

0
0
5
Open comments for this post

24m 5s logged

Key Features:
Navbar - Navigation menu with Home, About Us, Menu, Products, and Contact links; includes search bar and shopping cart
Hero Section - Eye-catching welcome banner with call-to-action (“Order Now”)
About Us - Company story and values with images
Menu Section - Showcases coffee beverages and food items (Croissant, Cappuccino, Americano, etc.) with prices
Interactive Elements - Hamburger menu for mobile, search functionality, click-outside handlers

will add more soon…..

1
0
26

Followers

Loading…