Bidding Interface Components
Relevant source files
The following files were used as context for generating this wiki page:
Bidding Interface Components provide the user-facing tools to interact with the live auction system. These components manage bid submissions, artwork customization, and the display of historical and active placement data.
The system uses a React-based frontend that communicates with a Cloudflare Workers backend. The backend manages a Durable Object with SQLite storage to maintain auction state and process payments through Stripe.
Sources: apps/website/README.md, apps/website/src/components/auction-site.tsx
Bid Submission and Checkout
The BidDialog component acts as the primary interface for creating a new bid. It validates user input, manages artwork uploads, and initiates the Stripe Checkout process.
Bid Lifecycle and Validation
To submit a bid, you must provide a brand name, a website URL, and two PNG images (artwork and logo). The system enforces a minimum bid increment of $1.00 USD above the current placement for a specific slot.
The diagram shows the transition from local UI validation to external payment processing and server-side publication.
Sources: apps/website/src/components/bid-dialog.tsx:84-142, apps/website/worker/auction.ts:335-375
Key Bidding Constraints
| Feature | Constraint | Description |
|---|---|---|
| Minimum Increment | $1.00 (100 cents) | New bids must exceed the current bid by at least 100 cents. |
| Maximum Bid | $99,999,999 | The UI limits bids to under 100 million dollars. |
| Image Format | 8-bit PNG | Only PNGs up to 1024x1024 pixels are accepted to ensure security and compatibility. |
| Message Length | 140 Characters | Optional supporter messages are capped at 140 characters. |
Sources: apps/website/src/lib/auction.ts:88-100, apps/website/src/components/bid-dialog.tsx:55-56, apps/website/worker/auction.ts:254-263
Auction Visualization
The interface provides multiple ways to view auction status, including a 3D car viewer, a tabular spot list, and a leaderboard.
Live Livery Updates
The useAuction hook maintains a WebSocket connection to the backend Durable Object. When a bid is published, the server increments a revision counter and broadcasts an AuctionSnapshot to all connected clients.
This flow illustrates how the UI stays synchronized with the server's authoritative state.
Sources: apps/website/worker/auction.ts:182-192, apps/website/src/components/auction-site.tsx:102-140
Support History and Leaderboard
The HistoricalBids component displays a paginated list of the 50 highest paid bids. It distinguishes between "Past sponsors" and bidders currently "On the car" by comparing bid IDs against the active placements record.
Sources: apps/website/src/components/historical-bids.tsx:10-74
Data Structures
The system relies on stable data structures to ensure consistency between the TypeScript frontend and the SQLite backend.
Auction Snapshot
The AuctionSnapshot represents the entire state of the auction at a specific revision.
export type AuctionSnapshot = {
activeSlotIds: string[];
revision: number;
placements: Record<string, Placement>;
history: Placement[];
highestBids: Placement[];
totalRaised: number;
totalPurchases: number;
online: number;
paymentsEnabled: boolean;
paymentMode: "live" | "test" | "unavailable";
};
Sources: apps/website/src/lib/auction.ts:46-57
Placement Object
Each Placement links a specific Bid to a physical Slot on the vehicle.
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier for the bid/placement. |
slotId | string | The stable geometry ID of the car surface. |
brand | string | Display name of the supporter. |
amount | number | The bid amount in USD cents. |
textureUrl | string | Immutable R2 path for the car surface PNG. |
logoUrl | string | Immutable R2 path for the leaderboard logo PNG. |
publishedAt | number | Unix timestamp of verified publication. |
Sources: apps/website/src/lib/auction.ts:7-17
Conflict Resolution and Refunds
The system handles race conditions where multiple users pay for the same spot simultaneously.
- Validation at Fulfillment: When a Stripe webhook confirms payment, the server re-checks the bid against the current winner in the SQL database.
- Auto-Refund: If the bid is no longer at least $1.00 higher than the current winner (because a higher bid was published while the user was in checkout), the server sets the status to
refund_pending. - Durable Recovery: An internal alarm in the Durable Object retries pending refunds and reconciliation tasks even if the initial process is interrupted.
Sources: apps/website/worker/auction.ts:474-500, apps/website/tests/auction.test.ts:316-335
Bidding Interface Components integrate real-time updates, secure payment flows, and interactive 3D previews to manage a competitive, open-ended auction environment. The architecture ensures that payments are verified, artwork is served immutably, and supporters are correctly attributed in the project's history.