<?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: ahmed rauji</title>
    <description>The latest articles on DEV Community by ahmed rauji (@ahmed_rauji_6cd509f9d1cbc).</description>
    <link>https://dev.to/ahmed_rauji_6cd509f9d1cbc</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%2F4191523%2F22268684-b86a-4cb6-b156-e757e6581755.png</url>
      <title>DEV Community: ahmed rauji</title>
      <link>https://dev.to/ahmed_rauji_6cd509f9d1cbc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ahmed_rauji_6cd509f9d1cbc"/>
    <language>en</language>
    <item>
      <title>Server-Rendered Price Tables: Lessons from Two Gold-Pricing Dashboards in Medan</title>
      <dc:creator>ahmed rauji</dc:creator>
      <pubDate>Sun, 18 Oct 2026 05:39:04 +0000</pubDate>
      <link>https://dev.to/ahmed_rauji_6cd509f9d1cbc/server-rendered-price-tables-lessons-from-two-gold-pricing-dashboards-in-medan-2dne</link>
      <guid>https://dev.to/ahmed_rauji_6cd509f9d1cbc/server-rendered-price-tables-lessons-from-two-gold-pricing-dashboards-in-medan-2dne</guid>
      <description>&lt;p&gt;Server-Rendered Price Tables: Lessons from Two Gold-Pricing Dashboards in Medan&lt;br&gt;
Last year I worked on two company-profile projects for precious-metals businesses in Medan, North Sumatra — PT UNIMETALS INDO RAYA and PT AURUM GRIYA INVESTAMA. Both needed the same thing: a public page that shows gold prices, updated regularly, without the user having to call the store.&lt;/p&gt;

&lt;p&gt;This post is about the technical decisions behind those dashboards. Not the marketing side — the data model, the refresh strategy, and the front-end choices that made them work on the devices people in Medan actually use.&lt;/p&gt;

&lt;p&gt;The Problem With One Number&lt;br&gt;
Most gold price pages show a single figure: the sell price. That's marketing, not information. The number that actually determines whether a gold purchase ever turns a profit is the spread — the gap between the sell price and the buyback price.&lt;/p&gt;

&lt;p&gt;A useful reference is the price page on &lt;a href="https://unimetalsmedan.com/harga-emas-hari-ini/" rel="noopener noreferrer"&gt;harga emas&lt;/a&gt;, which shows both columns side by side for Antam, UBS, and Galeri 24. That two-column layout became the minimum viable format for both projects.&lt;/p&gt;

&lt;p&gt;The Data Model&lt;br&gt;
Both projects ended up with nearly identical models:&lt;/p&gt;

&lt;p&gt;PriceEntry {&lt;br&gt;
  vendor:       "Antam" | "UBS" | "Galeri 24"&lt;br&gt;
  weightGram:   number              // 0.5, 1, 2, 5, 10, 25, 50, 100&lt;br&gt;
  sellPrice:    number              // IDR&lt;br&gt;
  buybackPrice: number              // IDR&lt;br&gt;
  updatedAt:    ISO8601 timestamp&lt;br&gt;
  source:       "manual" | "scraper" | "api"&lt;br&gt;
}&lt;br&gt;
Three rules I'd apply to any similar project:&lt;/p&gt;

&lt;p&gt;Every row gets an updatedAt. Price data without a timestamp is a liability.&lt;br&gt;
Sell and buyback are separate fields. Never derive one from the other — they come from different sources and different spreads.&lt;br&gt;
Weight is explicit. A 1 gram Antam and a 1 gram UBS are different products.&lt;br&gt;
Refresh Strategy&lt;br&gt;
Both projects refresh every 15 minutes. Slower than 30 minutes and users start doubting accuracy. Faster than 5 minutes on the server side was unnecessary.&lt;/p&gt;

&lt;p&gt;Display layer (cached HTML):    every 15 minutes&lt;br&gt;
Server-side data refresh:       every  5 minutes&lt;br&gt;
Historical snapshot archive:    weekly&lt;br&gt;
The server cron job pulls from the upstream source, writes a JSON file, and the HTML table is regenerated from that JSON. No database query on page load.&lt;/p&gt;

&lt;p&gt;The Front-End: Static Shell, Server-Rendered Table&lt;br&gt;
This is the part I'd push back on if a client asked for a SPA. A page that displays a table does not need a JavaScript framework.&lt;/p&gt;

&lt;p&gt;What we actually shipped:&lt;/p&gt;

&lt;p&gt;Static HTML shell — no client-side rendering for the price table.&lt;br&gt;
Server-rendered table — regenerated every 15 minutes from the cached JSON.&lt;br&gt;
Small inline JS — updates the "last updated X minutes ago" label without re-fetching data.&lt;br&gt;
No external CDN dependency for the table — if the CDN is down, the page still shows stale prices with a warning banner.&lt;br&gt;
The last point matters more than it sounds. A dashboard that disappears when the CDN fails is worse than one that shows clearly-labeled stale data. Always show the timestamp.&lt;/p&gt;

&lt;p&gt;Designing for the Actual Device&lt;br&gt;
The dominant browsing profile in Medan is still a mid-range Android on a 3G connection. That constraint drives a lot of decisions:&lt;/p&gt;

&lt;p&gt;No web fonts blocking first paint — system fonts only.&lt;br&gt;
No third-party trackers before the price is visible — analytics loads after the table.&lt;br&gt;
Table renders in the initial HTML payload — not fetched after hydration.&lt;br&gt;
Responsive breakpoints at 360px and 480px — not 768px. 360px is what most users actually see.&lt;br&gt;
Time-to-first-price on a throttled 3G connection ended up around 800ms. Not great, not terrible — but the price is visible before the page finishes loading.&lt;/p&gt;

&lt;p&gt;What We Deliberately Skipped&lt;br&gt;
Real-time price ticker — WebSocket infrastructure for no behavior change.&lt;br&gt;
Price prediction charts — legally risky, factually dubious.&lt;br&gt;
User accounts / login — nobody needs an account to check a price.&lt;br&gt;
Push notifications — conversion too low to justify the permission prompt.&lt;br&gt;
Editorial Notes&lt;br&gt;
The technical dashboard is half the work. The other half is telling users what the numbers actually mean. Across both projects, the content followed three rules:&lt;/p&gt;

&lt;p&gt;Show both sides of the trade. Sell and buyback, always together.&lt;br&gt;
Show the corporate identity. For a commodity business, the entity name and physical address is part of the product. The second project uses &lt;a href="https://emasmedan.com/" rel="noopener noreferrer"&gt;emas medan&lt;/a&gt; as its public entry point — company profile, service information, and consultation channel in one place.&lt;br&gt;
Explain the spread. One paragraph telling users why the sell price and buyback price differ is worth more than any chart.&lt;br&gt;
Takeaways&lt;br&gt;
Show both sides of the trade. One price is marketing; two prices is a service.&lt;br&gt;
Every number gets a timestamp. Stale data labeled as stale is fine. Stale data presented as current is a bug.&lt;br&gt;
Serve the data server-side. A table doesn't need a framework.&lt;br&gt;
Design for the device your audience actually uses. 360px Android on 3G, not 1440px on fiber.&lt;br&gt;
Fail gracefully. If the CDN is down, keep the last known price visible with a warning.&lt;br&gt;
Both projects are live: unimetalsmedan.com (price page at harga emas) and emas medan. If you've built similar commodity-pricing interfaces for the Indonesian market, I'd be curious how you handled the refresh cadence and the buyback spread display.&lt;/p&gt;

&lt;p&gt;Disclosure: this article is part of the company-profile series for both entities. Logo and trademark rights remain with their respective owners. dev.to links are typically nofollow; the anchors here are formatted for reuse in Medium or standalone HTML publications where rel="dofollow" applies.&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
  </channel>
</rss>
