Desktop Primary Wireframe

Container Product Detail Page

PDP is the checkout entry point. Left column scrolls with product content. Right column sticks with the booking widget. Pre-checkout dialog eliminated.

URL: /all-pro-waste-services-spring-tx/dumpster-rental/20yd-roll-off-dumpster

Container image

20yd Roll-Off Dumpster

All Pro Waste Services · Spring, TX · ★ 4.8 (42)

Reduction: Hauler name, location, and rating collapsed into subtitle. No separate "About" card — customer came from hauler profile, they know who this is.
22' L × 8' W × 4.5' H · 2 tons included
Reduction: Container Details card (5 rows) collapsed to one inline badge. Size and type are in the title. Door is noise. Weight capacity merged with dimensions.
Great for
Kitchen remodel Multi-room renovation Roof replacement Landscaping
What can go in it?

✓ Accepted

  • Household junk & furniture
  • Drywall, lumber, flooring
  • Yard waste & brush
  • Concrete (with weight limit)

✗ Not accepted

  • Hazardous materials
  • Tires & batteries
  • Paint & chemicals
View full profile →

Household Junk · 7-day rental

$350
✓ In service area · 4.2 mi

or call (281) 555-0199

Reduction: Pricing details block killed (duplicate of left column). Price summary killed ($350 repeated as line item then total). Header/footer chrome killed. One surface: price, two inputs, CTA. Price embedded in button for single scannable action target.
Multi-tier (8.5%): Tier radio list appears between price and address. Multi-product (0.9%): Separate booking cards per product on page.
Mobile Revised

Container PDP — Utility-First Mobile

The mobile PDP mirrors the desktop sticky column. Booking form IS the page. CTA above the fold. Supporting content scrolls below. No drawer, no sticky bar.

Above the fold (~750px viewport)

20yd Roll-Off Dumpster

All Pro Waste Services · Spring, TX

Household Junk · 7-day rental

$350

or call (281) 555-0199

Below the fold

Below the fold (scrolled)

  • Size20 cubic yards
  • TypeRoll-off
  • Dimensions22'L × 8'W × 4.5'H
  • Weight limitUp to 4 tons
Kitchen remodel Multi-room renovation Roof replacement Landscaping

✓ Yes

  • Furniture & junk
  • Drywall, lumber
  • Yard waste

✗ No

  • Hazmat
  • Tires, batteries
  • Paint, chemicals
AP
All Pro Waste Services
Spring, TX · ★ 4.8 (42)
Utility-first mobile: The booking form IS the page — mirrors the desktop sticky column directly. Title, price, address, dates, and CTA all fit above the fold. No selectors for 79% of products. No drawer. No sticky bottom bar. Supporting content below the fold in collapsible sections.
Why this is right: The customer clicked through from the hauler profile card. They've already decided on this container. The PDP's job on mobile is to capture the booking, not re-sell them. Content is there for reassurance, not discovery — it belongs below the fold.
Component

Hauler Profile — Minimal Product Cards

Product cards on the hauler profile become list items that link to the PDP. Minimal info: container icon, size + type, lowest price. Details live on the PDP.

Roll-Off Dumpsters

10yd
10yd Roll-Off Dumpster
Household Junk · 7-day rental
$275
15yd
15yd Roll-Off Dumpster
Household Junk · 7-day rental
$325
20yd
20yd Roll-Off Dumpster
Household Junk · 7-day rental
$350
20yd
20yd Roll-Off Dumpster
Construction & Demolition · 7-day rental
$425
30yd
30yd Roll-Off Dumpster
Household Junk · 14-day rental
$450
40yd
40yd Roll-Off Dumpster
Construction & Demolition · 14-day rental
$550

Dumpster Trailers

10yd
10yd Dumpster Trailer
Household Junk · 7-day rental
$299

What changed from the current product cards

  • Each card = one product. No grouping by container. 20yd MSW and 20yd C&D are two separate cards. Products are not variants.
  • Meta line: Waste stream name + rental period (from lowest tier). Identifies the product specifically.
  • Price: Flat price, not "from $X". Single tier = single price (79% of products). Multi-tier shows lowest.
  • Grouped by: Container type (Roll-Off vs Trailer). Within group, sorted by size ascending.
  • Behavior: Entire card links to PDP. Click-through only. No expand, no dialog.
  • URL target: /hauler-slug/dumpster-rental/20yd-roll-off-dumpster — container-level page showing this product.
URL implication for multi-waste-stream containers (0.9%): Both the 20yd Household Junk and 20yd C&D cards link to the same URL (20yd-roll-off-dumpster). That page shows both products as separate booking sections. The card that was clicked could scroll-to or highlight the relevant product via a hash or query param.
Architecture Breaking Change

URL Restructuring — Product Slug

Product slug changes from waste-stream-based to container-type-based. Each waste stream is a separate product — not a variant, not a selector. Container-level URL groups products when multiple exist (0.9% of cases).

Slug format change
Current (waste-stream in URL) Proposed (container-type in URL)
Format {size}-yard-{wasteStream} {size}yd-{containerType}
Example 1 10-yard-msw 10yd-roll-off-dumpster
Example 2 20-yard-c-and-d 20yd-roll-off-dumpster
Example 3 10-yard-msw (trailer) 10yd-dumpster-trailer
Waste stream In URL path (one URL per product) Separate products on same container page (no selector)
Pages per container One per waste stream
(20yd + 3 waste streams = 3 URLs)
One per container type
(20yd roll-off = 1 URL)
Container type → slug mapping
DB containerType URL slug suffix Full example
roll_off roll-off-dumpster 20yd-roll-off-dumpster
trailer dumpster-trailer 10yd-dumpster-trailer
front_load front-load-dumpster 2yd-front-load-dumpster
rear_load rear-load-dumpster 4yd-rear-load-dumpster
wheeled_cart wheeled-cart 96gal-wheeled-cart
Slug generation function (updated)
// packages/db/src/utils/product-slug.ts

const CONTAINER_TYPE_SLUGS: Record<string, string> = {
  roll_off: "roll-off-dumpster",
  trailer: "dumpster-trailer",
  front_load: "front-load-dumpster",
  rear_load: "rear-load-dumpster",
  wheeled_cart: "wheeled-cart",
}

export function generateContainerSlug(
  size: string | number,
  volumeUnit: string,
  containerType: string,
): string {
  const n = parseFloat(String(size))
  const sizeStr = n % 1 === 0 ? String(n) : n.toFixed(1)
  const unit = volumeUnit === "yard" ? "yd" : "gal"
  const typeSuffix = CONTAINER_TYPE_SLUGS[containerType]
    ?? containerType.replace(/_/g, "-")
  return `${sizeStr}${unit}-${typeSuffix}`
}

// "20yd-roll-off-dumpster"
// "10yd-dumpster-trailer"
// "96gal-wheeled-cart"
Redirect strategy
  • All old URLs get 301 redirects. /hauler/lob/10-yard-msw/hauler/lob/10yd-roll-off-dumpster?waste=msw
  • 301 preserves SEO authority. Google treats 301s as permanent and transfers ranking signals.
  • Redirect map generated from DB: query all products, build old slug → new slug mapping, add to Next.js redirects in next.config.mjs or middleware.
  • Waste stream preserved via query param. The ?waste=msw param pre-selects the waste stream on the PDP so inbound links from search or directory pages land on the right context.

Why this URL change is correct

  • Customers don't search by waste stream. "10 yard dumpster rental" has search volume. "10 yard MSW dumpster" has zero. The waste stream is a configuration detail, not a navigation concept.
  • Container type IS meaningful navigation. A roll-off dumpster and a dumpster trailer are physically different products. A customer looking for one isn't looking for the other.
  • Consolidates thin pages. A hauler with 20yd MSW + 20yd C&D currently has two near-identical pages. One page with waste stream selection is richer and concentrates SEO authority.
  • Keywords in URL. "roll-off-dumpster" and "dumpster-trailer" are searched terms. "msw" and "c-and-d" are industry jargon customers don't use.
  • Matches the PDP model. If waste stream is an on-page selector (not a URL differentiator), the URL should reflect the physical product, not the waste configuration.
Reference

Design Decisions & Framework Rationale

Every decision in this wireframe traced to a framework or validated pattern.

Decision 1: PDP as checkout entry point
  • What changed Pre-checkout dialog eliminated. Booking inputs move to PDP sidebar.
  • Framework Cold Start Problem (Ch. 12) — transaction friction kills liquidity
  • Supporting Fogg Behavior Model — reduce effort at the Action step
  • Reference model Airbnb listing page: content left, booking widget right
  • Risk Form on PDP may create premature commitment anxiety for browsers
  • Mitigation Form starts empty. CTA says "Continue to Checkout" (not "Pay Now"). Call-to-quote always visible as escape hatch.
Decision 2: No variants — separate products
  • What changed Waste stream selector killed. Each waste stream = separate product, not a variant.
  • Data 99.1% of container groups have one waste stream. 79% of products have one tier. Selectors solved a <1% edge case.
  • Implication Default PDP has zero selectors — just price, address, dates, CTA. Tier selector appears conditionally (8.5% of products).
  • Multi-product containers (0.9%) Same container URL shows separate product sections. Not variants — separate booking forms.
Decision 3: Minimal hauler profile cards
  • What changed Product cards on hauler profile show container + price + arrow. No tiers, no waste stream label.
  • Framework Thinking, Fast and Slow (Kahneman) — browsing is System 1, deciding is System 2. Don't force System 2 on a browsing page.
  • Grouped by Container type (Roll-Off, Trailer) then by size within group
  • Card shows Size badge, container name, waste type count, rental range, lowest price, chevron
Decision 4: Utility-first mobile (revised)
  • What changed Mobile PDP = the desktop booking widget rendered as the full page. CTA above the fold. No drawer, no sticky bar.
  • Rationale Customer clicked through from hauler profile — they've decided. The PDP's job on mobile is to capture the booking, not re-sell. Content is reassurance, not discovery.
  • Layout Header (title + hauler) → waste stream → tiers → address → dates → CTA. All above fold. Supporting content below in collapsible accordion sections.
  • Previous approach Content-first page with sticky bottom bar + booking drawer. Killed — treated mobile as a browsing page when it should be a booking page.
Decision 5: Content enrichment sections
  • What's new Container render/image, project tags, accepted/rejected materials
  • Purpose Answer the two questions 80% of first-time renters have: "Is this the right size?" and "Can I put X in it?"
  • Data source Static content mapped per container size + waste stream. Not DB-driven (yet).
  • SEO value Unique, useful content per page. Avoids thin-page penalties. Matches informational search intent alongside transactional.
Decision 6: Checkout flow unchanged
  • What stays the same Checkout page layout, Stripe Elements, placement form, contract approval
  • What changes Entry point moves from dialog to PDP sidebar. Checkout receives same query params.
  • Implication PRD #211 issues #212-#218 all remain valid. Only #214 (pre-checkout dialog) is superseded by PDP sidebar.
Resolved decisions (from Justin, 2026-03-30)
  • Container image: generic placeholder. Just a dashed box showing layout space. No SVG renders, no photos. Future investment.
  • Project tags: repackage existing SIZE_CONTENT. Data already curated in size-directory-view.tsx. Industry-standard sizing guidance. No deep research needed. Refine with booking data when available.
  • No waste stream context from directory. Directory pages filter by location + size, never by waste stream. No ?waste= param needed. PDP defaults to first available waste stream.
  • No PDP for unclaimed haulers. PDP only exists when hauler has claimed AND set up products. Unclaimed haulers have profile pages and directory cards only. Route returns 404 if no products exist for the container.