diff --git a/app/page.tsx b/app/page.tsx
index 37ee8e9..7a5921f 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -259,7 +259,18 @@ export default function HomePage() {
Your Sites
Manage your analytics sites and view insights.
- Add New Site
+ {subscription?.plan_id === 'solo' && sites.length >= 1 ? (
+
+
+ Limit reached (1/1)
+
+
+ Upgrade
+
+
+ ) : (
+ Add New Site
+ )}
{/* * Global Overview */}
diff --git a/app/sites/new/page.tsx b/app/sites/new/page.tsx
index 8190b86..c40c312 100644
--- a/app/sites/new/page.tsx
+++ b/app/sites/new/page.tsx
@@ -1,8 +1,9 @@
'use client'
-import { useState } from 'react'
+import { useState, useEffect } from 'react'
import { useRouter } from 'next/navigation'
-import { createSite } from '@/lib/api/sites'
+import { createSite, listSites } from '@/lib/api/sites'
+import { getSubscription } from '@/lib/api/billing'
import { toast } from '@ciphera-net/ui'
import { Button, Input } from '@ciphera-net/ui'
@@ -14,6 +15,28 @@ export default function NewSitePage() {
domain: '',
})
+ // * Check for plan limits on mount
+ useEffect(() => {
+ const checkLimits = async () => {
+ try {
+ const [sites, subscription] = await Promise.all([
+ listSites(),
+ getSubscription()
+ ])
+
+ if (subscription?.plan_id === 'solo' && sites.length >= 1) {
+ toast.error('Solo plan limit reached (1 site). Please upgrade to add more sites.')
+ router.replace('/')
+ }
+ } catch (error) {
+ // Ignore errors here, let the backend handle the hard check on submit
+ console.error('Failed to check limits', error)
+ }
+ }
+
+ checkLimits()
+ }, [router])
+
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
setLoading(true)