diff --git a/CHANGELOG.md b/CHANGELOG.md index 26d8951b..f40ae296 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +* **settings/license:** replaced static "View Pricing" button with dynamic upgrade cards — Community users see Personal Pro and Team Pro options with feature highlights; Personal Pro users see Team Pro upgrade only; each card links directly to Lemon Squeezy checkout + * **docs:** comprehensive documentation audit — updated 11 pages with accurate content and 14 fresh screenshots * **docs/configuration:** removed JWT_SECRET from required env vars (it's auto-generated), added compose directory reorganization explanation * **docs/settings:** added missing License, Users, Webhooks, Support, and About sections; removed obsolete Appearance section diff --git a/docs/features/licensing.mdx b/docs/features/licensing.mdx index 3daabf5e..7cfc47da 100644 --- a/docs/features/licensing.mdx +++ b/docs/features/licensing.mdx @@ -21,16 +21,24 @@ Every new Sencho installation starts with a **14-day Pro trial** - no license ke When the trial expires, Sencho automatically reverts to the Community tier. No data is lost. -## Purchasing a license +## Upgrading your plan -1. Visit [sencho.io](https://sencho.io/#pricing) and choose a plan. -2. Complete the checkout on Lemon Squeezy. -3. You'll receive a license key by email. +You can upgrade directly from **Settings > License** in your Sencho dashboard. The upgrade cards shown depend on your current tier: + +- **Community users** see both **Personal Pro** and **Team Pro** options with feature highlights and direct checkout links. +- **Personal Pro users** see a **Team Pro** upgrade card for when you need unlimited accounts. +- **Team Pro users** are on the highest tier — no upgrade cards are shown. + +Clicking an upgrade button opens the Lemon Squeezy checkout in a new tab. After completing the purchase, you'll receive a license key by email. + + + License settings showing upgrade cards for Personal Pro and Team Pro + ## Activating your license 1. Go to **Settings > License** in your Sencho dashboard. -2. Paste your key into the **License Key** field. +2. Paste your key into the **License Key** field at the bottom of the page. 3. Click **Activate**. Sencho validates the key against Lemon Squeezy and activates Pro features immediately. diff --git a/docs/images/license-settings.png b/docs/images/license-settings.png index fd806cdd..a2011afd 100644 Binary files a/docs/images/license-settings.png and b/docs/images/license-settings.png differ diff --git a/docs/reference/settings.mdx b/docs/reference/settings.mdx index 417dff63..00db4cd9 100644 --- a/docs/reference/settings.mdx +++ b/docs/reference/settings.mdx @@ -39,7 +39,7 @@ Manage your Sencho Pro license from this section. | **Trial status** | If on a trial, shows remaining days | | **Customer / Plan / Key** | Displayed when a Pro license is active | | **Renews** | Next renewal date for active subscriptions | -| **View Pricing** | Opens the Sencho pricing page to purchase a license | +| **Upgrade cards** | Dynamic plan cards with feature highlights and direct Lemon Squeezy checkout links. Community users see Personal Pro and Team Pro; Personal Pro users see Team Pro only | | **Activate** | Enter a license key to activate Pro | | **Manage Subscription** | Opens the billing portal (active Pro only) | | **Deactivate License** | Reverts to Community features (active Pro only) | diff --git a/frontend/src/components/SettingsModal.tsx b/frontend/src/components/SettingsModal.tsx index 8667e3a2..5aa44b48 100644 --- a/frontend/src/components/SettingsModal.tsx +++ b/frontend/src/components/SettingsModal.tsx @@ -18,7 +18,7 @@ import { Badge } from '@/components/ui/badge'; import { toast } from 'sonner'; import { apiFetch } from '@/lib/api'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; -import { Shield, Activity, Bell, Code, Server, Package, RefreshCw, Database, Info, Crown, CheckCircle, XCircle, Clock, Webhook, Copy, Trash2, Plus, ChevronDown, ChevronRight, History, Users, Pencil, ExternalLink, CreditCard, LifeBuoy, Book, Mail, Bug } from 'lucide-react'; +import { Shield, Activity, Bell, Code, Server, Package, RefreshCw, Database, Info, Crown, CheckCircle, Check, XCircle, Clock, Webhook, Copy, Trash2, Plus, ChevronDown, ChevronRight, History, Users, Pencil, ExternalLink, CreditCard, LifeBuoy, Book, Mail, Bug, Zap } from 'lucide-react'; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from '@/components/ui/alert-dialog'; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'; import { NodeManager } from './NodeManager'; @@ -647,7 +647,7 @@ function UsersSection() { export function SettingsModal({ isOpen, onClose }: SettingsModalProps) { const { activeNode } = useNodes(); const { isAdmin } = useAuth(); - const { license, isPro, activate, deactivate, checkout } = useLicense(); + const { license, isPro, activate, deactivate } = useLicense(); const isRemote = activeNode?.type === 'remote'; const [activeSection, setActiveSection] = useState('account'); const [licenseKeyInput, setLicenseKeyInput] = useState(''); @@ -1184,59 +1184,111 @@ export function SettingsModal({ isOpen, onClose }: SettingsModalProps) { )} - {/* Subscribe / Activate (not active) */} - {license?.status !== 'active' && ( -
-
- -

- Purchase a license key from our website, then activate it below. -

-
- + {/* Upgrade Cards — Community: show both, Personal Pro: show Team only, Team Pro: none */} + {(license?.tier !== 'pro' || (license?.variant === 'personal' && license?.status === 'active')) && ( +
+ +
+ {/* Personal Pro Card — only for Community users */} + {license?.tier !== 'pro' && ( +
+
+ + Personal Pro + Popular +
+

Professional tools for solo operators.

+
    + {['Fleet View with drill-down', 'RBAC viewer accounts (1 + 3)', 'Custom webhooks', 'Atomic deployment', 'Fleet-wide backups'].map((f) => ( +
  • + + {f} +
  • + ))} +
+ +
+ )} - {/* License key activation */} -
- -
- setLicenseKeyInput(e.target.value)} - className="font-mono" - /> + {/* Team Pro Card */} +
+
+ + Team Pro +
+

For teams managing shared infrastructure.

+
    + {[ + ...(license?.variant === 'personal' ? ['Everything in Personal Pro'] : ['Everything in Community']), + 'Unlimited admin accounts', + 'Unlimited viewer accounts', + ...(license?.variant !== 'personal' ? ['Fleet View & webhooks', 'Atomic deployment & backups'] : []), + 'Team onboarding assistance', + ].map((f) => ( +
  • + + {f} +
  • + ))} +
)} + + {/* License key activation — show when not active */} + {license?.status !== 'active' && ( +
+ +
+ setLicenseKeyInput(e.target.value)} + className="font-mono" + /> + +
+
+ )}
)} diff --git a/frontend/src/context/LicenseContext.tsx b/frontend/src/context/LicenseContext.tsx index 4a9d425d..cc87208e 100644 --- a/frontend/src/context/LicenseContext.tsx +++ b/frontend/src/context/LicenseContext.tsx @@ -26,7 +26,6 @@ interface LicenseContextType { refresh: () => Promise; activate: (licenseKey: string) => Promise<{ success: boolean; error?: string }>; deactivate: () => Promise<{ success: boolean; error?: string }>; - checkout: () => void; } const LicenseContext = createContext(undefined); @@ -88,14 +87,10 @@ export function LicenseProvider({ children }: { children: ReactNode }) { } }, []); - const checkout = useCallback(() => { - window.open('https://sencho.io/#pricing', '_blank'); - }, []); - const isPro = license?.tier === 'pro'; return ( - + {children} );