The website can't promise a price the app won't charge
Yesterday was the panel the people running ParkEase use. Today is the page everyone else sees first. A driver searching "parking near Indiranagar" doesn't land in an app. They land on a website. So does an owner wonderi
Yesterday was the panel the people running ParkEase use. Today is the page everyone else sees first.
A driver searching "parking near Indiranagar" doesn't land in an app. They land on a website. So does an owner wondering whether their empty driveway could earn anything. In about ten seconds that page has to say what ParkEase is, who it's for, and what it costs.
That last part is where marketing sites quietly lie.
Where the numbers go wrong
Every product site has a pricing page and an example: "Book 2 hours at βΉ40, pay βΉX." Somebody types that example into the page, a designer makes it beautiful, and it ships.
Then the fee changes. The app changes with it, because the app's prices come from the server. The website doesn't, because nobody remembers that a sentence in a hero section was a price.
Now the site promises one number and the checkout charges another. In a market where people are already wary of "convenience fees", that's the fastest way to lose someone forever.
One source for every number
ParkEase already had one place prices live: the contracts package that the API itself uses to compute every booking, every commission and every tax line, in integer paise.
So the website doesn't contain prices. It imports them. Every number the site quotes is computed from that package at build time, with the same functions the API calls:
/**
* Every number the site quotes, derived from @parkease/contracts so the marketing copy cannot
* drift from what the API charges. Nothing here is typed in by hand.
*/
const pct = (rate: number): number => Math.round(rate * 100);
const rupees = (paise: number): number => paise / 100;
/** Two hours at βΉ40, at a normal hour: the worked example used on the site. */
const EXAMPLE_HOURS = 2;
const EXAMPLE_HOURLY_PAISE = 4_000;
const example = quote({
basePaise: toPaise(EXAMPLE_HOURS * EXAMPLE_HOURLY_PAISE),
surgeMultiplier: toRate(1),
});
/** A 3 km valet leg and a βΉ399 premium wash, priced by the same functions the API uses. */
const valetTripKm = 3;
const valetTrip = computeValetLegFee(valetTripKm * 1_000, VALET_COMMISSION_RATE);
const washExample = computeWashFee(toPaise(39_900), CARWASH_COMMISSION_RATE);
quote() is the function that prices a real booking. If the commission moves, the site's worked example moves with it on the next build. There's no second copy to forget.
The pricing table is tested against what it renders, not against the constants, because what a visitor reads is the HTML:
it('lists owner commission as 15% of base, charged once', () => {
expect(ledger('For space owners')).toContain('15% of the base booking price, charged once');
});
The same rule runs through the rest of the site. Colours come from the app's design tokens, and a test fails on any colour typed in by hand. Every page's title and description lives in one list, which the metadata, the sitemap and the tests all read. The city pages exist only for cities in one array, and any other slug is a real 404, not an empty page Google will index.
What's on it
The video walks through the site itself: the "Stop circling the block" hero with a parking bay that lights up FREE, the map, where every rupee of a booking goes, the earnings calculator for owners, and valet and car wash. Beyond that there are city pages, an FAQ and the legal pages. Playwright checks every page at desktop and phone sizes, runs axe on each, and fails if anything scrolls sideways down to 320 pixels wide. Lighthouse gates performance and SEO in CI.
And as of this week, it's live: https://parkease-web-navy.vercel.app
What I'd tell myself before starting
The dangerous numbers on a website aren't in the pricing table; everyone remembers that one. They're the ones in sentences. If a number appears in copy, it's data, and data has one source.
Next: a website, an admin panel and an app, each built and tested on its own. Tomorrow I put all three on the internet for the first time, for free, and find out what five weeks of green tests had missed. It was more than one thing.
ParkEase is a peer-to-peer parking marketplace for India, built solo.
Code: https://github.com/Deonkar/parkease Β· Music: ende.app (CC BY 4.0)
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.