Pricing computation library for the epilot platform. Handles tariff calculations, tax, discounts, tiered pricing, composite prices, and currency formatting.
A single-page React app that demonstrates every pricing model the library supports. Each page is a self-contained, interactive example with live computation, visual breakdown, and a code snippet showing the data model.
The Playground is a Visual Storybook for pricing -- a living documentation tool that serves multiple audiences:
- Developer Experience -- Before the Playground, testing pricing models required linking the library and running live on the platform. Now developers can explore, configure, and validate any pricing scenario interactively without touching a real environment.
- Onboarding & Reference -- Especially valuable for Customer Success teams to explain how a given pricing model works to customers. Each page is self-explanatory with interactive controls and real computed results.
- Marketing -- Publicly shareable showcase of epilot's pricing capabilities -- Dynamic Tariffs, GetAG integration, Coupons, Composite Pricing, and more. The Playground is the documentation.
- Technical Sales -- For demos with IT departments and technical managers who want to understand the range of pricing scenarios epilot supports. A useful reference during deeper technical evaluations.
- React 18 + TypeScript
- Vite (dev server + build)
- Tailwind CSS (utility-first styling)
- No external UI library -- all components are custom
demo/
src/
App.tsx # Sidebar navigation + section routing
helpers.ts # Shared utilities: fmtCents, fmtEur, buildPriceItemDto, makeTax, makeCoupon
main.tsx # Entry point
components/
CodeBlock.tsx # Syntax-highlighted code snippet with copy button
ProductShowcase.tsx # Product category cards with SVG illustrations
ResultCard.tsx # Colored result metric card
TariffCard.tsx # Gradient header card for tariff summaries
TierChart.tsx # Bar chart for tiered pricing visualization
sections/
OverviewDemo.tsx # Landing page with feature highlights
ElectricityDemo.tsx # Single/dual tariff with base price + work price
GasDemo.tsx # Gas tariff with CO2 and storage levies
HouseConnectionDemo.tsx # Multi-utility connection with distance-based trench work
NonCommodityDemo.tsx # Product bundles using composite prices (price_components)
PerUnitDemo.tsx # Basic per-unit pricing
TieredVolumeDemo.tsx # Volume-based tier selection
TieredGraduatedDemo.tsx # Graduated tier pricing
TieredFlatFeeDemo.tsx # Flat fee per tier
TaxDemo.tsx # Tax-inclusive vs tax-exclusive comparison
DiscountDemo.tsx # Fixed/percentage discounts and cashback
CompositePriceDemo.tsx # Composite price with price_components
CurrencyDemo.tsx # EUR and CHF formatting utilities
DynamicTariffDemo.tsx # Market price + supplier margin
GetAGDemo.tsx # GetAG regulated fee breakdown (electricity + gas)
The sidebar organizes sections into two groups:
Energy Products: Electricity, Gas, House Connection, Products & Add-ons
Pricing Models: Per Unit, Tiered Volume, Tiered Graduated, Tiered Flat Fee, Tax Handling, Discounts & Coupons, Composite Pricing, Currency & Formatting, Dynamic Tariff, GetAG Energy
Every section file follows the same pattern:
- State -- React
useStatefor user-configurable inputs (prices, quantities, tax rates) - Computation --
useMemocallingcomputeAggregatedAndPriceTotals()from@epilot/pricingwith price items built viabuildPriceItemDto() - Manual display calculations -- Parallel EUR calculations for the visual breakdown (tariff cards, cost lines, stacked bars)
- UI -- Left column with controls, right column with TariffCard/ResultCard showing results
- Code example -- A
CodeBlockat the bottom showing the exact data model passed to the library
- Currency formatting: Always use
fmtCents(amountInCents)for library output orfmtEur(amountInEUR)for manual calculations. Both produce€12,500.00format. Never useEUR ${value.toFixed(2)}ortoLocaleString('de-DE'). - ct/kWh to EUR conversion: Energy work prices are entered in ct/kWh but the library expects EUR. Always divide by 100:
(parseFloat(ctValue) / 100).toFixed(4). - Language: All text must be in English. No German labels (no Grundpreis, Arbeitspreis, Erdgas, etc).
- Supported currencies: Only EUR and CHF.
- Code examples: Show
unit_amount(integer cents) alongsideunit_amount_decimal(EUR string). Do not duplicatepricing_model/is_tax_inclusiveat item level -- keep them only in_price. Do not include a separatetaxesarray on the item. - Consumption items: Use
quantity: 1withprice_mappings: [{ frequency_unit, value }]to model consumption-based pricing (the mapping drives the quantity). - Product bundles: Use composite prices (
is_composite_price: truewithprice_components) not individual items. - Simulated data: GetAG and Dynamic Tariff pages include an info block noting values are simulated.
- Create
demo/src/sections/YourDemo.tsxfollowing the pattern of existing sections - Import and add it to the
sectionsarray indemo/src/App.tsx - Use
buildPriceItemDto()fromhelpers.tsto create price items - Use
computeAggregatedAndPriceTotals()from@epilot/pricingfor computation - Display results with
ResultCard(metrics) and optionallyTariffCard(energy tariffs) - Add a
CodeBlockat the bottom showing the data model - Run
npx tsc --noEmit --project demo/tsconfig.jsonto verify TypeScript - Run
npx vite buildfromdemo/to verify the production build
After making changes to the playground:
# 1. Build the demo
cd demo && npx vite build
# 2. Navigate to the docs repo
cd /path/to/codebase/github/docs
# 3. Copy the built playground into the docs site
npm run update-pricing-playground
# 4. Commit and push all files (including untracked new assets)
git add -A
git commit -m "update pricing playground"
git push
# This triggers the CI build which deploys the docs site with the updated playground.The main export is computeAggregatedAndPriceTotals(priceItems) which takes an array of price items and returns aggregated totals including amount_subtotal, amount_tax, amount_total, and per-item breakdowns.
per_unit-- unit price x quantitytiered_volume-- single tier selected by quantity, applies to all unitstiered_graduated-- each tier applies to units in its rangetiered_flatfee-- flat fee per tier based on quantity
- Price item:
{ quantity, _price: { unit_amount, unit_amount_decimal, unit_amount_currency, pricing_model, is_tax_inclusive, type, billing_period, tax } } - Composite price:
{ _price: { is_composite_price: true, price_components: [...] }, price_components: [...] } - Dynamic tariff: Standard
per_unitwith_price.dynamic_tariffmetadata - Coupons: Attached via
_couponsarray on the price item. Fixed or percentage, discount or cashback category.