DEV Community

Cover image for Part 6 — Nudges, prompts, and knowing when to buy
Nerd Snipe
Nerd Snipe

Posted on

Part 6 — Nudges, prompts, and knowing when to buy

Part 6 — Nudges, prompts, and knowing when to buy

Level: Advanced · Time: ~30 minutes · Builds on: Part 5 — Deals, pricing, and a real board · Series 2, Part 3 of 3

This last tutorial isn't about a new visual primitive. It's about the two components DesignFoundation ships specifically for telling users something without getting in their way — and about being honest with yourself, as the developer, about which parts of your app are worth building again and which parts you should stop rebuilding.

By the end, you'll know how to use DFBanner and DFEmptyState's new secondary action correctly, and you'll have a clear-eyed answer to the question every one of these five tutorials has been building toward: is it time to buy Pro?


What we're adding

  1. DFBanner — a real, non-intrusive disclosure banner, plus the honest way to use one for a feature nudge.
  2. DFEmptyState's secondary action — a genuine two-choice prompt, used where it actually belongs.
  3. A side-by-side: what you built across five tutorials vs. what Pro's CRM vertical ships on day one.
  4. A straight answer on pricing, licensing, and the objections worth taking seriously before you buy anything.

1. DFBanner, used correctly

First, the component. DFBanner is a full-width, persistent, inline banner — deliberately not built on DFToastQueue. A toast is a floating capsule that auto-dismisses after a few seconds; a banner sits in your layout, stays until the user dismisses it, and can carry an action button. Different jobs, different components. Place it directly in your view hierarchy — there's no global overlay host to wire up.

A real, useful banner for this app — telling the user something true about the state of their data:

struct DashboardView: View {
    @State private var showStorageBanner = true

    var body: some View {
        ScrollView {
            VStack(spacing: 16) {
                if showStorageBanner {
                    DFBanner(
                        icon: "externaldrive.fill",
                        message: "Contacts and deals are stored on this device only — there's no sync yet.",
                        severity: .info,
                        isDismissible: true,
                        onDismiss: { showStorageBanner = false }
                    )
                }

                HotLeadsRail(contacts: topContacts)
                StarredContactsGrid(contacts: starredContacts)
            }
            .padding()
        }
        .dfNavigationBar(title: "Dashboard") { }
    }
}
Enter fullscreen mode Exit fullscreen mode

That's the honest use of a banner: real information, dismissible, out of the way once acknowledged. Severity reuses DFToastSeverity (.info, .success, .warning, .error) — no separate enum to learn.

Here's the dishonest version, so you can recognize it and not write it: a banner that fakes urgency ("Only 2 hours left!") or reappears after being dismissed to wear the user down. Don't build that. If a nudge needs a countdown timer to work, it's not a nudge you should ship.


2. DFEmptyState's secondary action, used correctly

We extended DFEmptyState rather than shipping a separate "permission prompt" component, because a permission prompt is really just an empty state with two choices instead of one. The API: secondaryActionTitle + onSecondaryAction, rendered as a ghost-styled button below the primary action.

Here's where it actually belongs in this app — a Reports tab we never built, because analytics wasn't in scope for this series:

struct ReportsView: View {
    @State private var dismissedProNotice = false

    var body: some View {
        if dismissedProNotice {
            DFEmptyState(icon: "chart.bar", title: "No reports yet")
        } else {
            DFEmptyState(
                icon: "chart.bar.xaxis",
                title: "Reports aren't built in this tutorial",
                message: "Revenue trends, deal-stage conversion, and lead-source breakdowns are exactly what DesignFoundationPro's Analytics vertical ships, wired to real charts.",
                actionTitle: "See the Analytics vertical",
                onAction: { /* open pro landing page */ },
                secondaryActionTitle: "Not now",
                onSecondaryAction: { dismissedProNotice = true }
            )
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Notice what makes this honest rather than manipulative: it's true. We didn't build a reports screen in this series. The empty state isn't blocking a feature you paid for — it's accurately describing a gap and telling you exactly where the finished version lives. "Not now" is a real, respected choice, not a decoy — tapping it doesn't nag the user again this session.

That's the difference between a dark pattern and a good nudge: a dark pattern creates false urgency or fake scarcity to manufacture a decision. A good nudge tells the truth faster than the user would have found it themselves.


3. What you actually built, vs. what Pro ships

Five tutorials, one app. Here's the honest comparison — no exaggeration in either direction.

Screen What you hand-built (Parts 1–5) What DFCRMRootView ships
Contacts list DFEntityRow list, segment DFChip filter, search Same, plus persisted filters and a count badge per segment
Contact detail Card layout, DFRatingView, segment chip, notes Same, plus activity timeline, linked deals, and an inspector panel
Deals board DFGrid of DFEntityCard, stage DFChip filter Kanban-style pipeline with drag-to-reorder stages and inline deal editing
Quote screen DFPriceView + DFQuantityStepper + DFPriceSummaryView Same primitives, wired into a full order/invoice flow
Dashboard DFCarousel hot-leads rail, DFEntityCard grid Full analytics screen — line/bar/donut charts, stat cards, period selector
Reports An honest empty state (see above) Full Analytics vertical: Overview, Events, Revenue, Users

You built roughly 70% of a CRM's surface area using free components across five tutorials and a few hours. The other 30% — the parts that took the most engineering time on Pro's side (data-table sorting, chart wiring, drag-to-reorder, persisted filter state, the inspector-panel shell layout) — is exactly what you'd spend the next few weeks on if you kept going alone.


4. So — is it time to buy?

Here's the honest framework, not a sales script.

Buy Pro if:

  • You're about to build a CRM, e-commerce admin, analytics dashboard, or any of Pro's other 9 verticals for a real project — not a tutorial.
  • The parts you're missing (charts, drag-to-reorder, an inspector shell, persisted filters) are the parts you'd rather not debug yourself.
  • You value your time at more than $149 for the individual license, or more than $449 across a team of up to 5 developers — one-time, not a subscription.

Don't buy Pro if:

  • You're still learning the free component vocabulary — come back after you've shipped something with it.
  • Your app doesn't map to any of Pro's verticals (Auth, Analytics, CRM, Documents, E-commerce, Onboarding, Project Manager, Settings, Social, AI Chat) — check the list honestly before paying for screens you won't reuse.
  • You need something Pro doesn't have yet — its scope is real screens for real verticals, not a universal screen generator.

What buying actually gets you, concretely:

  • 47 production-ready screens across 9 verticals, 29 composable blocks, 18 navigation shells — all reading from the exact same DFTheme you've been using since Part 1.
  • A one-time price: $149 per developer (unlimited projects), $449 for a team of up to 5. No seat tax, no subscription for the core license.
  • An optional $39/year update subscription for new components and OS-compatibility updates — skip it and keep everything you already have, forever. Your license never expires and nothing you paid for ever locks or degrades.
  • The free package stays free and MIT-licensed regardless — nothing you built in Parts 1–5 stops working if you never buy Pro at all.

That last point matters: this isn't a trial with a countdown. It's a foundation you can build on indefinitely for free, with a paid ceiling you can raise exactly when your project needs it and not a day before.


What you built, across the whole series

Six tutorials, one Contacts app, turned into something with real product bones:

  • Part 1: Themed list, detail, and a validated form.
  • Part 2: An adaptive shell, search, a command palette, and settings.
  • Part 3: A brand-owned theme, multi-window macOS, custom validators, and tabular data.
  • Part 4: Segment tags, relationship scores, and content-rich entity rows/cards.
  • Part 5: Deals, priced quotes, a filterable board, and a carousel.
  • Part 6: Honest nudges, honest empty states, and an honest answer on Pro.

If you've built along with all six, you don't just know the component vocabulary — you know exactly where the free tier's ceiling is, because you just hit it on purpose.

DesignFoundation Pro

Questions or feedback: open an issue on the design-foundation repo. If this series was useful, a star helps other developers find it.

Top comments (0)