Skip to content

Cloud onboarding wizard, billing trial card, and post-checkout server setup - #5264

Merged
Siumauricio merged 3 commits into
canaryfrom
feat/cloud-onboarding-plan-gate
Sep 2, 2026
Merged

Cloud onboarding wizard, billing trial card, and post-checkout server setup#5264
Siumauricio merged 3 commits into
canaryfrom
feat/cloud-onboarding-plan-gate

Conversation

@Siumauricio

@Siumauricio Siumauricio commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

What

  • Onboarding wizard (Welcome → Plan → Project → Server → Deploy → Complete), shown once to an org owner with zero projects and no active plan/trial. Skippable per step or entirely, with a confirm before skipping everything.
  • Billing page shows the org's current plan, and a no-card 14-day trial card when eligible.
  • Post-checkout "Welcome to Dokploy Cloud" modal simplified: reuses the onboarding wizard's own project/server/deploy steps behind a modal instead of its previous standalone 6-step flow, with the app's regular typography instead of the wizard's display serif.
  • onboardingCompletedAt column on user, with a backfill so existing users aren't shown the wizard on upgrade.
  • pnpm reset-onboarding <email> dev script to reset a test account's onboarding state (Stripe subscriptions, projects, servers, flags) end to end.
  • apps/api: local Inngest dev server script + README section.

Fixes along the way

  • Onboarding wizard now validates a persisted project still exists before resuming a stale session, instead of landing on a dead link.
  • Dashboard layout no longer gets stuck redirecting to /dashboard/home once the local onboarding-active flag goes stale mid-session (it was only ever read once, on first mount, since the layout persists across navigations).

Greptile Summary

The PR adds a cloud onboarding wizard, no-card trials, billing status UI, post-checkout project/server/deployment setup, onboarding persistence, and local development utilities.

  • Adds project, server, and quickstart deployment onboarding flows.
  • Adds Stripe trial creation and current billing-status handling.
  • Adds the onboarding-completion migration and reset utility.
  • Adds local Inngest development documentation and scripts.

Confidence Score: 2/5

The PR should not merge until duplicate trial creation, automatic setup of existing servers, and organization-wide reset deletions are addressed.

Concurrent trial requests can create untracked Stripe subscriptions, the onboarding server step can reconfigure an unrelated existing host automatically, and the reset script can delete shared resources across every organization joined by the target user.

Files Needing Attention: apps/dokploy/server/api/routers/stripe.ts, apps/dokploy/components/dashboard/onboarding/steps/server-step.tsx, apps/dokploy/scripts/reset-onboarding.ts

Reviews (1): Last reviewed commit: "feat: cloud onboarding wizard, billing t..." | Re-trigger Greptile

Greptile also left 3 inline comments on this PR.

Siumauricio and others added 3 commits September 1, 2026 19:11
…server setup

- Onboarding wizard (Welcome -> Plan -> Project -> Server -> Deploy ->
  Complete), shown once to an org owner with zero projects and no active
  plan/trial; skippable per step or entirely
- Billing page shows the org's current plan, and a no-card 14-day trial
  card when eligible
- Post-checkout "Welcome to Dokploy Cloud" modal simplified to reuse the
  onboarding wizard's own project/server/deploy steps behind a modal
  instead of its previous standalone 6-step flow, using the app's regular
  typography instead of the wizard's display serif
- Onboarding wizard validates a persisted project still exists before
  resuming a stale session, and the dashboard layout no longer gets stuck
  redirecting to /dashboard/home once the local onboarding-active flag
  goes stale mid-session
- onboardingCompletedAt column on user, with a backfill so existing users
  aren't shown the wizard
- pnpm reset-onboarding dev script to reset a test account's onboarding
  state end to end
Comment on lines +94 to +100
const subscription = await stripe.subscriptions.create({
customer: stripeCustomerId,
items: [{ price: HOBBY_PRICE_MONTHLY_ID, quantity: 1 }],
trial_period_days: TRIAL_DURATION_DAYS,
trial_settings: { end_behavior: { missing_payment_method: "cancel" } },
metadata: { source: "onboarding_trial", adminId: owner.id },
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Concurrent trials bypass eligibility

If two organization admins start a trial concurrently, both requests can pass the eligibility check before either persists billing state, causing Stripe to create multiple trial subscriptions while Dokploy tracks only the last one written.

Comment on lines +97 to +101
useEffect(() => {
if (!createdServerId && existingServers && existingServers.length > 0) {
setCreatedServerId(existingServers[0]!.serverId);
}
}, [existingServers, createdServerId]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Existing server setup starts automatically

When the organization already has a server, this selects the most recently created accessible server and starts setupWithLogs before validation establishes whether setup is required, causing Docker Swarm, network, Traefik, and dependency setup to run against an unrelated existing host.

Knowledge Base Used: Dashboard and client state

Comment on lines +80 to +103
for (const membership of memberships) {
const deletedProjects = await db
.delete(projects)
.where(eq(projects.organizationId, membership.organizationId))
.returning({ id: projects.projectId, name: projects.name });
for (const project of deletedProjects) {
console.log(` - deleted project "${project.name}" (${project.id})`);
}

const deletedServers = await db
.delete(server)
.where(eq(server.organizationId, membership.organizationId))
.returning({ id: server.serverId, name: server.name });
for (const deletedServer of deletedServers) {
console.log(
` - deleted server "${deletedServer.name}" (${deletedServer.id})`,
);
}
}

await updateUser(foundUser.id, {
onboardingCompletedAt: null,
stripeCustomerId: null,
// startFreeTrial sets these directly on the user row (not via webhook),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Reset deletes shared organization resources

When the target account belongs to an organization shared with other users, the script deletes every project and server by membership organization ID, causing resources unrelated to that test account to be permanently removed.

Knowledge Base Used: Identity, permissions, and audit

@Siumauricio
Siumauricio merged commit c32c8d0 into canary Sep 2, 2026
4 checks passed
@Siumauricio
Siumauricio deleted the feat/cloud-onboarding-plan-gate branch September 2, 2026 06:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant