addon comin sonn adn pricign apge updates

This commit is contained in:
IGNY8 VPS (Salman)
2026-01-20 01:32:48 +00:00
parent 9d4aa32f9e
commit 9b93d22d22
4 changed files with 240 additions and 43 deletions

View File

@@ -0,0 +1,146 @@
# Managed Add-on Plans (Marketing + App)
**Date:** 2026-01-20
## Goals
- Offer managed services as an optional add-on per site.
- Keep core SaaS plans unchanged while enabling add-on selection at pricing, signup, and billing.
- Provide clear separation between **Core Plans** and **Managed Add-ons** in backend, frontend, and billing UI.
---
## Proposed Managed Add-on Tiers
- **Managed Lite** — **$100/site/month**
- **Managed Pro** — **$399/site/month**
### Managed Features (shared)
- Onboarding & setup: site integration, automation schedule, content settings.
- Monthly SEO content plan: keyword import from library/clustering, topic strategy, content calendar.
- Content QA & optimization: review queue checks, SEO meta validation, internal link suggestions.
- Publishing ops: scheduled publishing, status monitoring, retry/failure handling.
- Reporting: monthly performance + usage summary (credits, content velocity, publishing outcomes).
- Support & tuning: strategy optimization/tweaks, automation adjustments, issue triage.
### Pro extras
- Proactive monitoring and escalation.
- Priority response.
- Expanded strategy iteration (more frequent adjustments).
---
## Marketing Site (https://igny8.com/pricing)
### Layout changes
1. **Keep Core Plans section unchanged**.
2. Add a **big + icon** directly below the pricing table.
3. Add **one single horizontal card** for Managed Add-on:
- Visible badge: **COMING SOON**
- Card title: “Managed Add-on (Per Site)”
- Short summary of major features (1 line)
- **Toggle switch** inside the card for **Managed Lite / Managed Pro**
- Show price per site for the selected toggle
4. No other sections or FAQs added.
### Suggested UX copy
- “Managed Add-on (Per Site) — Coming Soon”
- “Choose Lite or Pro”
---
## Signup Page (https://app.igny8.com/signup)
### Layout changes
Add **Step 2: Managed Add-ons (Optional)** after plan selection.
- Toggle per site: “Add managed services to selected site(s)”
- If user selects a plan with multiple sites:
- Show checkboxes for each site slot.
- Default: none selected.
- Inline price calculator:
- “Managed Lite x N sites = $X/mo”
- “Managed Pro x N sites = $X/mo”
### UX notes
- Keep signup friction low.
- If user skips add-on, allow adding later from Billing.
---
## App Billing & Plans (Account → Plans & Billing)
### New UI sections
1. **Current Plan** remains unchanged.
2. Add **“Managed Add-ons”** section:
- Show current add-on tier (if any) and assigned sites.
- Show monthly add-on price and next renewal date.
3. Add **“Upgrade Add-ons”** tab or sub-panel:
- Choose Managed Lite/Pro.
- Assign to site(s).
- Update monthly total.
### Existing users
- If a user already subscribed to a managed add-on:
- Display in **Plan** tab summary.
- Include in billing history and invoice breakdown.
---
## Backend Model Changes
### Option A (Minimal changes in Plan model)
Add fields to `Plan`:
- `plan_type` (choices: `core`, `managed`) — distinguishes SaaS vs add-on.
- `per_site` (bool, default false) — marks managed add-ons.
- `managed_tier` (optional slug: `lite`, `pro`).
Add optional relation to `Account` or `Site`:
- New model `SiteManagementAddon`:
- `site` (FK)
- `plan` (FK to Plan where `plan_type=managed`)
- `status`, `current_period_start`, `current_period_end`
- `external_subscription_id`
### Option B (Separate ManagedPlan model)
Create `ManagedPlan` model (clone of Plan fields needed for pricing + name).
Keep `Plan` for core SaaS only.
**Recommendation:** Option A (fewer tables, uses existing pricing pipeline).
---
## Backend Billing Logic
- Managed add-ons are **per site**.
- Create separate Stripe subscription items per site, or a single subscription with quantity = number of managed sites.
- Billing summary should show:
- Core plan price
- Managed add-on subtotal (N sites x price)
- Total monthly
---
## Frontend Data Contracts
### API additions
- `GET /api/v1/auth/plans/?type=core` (core plans only)
- `GET /api/v1/auth/plans/?type=managed` (managed add-ons)
- `GET /api/v1/account/managed-addons/` (current user add-ons + site assignments)
- `POST /api/v1/account/managed-addons/` (assign add-on to site(s))
- `PUT /api/v1/account/managed-addons/{id}/` (upgrade/downgrade add-on tier)
---
## Pricing Copy (Core Plans)
Suggested renames to keep consistency:
- Starter → **Launch**
- Growth → **Growth** (keep)
- Scale → **Scale** (keep)
---
## Rollout Checklist
- Add plan_type + per_site fields + migration.
- Add managed add-on seed data (Lite/Pro).
- Add managed add-on endpoints + serializer filtering.
- Update pricing page layout (marketing).
- Update signup flow (managed add-on step).
- Update billing page (Managed Add-ons section).
- Update invoices to show core + managed breakdown.

View File

@@ -53,6 +53,10 @@ export default function PricingTable({
className = '',
}: PricingTableProps) {
const [billingPeriod, setBillingPeriod] = useState<'monthly' | 'annually'>('monthly');
const maxAnnualDiscount = Math.max(
0,
...plans.map((plan) => plan.annualDiscountPercent || 0)
);
const handlePlanClick = (plan: PricingPlan) => {
if (plan.disabled) return;
@@ -117,7 +121,7 @@ export default function PricingTable({
onClick={() => setBillingPeriod('monthly')}
className={`relative z-10 flex h-11 w-[130px] items-center justify-center font-medium transition-all duration-200 rounded-full cursor-pointer ${
billingPeriod === 'monthly'
? 'text-white'
? 'text-white hover:text-white hover:bg-transparent'
: 'text-gray-500 hover:text-gray-700 dark:hover:text-white/80 dark:text-gray-400'
}`}
>
@@ -130,7 +134,7 @@ export default function PricingTable({
onClick={() => setBillingPeriod('annually')}
className={`relative z-10 flex h-11 w-[130px] items-center justify-center font-medium transition-all duration-200 rounded-full cursor-pointer ${
billingPeriod === 'annually'
? 'text-white'
? 'text-white hover:text-white hover:bg-transparent'
: 'text-gray-500 hover:text-gray-700 dark:hover:text-white/80 dark:text-gray-400'
}`}
>
@@ -147,7 +151,7 @@ export default function PricingTable({
d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
Save {Math.round(plans[0]?.annualDiscountPercent || 15)}% with annual billing
Save upto {Math.round(maxAnnualDiscount)}% with annual billing
</span>
)}
</div>

View File

@@ -166,6 +166,7 @@ export { EyeIcon as Maximize2Icon }; // Maximize alias
export { AngleRightIcon as ChevronRightIcon }; // Chevron right alias
export { BoxCubeIcon as Building2Icon }; // Building alias
export { BoxIcon as CreditCardIcon }; // Credit card alias
export { BoxIconLine as CardIcon }; // Card icon alias
export { BoxIcon as WalletIcon }; // Wallet alias
export { AlertIcon as BellIcon }; // Bell notification alias
export { PlugInIcon as TestTubeIcon }; // Test tube alias

View File

@@ -20,6 +20,7 @@ const Pricing: React.FC = () => {
const [plans, setPlans] = useState<Plan[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [managedTier, setManagedTier] = useState<'lite' | 'pro'>('lite');
useEffect(() => {
const fetchPlans = async () => {
@@ -301,7 +302,7 @@ const Pricing: React.FC = () => {
Limited Time
</span>
<p className="text-base sm:text-lg font-bold text-transparent bg-clip-text bg-gradient-to-r from-warning-700 via-warning-700 to-error-700">
Lifetime Discount on all Plans for First 100 Users!
Upto 33% Lifetime Discount on all Plans for First 25 Users!
</p>
</div>
@@ -354,11 +355,65 @@ const Pricing: React.FC = () => {
/>
</div>
{/* What's Included Explanation */}
<div className="max-w-5xl mx-auto mt-8 text-center">
<p className="text-gray-600 dark:text-gray-400 text-sm leading-relaxed">
Every content piece includes High-Opportunity Keywords, AI clustering, idea generation, standard/premium images, Automation, WP publishing, SEO optimization, and internal linking.
</p>
<div className="max-w-5xl mx-auto mt-10">
<div className="flex justify-center">
<div className="flex items-center justify-center w-20 h-20 rounded-full bg-white shadow-md border border-gray-200 text-[var(--color-primary)] text-5xl">
+
</div>
</div>
<div className="mt-6 rounded-2xl border border-brand-200 bg-brand-50 px-6 py-6 shadow-sm">
<div className="flex flex-col gap-6 md:flex-row md:items-center md:justify-between">
<div className="space-y-2">
<div className="flex items-center gap-3">
<h3 className="text-lg font-semibold text-gray-900">
Managed Add-on (Per Site)
</h3>
<span className="inline-flex items-center rounded-full bg-warning-700 px-2.5 py-1 text-xs font-semibold text-white">
COMING SOON
</span>
</div>
<p className="text-sm text-gray-600">
Setup, monthly planning, QA, publishing ops, reporting, and tuning.
</p>
</div>
<div className="flex flex-col gap-3 sm:flex-row sm:items-center">
<div className="inline-flex rounded-full bg-white/80 p-1 border border-gray-200">
<button
type="button"
onClick={() => setManagedTier('lite')}
className={`px-4 py-2 text-sm font-medium rounded-full transition ${
managedTier === 'lite'
? 'bg-[var(--color-success)] text-white shadow'
: 'text-gray-600 hover:text-gray-900'
}`}
>
Managed Lite
</button>
<button
type="button"
onClick={() => setManagedTier('pro')}
className={`px-4 py-2 text-sm font-medium rounded-full transition ${
managedTier === 'pro'
? 'bg-[var(--color-success)] text-white shadow'
: 'text-gray-600 hover:text-gray-900'
}`}
>
Managed Pro
</button>
</div>
<div className="text-right">
<div className="text-xl font-bold text-gray-900">
{managedTier === 'lite' ? '$100' : '$300'}
<span className="text-sm font-medium text-gray-500"> /site/month</span>
</div>
<div className="text-xs text-gray-500">Optional add-on</div>
</div>
</div>
</div>
</div>
</div>
</section>
)}
@@ -453,6 +508,30 @@ const Pricing: React.FC = () => {
</section>
)}
{/* AGENCY CTA */}
<section className="relative overflow-hidden bg-gradient-to-br from-[var(--color-success)] via-[var(--color-primary-dark)] to-[var(--color-primary)] mt-[30px]">
{/* Radial glow */}
<div className="absolute inset-0 bg-[radial-gradient(circle_at_50%_50%,rgba(255,255,255,0.1),transparent_70%)]" />
<div className="relative max-w-4xl mx-auto px-6 py-14 md:py-18 text-center z-10">
<h2 className="text-3xl md:text-4xl lg:text-5xl font-extrabold text-white mb-4 leading-tight max-w-none md:whitespace-nowrap">
Agency & enterprise plans built for scale.
</h2>
<p className="text-lg md:text-xl text-white/90 mb-8 max-w-2xl mx-auto font-medium">
Need more credits, more sites, and lower effective costs? Well tailor a plan that fits your volume and workflow.
</p>
<div className="flex flex-col sm:flex-row gap-5 justify-center">
<Link
to="/contact"
className="inline-flex items-center justify-center gap-2 rounded-xl border-2 border-white/30 bg-white/10 backdrop-blur-sm text-white px-10 py-5 text-lg font-bold hover:bg-white/20 hover:border-white/50 transition"
>
<ChatBubbleLeftRightIcon className="h-5 w-5" />
Talk to sales
</Link>
</div>
</div>
</section>
{/* INFO BLOCKS SECTION */}
<section className="bg-gradient-to-b from-white via-gray-50/30 to-white">
<div className="max-w-6xl mx-auto px-6 py-24 grid grid-cols-1 md:grid-cols-2 gap-8">
@@ -487,39 +566,6 @@ const Pricing: React.FC = () => {
</div>
</div>
</section>
{/* FINAL CTA */}
<section className="relative overflow-hidden bg-gradient-to-br from-[var(--color-success)] via-[var(--color-primary-dark)] to-[var(--color-primary)]">
{/* Radial glow */}
<div className="absolute inset-0 bg-[radial-gradient(circle_at_50%_50%,rgba(255,255,255,0.1),transparent_70%)]" />
<div className="relative max-w-4xl mx-auto px-6 py-24 md:py-32 text-center z-10">
<h2 className="text-4xl md:text-5xl lg:text-6xl font-extrabold text-white mb-6 leading-tight">
Let's build a plan tailored to your growth.
</h2>
<p className="text-xl md:text-2xl text-white/90 mb-12 max-w-2xl mx-auto font-medium">
Get guidance for automation mapping, migration, and onboarding.
</p>
<div className="flex flex-col sm:flex-row gap-5 justify-center">
<Link
to="/contact"
className="inline-flex items-center justify-center gap-2 rounded-xl border-2 border-white/30 bg-white/10 backdrop-blur-sm text-white px-10 py-5 text-lg font-bold hover:bg-white/20 hover:border-white/50 transition"
>
<ChatBubbleLeftRightIcon className="h-5 w-5" />
Talk to sales
</Link>
<a
href="https://app.igny8.com/signup"
target="_blank"
rel="noreferrer"
className="inline-flex items-center justify-center gap-2 rounded-xl bg-white text-[var(--color-primary)] px-10 py-5 text-lg font-bold hover:bg-white/95 transition shadow-xl hover:shadow-2xl hover:-translate-y-0.5"
>
<RocketLaunchIcon className="h-5 w-5" />
Start free trial
</a>
</div>
</div>
</section>
</div>
</>
);