Skip to content

Commit f144d24

Browse files
anuveyatsuclaude
andcommitted
feat(pricing): single-row plans, relocate Arc/Cloud strip, simplify TCO (po-6sc)
- Remove ProductLines (Arc/Cloud disambiguation) from /pricing; relocate the canonical framing to a new docs page (/docs/products) + sidebar entry, plus an unobtrusive "Not sure which product?" link on pricing. - Make all 5 plans fit one row on desktop: 5-col grid at lg, tighter card padding and price typography; sm 2-col, mobile stacked. - Replace the per-competitor TCO table with a generic CostSavings section ("Customers report a 50-80% reduction") — no vendor names, no table. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent bf05f38 commit f144d24

7 files changed

Lines changed: 134 additions & 202 deletions

File tree

site/components/CostSavings.tsx

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { useEffect, useRef } from 'react'
2+
import posthog from 'posthog-js'
3+
4+
// Generic, high-level cost message (po-6sc §3). Replaces the per-competitor TCO table
5+
// (TcoComparison) — no vendor names, no figures table. Framed as "reported" / "typically"
6+
// to stay credible. Named comparisons live only on the dedicated /compare pages.
7+
export default function CostSavings() {
8+
const ref = useRef<HTMLDivElement>(null)
9+
10+
useEffect(() => {
11+
const el = ref.current
12+
if (!el || typeof IntersectionObserver === 'undefined') return
13+
const observer = new IntersectionObserver(
14+
(entries) => {
15+
entries.forEach((entry) => {
16+
if (entry.isIntersecting) {
17+
try {
18+
posthog.capture('pricing_cost_savings_view')
19+
} catch (_) {
20+
/* never let analytics break the page */
21+
}
22+
observer.disconnect()
23+
}
24+
})
25+
},
26+
{ threshold: 0.4 }
27+
)
28+
observer.observe(el)
29+
return () => observer.disconnect()
30+
}, [])
31+
32+
return (
33+
<section
34+
ref={ref}
35+
className="mx-auto max-w-3xl px-4 sm:px-6 lg:px-12 mt-24 text-center"
36+
>
37+
<h2 className="text-3xl font-bold tracking-tight text-slate-900 dark:text-white sm:text-4xl">
38+
Same job. A fraction of the invoice.
39+
</h2>
40+
<p className="mx-auto mt-6 text-2xl font-semibold tracking-tight text-slate-900 dark:text-white sm:text-3xl">
41+
Customers report a{' '}
42+
<span className="text-blue-600 dark:text-blue-400">50–80% reduction</span>{' '}
43+
in total cost.
44+
</p>
45+
<p className="mx-auto mt-4 text-[17px] leading-relaxed text-slate-600 dark:text-slate-300">
46+
Open-source economics change the math: no per-dataset caps, no quota
47+
licensing, no license fees. You typically pay only for hosting,
48+
compliance, and support — not for the right to publish your own data.
49+
</p>
50+
</section>
51+
)
52+
}

site/components/PricingPlans.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ export default function PricingPlans() {
265265
</p>
266266
)}
267267

268-
<main className="relative mx-auto mt-10 grid max-w-md grid-cols-1 gap-y-8 lg:-mb-14 lg:max-w-none lg:grid-cols-2 custom:grid-cols-5 gap-3 px-1 dark:px-0">
268+
<main className="relative mx-auto mt-10 grid max-w-md grid-cols-1 gap-y-8 lg:-mb-14 lg:max-w-none sm:grid-cols-2 lg:grid-cols-5 gap-3 px-1 dark:px-0">
269269
<div
270270
className="hidden lg:absolute lg:inset-x-px lg:bottom-0 lg:top-4 lg:block lg:rounded-2xl"
271271
aria-hidden="true"
@@ -306,7 +306,7 @@ export default function PricingPlans() {
306306
{tier.badge}
307307
</span>
308308
)}
309-
<div className="p-8 lg:pt-12 xl:p-8 xl:pt-14 flex flex-col flex-1">
309+
<div className="p-5 pt-10 lg:pt-12 flex flex-col flex-1">
310310
<h3 id={tier.id} className="text-xl font-bold leading-6">
311311
{tier.title}
312312
</h3>
@@ -327,9 +327,9 @@ export default function PricingPlans() {
327327
</h4>
328328

329329
<div className="flex flex-col gap-4 sm:justify-between lg:flex-col lg:items-stretch">
330-
<div className="flex items-center gap-x-4 min-h-[70px] sm:-mt-2">
330+
<div className="flex items-center gap-x-3 min-h-[70px] sm:-mt-2">
331331
<p className="text-2xl xl:text-xl semi-bold tracking-tight">
332-
<span className="text-4xl font-bold tracking-tight">
332+
<span className="text-3xl xl:text-4xl font-bold tracking-tight">
333333
{priceValue}
334334
</span>
335335
</p>

site/components/ProductLines.tsx

Lines changed: 0 additions & 63 deletions
This file was deleted.

site/components/TcoComparison.tsx

Lines changed: 0 additions & 131 deletions
This file was deleted.

site/content/assets/docs-sidebar.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
"title": "Core concepts",
2424
"href": "/docs/core-concepts"
2525
},
26+
{
27+
"title": "PortalJS vs Arc vs Cloud",
28+
"href": "/docs/products"
29+
},
2630
{
2731
"title": "Architecture decision framework",
2832
"href": "/docs/architecture/decision-framework"

site/content/docs/products.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
---
2+
metatitle: PortalJS vs Arc vs Cloud – Which product is which?
3+
metadescription: PortalJS is the open-source framework; PortalJS Arc is the default managed layer (zero-infra, edge-served portals); PortalJS Cloud is a managed CKAN backend you attach to Arc when a program needs heavy cataloging. How the three fit together.
4+
title: PortalJS vs Arc vs Cloud
5+
description: One open-source framework, two managed layers. How PortalJS, PortalJS Arc, and PortalJS Cloud fit together — and which one you actually need.
6+
---
7+
8+
There are three names in the PortalJS world — **PortalJS**, **PortalJS Arc**, and
9+
**PortalJS Cloud**. Most of the time you only need to know one of them. This page
10+
explains what each is and how they layer, so you can pick without second-guessing.
11+
12+
> [!info] Short version
13+
> **PortalJS** is the open-source framework (own the code, host anywhere).
14+
> **PortalJS Arc** is the default managed way to run it (zero-infra, edge-served).
15+
> **PortalJS Cloud** is a managed CKAN backend you *attach* to Arc when a program
16+
> needs heavy cataloging infrastructure. Start on Arc; add Cloud only if you need it.
17+
18+
## One framework, two managed layers
19+
20+
| Product | What it is | When you want it |
21+
| ---------------- | -------------------------------- | -------------------------------------------------------------------------------- |
22+
| **PortalJS** | Open-source framework | You want to own the code and host anywhere. Free forever, MIT licensed. |
23+
| **PortalJS Arc** | The default managed layer | You want a portal live without running infrastructure — AI-built, edge-served, in-browser querying. |
24+
| **PortalJS Cloud** | Managed backend (CKAN) | Your program needs a heavy cataloging backend. Attach it to any Arc portal — same frontend, no rebuild. |
25+
26+
### PortalJS — the framework
27+
28+
The open-source project: a lightweight Next.js + Tailwind + React template plus a set
29+
of agentic skills. Own every line, host it anywhere, pay nothing. See
30+
[Get started](/docs/quickstart) and [/opensource](/opensource).
31+
32+
### PortalJS Arc — the default managed layer
33+
34+
Zero-infra managed portals: [`/portaljs-deploy`](/docs/skills/portaljs-deploy) builds a
35+
static export and serves it from Cloudflare's edge, with in-browser querying over your
36+
data. It's the default way to run PortalJS when you don't want to manage servers. See
37+
[PortalJS Arc](/docs/arc).
38+
39+
Architecturally, Arc is the **publish / explore / share** layer that sits on top of a
40+
compute+storage backend. Its built-in zero-infra stack (object storage on R2, edge
41+
hosting, client-side DuckDB-Wasm compute) covers the self-serve and small-to-mid case
42+
with nothing to provision. When data outgrows the browser, the compute backend is
43+
pluggable behind the same catalog UX.
44+
45+
### PortalJS Cloud — the managed backend
46+
47+
A managed **CKAN** backend for programs that need heavy cataloging infrastructure. You
48+
don't start here — you *attach* it to an Arc portal when a program needs it, keeping the
49+
same frontend with no rebuild. See [Backends](/docs/backends) for how PortalJS stays
50+
decoupled from whatever catalog you run.
51+
52+
## How they compose
53+
54+
```
55+
PortalJS (open-source framework)
56+
└── run it your way:
57+
├── self-host anywhere (free)
58+
└── PortalJS Arc (managed, default)
59+
└── attach PortalJS Cloud (managed CKAN backend) — only if you need it
60+
```
61+
62+
Start on Arc. Attach a managed CKAN backend (Cloud) when your program needs one — same
63+
frontend, no rebuild. For plans and pricing, see [Pricing](/pricing).

site/pages/pricing.tsx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import Layout from '@/components/Layout'
22
import PricingPlans from '@/components/PricingPlans'
3-
import ProductLines from '@/components/ProductLines'
4-
import TcoComparison from '@/components/TcoComparison'
3+
import CostSavings from '@/components/CostSavings'
54
import AddOns from '@/components/AddOns'
65
import { generateNextSeo } from 'next-seo/pages';
76
import Head from 'next/head';
@@ -48,9 +47,17 @@ export default function Pricing() {
4847
Our plans cover all ranges of budgets and needs
4948
</p>
5049
</div>
51-
<ProductLines />
5250
<PricingPlans />
53-
<TcoComparison />
51+
<p className="mx-auto mt-8 lg:mt-24 text-center text-[15px] text-slate-600 dark:text-slate-300">
52+
Not sure which product?{' '}
53+
<Link
54+
href="/docs/products"
55+
className="text-blue-600 dark:text-blue-400 underline"
56+
>
57+
PortalJS vs Arc vs Cloud →
58+
</Link>
59+
</p>
60+
<CostSavings />
5461
</div>
5562
</div>
5663
<div className="relative" id="addons">

0 commit comments

Comments
 (0)