Careeroza
Data Flow
Reading
Browser ── GET /products/redmi-note-14-42 ──► CDN / Next.js
│ static shell cached? ──yes──► send shell
▼
page.tsx (Server Component)
│ getProduct(42) ── lib/dal/products.ts ('use cache', tag product-42)
│ │
│ ▼
│ Prisma ──► PostgreSQL
▼
HTML shell + streamed <DeliveryEstimate/> (cookie: pincode)
▼
Browser hydrates AddToCartButton, Gallery (client)Writing
AddToCartButton (client) ── addToCart(42, 1) [Server Action, POST] ──► server
│ auth / guest cart cookie
│ lib/dal/cart.ts ──► PostgreSQL
│ revalidatePath('/cart')
Navbar badge updates ◄──── action result + fresh RSC payload ──────┘
Razorpay ── POST /api/webhooks/razorpay (HMAC verified) ──► markOrderPaid ──► revalidateTag('orders-u1')Order Total, End to End
Example
The checkout summary combines several rules from this material (paise to avoid float errors, coupon, delivery fee, GST shown inclusive):
type CartLine = { name: string; pricePaise: number; qty: number };
const rupees = (p: number) => '₹' + (p / 100).toLocaleString('en-IN', { minimumFractionDigits: 2 });
function summary(lines: CartLine[], coupon: { code: string; percent: number; maxPaise: number } | null) {
const subtotal = lines.reduce((s, l) => s + l.pricePaise * l.qty, 0);
const discount = coupon ? Math.min(Math.round((subtotal * coupon.percent) / 100), coupon.maxPaise) : 0;
const delivery = subtotal - discount >= 49900 ? 0 : 4000;
const total = subtotal - discount + delivery;
const gstIncluded = Math.round(total - total / 1.18); // 18% GST already inside the price
return { subtotal, discount, delivery, total, gstIncluded };
}
const s = summary(
[{ name: 'Clean Code', pricePaise: 45000, qty: 1 }, { name: 'USB-C Cable', pricePaise: 29900, qty: 2 }],
{ code: 'BOOKS10', percent: 10, maxPaise: 10000 },
);
for (const [k, v] of Object.entries(s)) console.log(k.padEnd(12), rupees(v));Output
subtotal ₹1,048.00 discount ₹100.00 delivery ₹0.00 total ₹948.00 gstIncluded ₹144.61