diff --git a/apps/site/src/app/pricing/page.tsx b/apps/site/src/app/pricing/page.tsx index 8b494527ba..763b2a4f7e 100644 --- a/apps/site/src/app/pricing/page.tsx +++ b/apps/site/src/app/pricing/page.tsx @@ -1,26 +1,11 @@ import { JsonLd } from "@/components/json-ld"; import { createFaqStructuredData } from "@/lib/structured-data"; import type { Metadata } from "next"; -import { - Accordion, - Accordions, - Badge, - Button, - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, -} from "@prisma/eclipse"; -import { comparisonSections, faqs } from "./pricing-data"; +import { Accordion, Accordions, Button } from "@prisma/eclipse"; +import { faqs } from "./pricing-data"; import { PricingPageContent } from "./pricing-page-content"; -const pricingFaqStructuredData = createFaqStructuredData( - "/pricing", - faqs, - "Prisma pricing FAQ", -); +const pricingFaqStructuredData = createFaqStructuredData("/pricing", faqs, "Prisma pricing FAQ"); export const metadata: Metadata = { title: "Pricing - Prisma Data Platform", @@ -52,87 +37,9 @@ export const metadata: Metadata = { export default function PricingPage() { return (
- + - {/* Compare plans */} -
-
-

- Compare plans -

-

- All of the features below are included with Prisma Postgres. -

-
-
- - - - - {comparisonSections[0]?.title} - - {["Free", "Starter", "Pro", "Business"].map((label) => ( - - - - ))} - - - {comparisonSections.map((section) => ( - - - - {section.title} - - - - {section.rows.map((row) => ( - - - {row[0]} - - {row.slice(1).map((value, valueIndex) => ( - - {value} - - ))} - - ))} - - ))} -
-
-
- {/* FAQ */}
@@ -190,11 +97,7 @@ export default function PricingPage() { Create your first Database - diff --git a/apps/site/src/app/pricing/pricing-calculator.tsx b/apps/site/src/app/pricing/pricing-calculator.tsx index be232474f3..e95d96eb6b 100644 --- a/apps/site/src/app/pricing/pricing-calculator.tsx +++ b/apps/site/src/app/pricing/pricing-calculator.tsx @@ -16,6 +16,8 @@ import { type Symbol, symbols, usagePricing, + convertFromUsd, + currencyConfig, } from "./pricing-data"; function cn(...classes: Array) { @@ -66,25 +68,29 @@ const PRESETS: Record< }, }; -const CALCULATOR_PLAN_ORDER = Object.keys( - usagePricing, -) as BillablePricingPlanKey[]; +const CALCULATOR_PLAN_ORDER = Object.keys(usagePricing) as BillablePricingPlanKey[]; function formatNumber(value: number) { return new Intl.NumberFormat("en-US").format(Math.round(value)); } -function formatCurrency(value: number, currency: Symbol, digits = 2) { - return `${symbols[currency]}${value.toLocaleString("en-US", { - minimumFractionDigits: digits, - maximumFractionDigits: digits, +function formatCurrency(valueUsd: number, currency: Symbol, digits = 2) { + const converted = convertFromUsd(valueUsd, currency); + const rounded = converted >= 1 ? Math.round(converted) : converted; + const effectiveDigits = converted >= 1 ? 0 : digits; + return `${symbols[currency]}${rounded.toLocaleString("en-US", { + minimumFractionDigits: effectiveDigits, + maximumFractionDigits: effectiveDigits, })}`; } -function formatCompactCurrency(value: number, currency: Symbol) { - return `${symbols[currency]}${value.toLocaleString("en-US", { - minimumFractionDigits: Number.isInteger(value) ? 0 : 1, - maximumFractionDigits: 2, +function formatCompactCurrency(valueUsd: number, currency: Symbol) { + const converted = convertFromUsd(valueUsd, currency); + const config = currencyConfig[currency]; + const maxDigits = Number.isInteger(converted) && converted > 1 ? 0 : config.microDecimals; + return `${symbols[currency]}${converted.toLocaleString("en-US", { + minimumFractionDigits: 0, + maximumFractionDigits: maxDigits, })}`; } @@ -113,7 +119,7 @@ function calculateMonthlyPlanCost( return ( details.baseMonthlyPrice + - extraOperations / 1_000 * details.operationPricePerThousand + + (extraOperations / 1_000) * details.operationPricePerThousand + extraStorageGb * details.storagePricePerGb ); } @@ -140,16 +146,11 @@ function calculatePlanBreakdown( billingCycle: BillingCycle, ): CostBreakdown { const details = usagePricing[plan]; - const billableOperations = Math.max( - 0, - databaseOperations - details.includedOperations, - ); + const billableOperations = Math.max(0, databaseOperations - details.includedOperations); const billableStorageGb = Math.max(0, storageGb - details.includedStorageGb); - const operationsCost = - billableOperations / 1_000 * details.operationPricePerThousand; + const operationsCost = (billableOperations / 1_000) * details.operationPricePerThousand; const storageCost = billableStorageGb * details.storagePricePerGb; - const yearlyMultiplier = - billingCycle === "yearly" ? 1 - details.yearlyDiscount : 1; + const yearlyMultiplier = billingCycle === "yearly" ? 1 - details.yearlyDiscount : 1; return { basePlanFee: details.baseMonthlyPrice * yearlyMultiplier, @@ -187,28 +188,16 @@ function getRecommendedPlan( }); } -function getMatchingPreset( - databaseOperations: number, - storageGb: number, -): PresetKey | null { - const match = ( - Object.entries(PRESETS) as Array<[PresetKey, (typeof PRESETS)[PresetKey]]> - ).find( +function getMatchingPreset(databaseOperations: number, storageGb: number): PresetKey | null { + const match = (Object.entries(PRESETS) as Array<[PresetKey, (typeof PRESETS)[PresetKey]]>).find( ([, preset]) => - preset.databaseOperations === databaseOperations && - preset.storageGb === storageGb, + preset.databaseOperations === databaseOperations && preset.storageGb === storageGb, ); return match?.[0] ?? null; } -function InputShell({ - children, - className, -}: { - children: React.ReactNode; - className?: string; -}) { +function InputShell({ children, className }: { children: React.ReactNode; className?: string }) { return (
)}
-

+

- First {formatNumber(planDetails.includedStorageGb)}GB of - storage are included. Remaining{" "} - {formatNumber(breakdown.billableStorageGb)}GB are billed at{" "} + First {formatNumber(planDetails.includedStorageGb)}GB of storage are included. + Remaining {formatNumber(breakdown.billableStorageGb)}GB are billed at{" "} {formatCompactCurrency(planDetails.storagePricePerGb, currency)} /GB. @@ -382,12 +368,9 @@ function SummaryCard({ } export function PricingCalculator({ currency }: { currency: Symbol }) { - const [lastAppliedPreset, setLastAppliedPreset] = - React.useState("scaleup"); - const [billingCycle, setBillingCycle] = - React.useState("monthly"); - const [expandedPlan, setExpandedPlan] = - React.useState(null); + const [lastAppliedPreset, setLastAppliedPreset] = React.useState("scaleup"); + const [billingCycle, setBillingCycle] = React.useState("monthly"); + const [expandedPlan, setExpandedPlan] = React.useState(null); const [databaseOperations, setDatabaseOperations] = React.useState( PRESETS.scaleup.databaseOperations, ); @@ -418,116 +401,116 @@ export function PricingCalculator({ currency }: { currency: Symbol }) { return (
-
-
-

- Pricing Calculator -

- -
-
- Quick Start Presets -
-
- {(Object.entries(PRESETS) as Array<[PresetKey, (typeof PRESETS)[PresetKey]]>).map( - ([key, item]) => { - const active = key === matchingPreset; - - return ( - - ); - }, - )} +
+
+

+ Pricing Calculator +

+ +
+
+ Quick Start Presets +
+
+ {(Object.entries(PRESETS) as Array<[PresetKey, (typeof PRESETS)[PresetKey]]>).map( + ([key, item]) => { + const active = key === matchingPreset; + + return ( + + ); + }, + )} +
-
-
-
-
- -

- Estimate your monthly usage -

- -
+
+
+
+ +

+ Estimate your monthly usage +

+ +
-
-
-
- - Database Operations - +
+
+
+ + Database Operations + +
+ {formatNumber(databaseOperations)} + setDatabaseOperations(value[0] ?? databaseOperations)} + />
- {formatNumber(databaseOperations)} - setDatabaseOperations(value[0] ?? databaseOperations)} - /> -
-
-
- Estimated SQL Queries - - {SQL_QUERY_MULTIPLIER}x - - +
+
+ Estimated SQL Queries + + {SQL_QUERY_MULTIPLIER}x + + +
+ {formatNumber(estimatedSqlQueries)}
- {formatNumber(estimatedSqlQueries)} -
-
-
- - Storage +
+
+ + Storage +
+ + {formatNumber(storageGb)} + + GB + + + setStorageGb(value[0] ?? storageGb)} + />
- - {formatNumber(storageGb)} - - GB - - - setStorageGb(value[0] ?? storageGb)} - /> -
-
- {/*
+
+ {/*
Compute Size
Included and auto-scaled by Prisma Postgres @@ -537,98 +520,93 @@ export function PricingCalculator({ currency }: { currency: Symbol }) {

*/} -
-
Data Transfer
-
- Unlimited included for free +
+
Data Transfer
+
+ Unlimited included for free +
+

+ Ingress, egress, sidewaysgress, it's all covered. Just Ship It. +

-

- Ingress, egress, sidewaysgress, it's all covered. Just Ship It. -

-
-
-
-
- -

- Estimated total cost -

-
+
+
+
+ +

+ Estimated total cost +

+
+ +
+ {(["monthly", "yearly"] as BillingCycle[]).map((cycle) => { + const active = cycle === billingCycle; -
- {(["monthly", "yearly"] as BillingCycle[]).map((cycle) => { - const active = cycle === billingCycle; - - return ( - - ); - })} + return ( + + ); + })} +
-
-
- {isEnterpriseRecommendation && ( - -

- Usage at this scale is best served on an enterprise plan. Reach - out to{" "} - - support@prisma.io - {" "} - for pricing. -

-
- )} - {CALCULATOR_PLAN_ORDER.map((plan) => ( - - setExpandedPlan((current) => (current === plan ? null : plan)) - } - yearly={billingCycle === "yearly"} - price={calculateDisplayedPlanCost( - plan, - databaseOperations, - storageGb, - billingCycle, - )} - /> - ))} +
+ {isEnterpriseRecommendation && ( + +

+ Usage at this scale is best served on an enterprise plan. Reach out to{" "} + + support@prisma.io + {" "} + for pricing. +

+
+ )} + {CALCULATOR_PLAN_ORDER.map((plan) => ( + setExpandedPlan((current) => (current === plan ? null : plan))} + yearly={billingCycle === "yearly"} + price={calculateDisplayedPlanCost( + plan, + databaseOperations, + storageGb, + billingCycle, + )} + /> + ))} +
-
); } diff --git a/apps/site/src/app/pricing/pricing-comparison-table.tsx b/apps/site/src/app/pricing/pricing-comparison-table.tsx new file mode 100644 index 0000000000..9f52e665f2 --- /dev/null +++ b/apps/site/src/app/pricing/pricing-comparison-table.tsx @@ -0,0 +1,88 @@ +"use client"; + +import { + Badge, + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@prisma/eclipse"; +import { type ComparisonCell, type Symbol, comparisonSections } from "./pricing-data"; + +function renderCell(cell: ComparisonCell, currency: Symbol): string { + if (typeof cell === "string") return cell; + return cell.text.replace("", cell.price[currency]); +} + +export function PricingComparisonTable({ currency }: { currency: Symbol }) { + return ( +
+ + + + + {comparisonSections[0]?.title} + + {["Free", "Starter", "Pro", "Business"].map((label) => ( + + + + ))} + + + {comparisonSections.map((section) => ( + + + + {section.title} + + + + {section.rows.map((row) => { + const label = typeof row[0] === "string" ? row[0] : row[0].text; + return ( + + + {label} + + {row.slice(1).map((cell, valueIndex) => ( + + {renderCell(cell, currency)} + + ))} + + ); + })} + + ))} +
+
+ ); +} diff --git a/apps/site/src/app/pricing/pricing-data.ts b/apps/site/src/app/pricing/pricing-data.ts index fa87098395..bf0ed81abf 100644 --- a/apps/site/src/app/pricing/pricing-data.ts +++ b/apps/site/src/app/pricing/pricing-data.ts @@ -11,17 +11,37 @@ export const symbols = { USD: "$", } as const; -export type Symbol = - | "EUR" - | "AUD" - | "INR" - | "GBP" - | "CAD" - | "BRL" - | "JPY" - | "CNY" - | "KRW" - | "USD"; +export type Symbol = "EUR" | "AUD" | "INR" | "GBP" | "CAD" | "BRL" | "JPY" | "CNY" | "KRW" | "USD"; + +export const exchangeRates: Record = { + USD: 1, + EUR: 0.93, + GBP: 0.8, + AUD: 1.54, + CAD: 1.36, + INR: 83.2, + BRL: 5.4, + JPY: 157.5, + CNY: 7.2, + KRW: 1370, +}; + +export const currencyConfig: Record = { + USD: { decimals: 2, microDecimals: 4 }, + EUR: { decimals: 2, microDecimals: 4 }, + GBP: { decimals: 2, microDecimals: 4 }, + AUD: { decimals: 2, microDecimals: 4 }, + CAD: { decimals: 2, microDecimals: 4 }, + INR: { decimals: 0, microDecimals: 2 }, + BRL: { decimals: 2, microDecimals: 4 }, + JPY: { decimals: 0, microDecimals: 2 }, + CNY: { decimals: 2, microDecimals: 4 }, + KRW: { decimals: 0, microDecimals: 2 }, +}; + +export function convertFromUsd(amountUsd: number, currency: Symbol): number { + return amountUsd * exchangeRates[currency]; +} export type CurrencyMap = Record; @@ -30,7 +50,7 @@ export type PlanPoint = | { text: string; price: CurrencyMap; - } + }; export type PricingPlan = { title: string; @@ -48,16 +68,23 @@ export type UsagePricing = { yearlyDiscount: number; }; -/** Formats a single numeric amount with every supported currency symbol. */ -export function formatAmountForAllCurrencies( - amount: number, - digits: number, -): CurrencyMap { +export function formatAmountForAllCurrencies(amountUsd: number, digits: number): CurrencyMap { return Object.fromEntries( - Object.entries(symbols).map(([code, symbol]) => [ - code, - `${symbol}${amount.toFixed(digits)}`, - ]), + Object.entries(symbols).map(([code, symbol]) => { + const typedCode = code as Symbol; + const converted = convertFromUsd(amountUsd, typedCode); + const config = currencyConfig[typedCode]; + const isMicroPrice = digits > config.decimals; + const effectiveDigits = isMicroPrice ? config.microDecimals : digits; + const displayValue = isMicroPrice ? converted : Math.round(converted); + return [ + code, + `${symbol}${displayValue.toLocaleString("en-US", { + minimumFractionDigits: effectiveDigits, + maximumFractionDigits: effectiveDigits, + })}`, + ]; + }), ) as CurrencyMap; } @@ -173,7 +200,12 @@ export const usagePricing: Record = { }, }; -export const comparisonSections = [ +export type ComparisonCell = string | { text: string; price: CurrencyMap }; + +export const comparisonSections: Array<{ + title: string; + rows: ComparisonCell[][]; +}> = [ { title: "Managed Connection Pool", rows: [ @@ -189,15 +221,25 @@ export const comparisonSections = [ { title: "Global Cache", rows: [ - ["Cache tag invalidations", "-", "-", "$0.002 per 1,000, max 10,000 per day", "$0.001 per 1,000, max 100,000 per day"], + [ + "Cache tag invalidations", + "-", + "-", + { + text: " per 1,000, max 10,000 per day", + price: formatAmountForAllCurrencies(0.002, 3), + }, + { + text: " per 1,000, max 100,000 per day", + price: formatAmountForAllCurrencies(0.001, 3), + }, + ], ["Cache purge requests", "5 per hour", "5 per hour", "10 per hour", "20 per hour"], ], }, { title: "Database optimizations", - rows: [ - ["Query insights", "✓", "✓", "✓", "✓"], - ], + rows: [["Query insights", "✓", "✓", "✓", "✓"]], }, { title: "Data management", @@ -210,18 +252,18 @@ export const comparisonSections = [ ["Compliance", "GDPR", "GDPR", "GDPR / HIPAA", "GDPR / HIPAA / SOC2 / ISO:27001"], ], }, -] as const; +]; export const faqs: Array<{ question: string; answer: string }> = [ { question: "What is an operation?", answer: - "

Each action you perform, whether it’s a create, read, update, or delete query against your Prisma Postgres database counts as a single operation. Even if Prisma issues multiple database queries behind the scenes to fulfill your request, it’s still billed as one operation.

By treating simple lookups and complex queries the same, you can directly correlate your database usage and costs with your product usage and user behavior. There’s no need to track write-heavy workloads or worry about bandwidth per operation: each of them is counted and billed the same, making your usage and budgeting simple and straightforward. You can learn more about our operations-based pricing model in our blog post.

", + '

Each action you perform, whether it’s a create, read, update, or delete query against your Prisma Postgres database counts as a single operation. Even if Prisma issues multiple database queries behind the scenes to fulfill your request, it’s still billed as one operation.

By treating simple lookups and complex queries the same, you can directly correlate your database usage and costs with your product usage and user behavior. There’s no need to track write-heavy workloads or worry about bandwidth per operation: each of them is counted and billed the same, making your usage and budgeting simple and straightforward. You can learn more about our operations-based pricing model in our blog post.

', }, { question: "How many operations do I need for my project?", answer: - "

While the answer to this question will vary from project to project, there are a couple of ways to get an idea of what you will need:

  • If you already have a database with another provider, you can often look in their dashboard to see your current usage. The number of queries will be a good hint to the approximate number of operations you’ll use.
  • If you already use the Prisma ORM, you can enable the metrics feature to begin tracking your usage, which is an easy and accurate way to see your current usage.
  • If you’re starting a new project, we encourage you to just get started and see how many queries you typically use. We offer a free plan with 100,000 operations per month, meaning you can confidently get started without paying anything. From our experience, 100,000 operations per month is more than enough to get started with a project and serve your first users.

You can find an example calculation for a medium-sized workload in our blog post about our operations-based pricing model.

", + '

While the answer to this question will vary from project to project, there are a couple of ways to get an idea of what you will need:

  • If you already have a database with another provider, you can often look in their dashboard to see your current usage. The number of queries will be a good hint to the approximate number of operations you’ll use.
  • If you already use the Prisma ORM, you can enable the metrics feature to begin tracking your usage, which is an easy and accurate way to see your current usage.
  • If you’re starting a new project, we encourage you to just get started and see how many queries you typically use. We offer a free plan with 100,000 operations per month, meaning you can confidently get started without paying anything. From our experience, 100,000 operations per month is more than enough to get started with a project and serve your first users.

You can find an example calculation for a medium-sized workload in our blog post about our operations-based pricing model.

', }, { question: "Can I use Prisma Postgres for free?", @@ -241,12 +283,12 @@ export const faqs: Array<{ question: string; answer: string }> = [ { question: "What’s the difference between usage pricing and traditional database pricing?", answer: - "

Traditional pricing is where you choose a fixed database size and price, and the amount you pay is generally predictable. But that comes at the expense of flexibility, meaning it’s much harder to scale up and down with your application’s demands. This is usually fine for a small test database, but for production workloads, it can be burdensome: If you have low-traffic periods, and high-traffic periods (most production apps do) then you either under-provision and risk having downtime in busy periods, or you over-provision and pay a lot more for your database.

With usage pricing, you only pay for what you need, when you need it. If your app has a quiet period, you’ll pay less. If things get busy, we can simply scale up to handle it for you. Prisma Postgres comes with budget controls, so you can always stay in control of your spending, while taking advantage of the flexibility. You can learn more on why operations-based pricing is better in our blog post.

", + '

Traditional pricing is where you choose a fixed database size and price, and the amount you pay is generally predictable. But that comes at the expense of flexibility, meaning it’s much harder to scale up and down with your application’s demands. This is usually fine for a small test database, but for production workloads, it can be burdensome: If you have low-traffic periods, and high-traffic periods (most production apps do) then you either under-provision and risk having downtime in busy periods, or you over-provision and pay a lot more for your database.

With usage pricing, you only pay for what you need, when you need it. If your app has a quiet period, you’ll pay less. If things get busy, we can simply scale up to handle it for you. Prisma Postgres comes with budget controls, so you can always stay in control of your spending, while taking advantage of the flexibility. You can learn more on why operations-based pricing is better in our blog post.

', }, { question: "How is Prisma’s pricing different to others?", answer: - "

Prisma’s pricing is designed to provide maximum flexibility to developers, while aiming to be as intuitive as possible.

We charge primarily by operation, which is counted each time you invoke the Prisma ORM client to create, read, update or delete a record. Additionally we also charge for storage. All with a very generous free threshold each month.

We don’t charge by data transfer (bandwidth) or by compute/memory hours, simply because we felt that these metrics are more difficult to grasp as a developer.

We created a pricing model to more closely match how you use your database as a developer, not how the infrastructure works. You can learn more about our approach to an operations-based database pricing model in this blog post.

", + '

Prisma’s pricing is designed to provide maximum flexibility to developers, while aiming to be as intuitive as possible.

We charge primarily by operation, which is counted each time you invoke the Prisma ORM client to create, read, update or delete a record. Additionally we also charge for storage. All with a very generous free threshold each month.

We don’t charge by data transfer (bandwidth) or by compute/memory hours, simply because we felt that these metrics are more difficult to grasp as a developer.

We created a pricing model to more closely match how you use your database as a developer, not how the infrastructure works. You can learn more about our approach to an operations-based database pricing model in this blog post.

', }, { question: "How can I compare Prisma pricing to other providers?", @@ -261,11 +303,11 @@ export const faqs: Array<{ question: string; answer: string }> = [ { question: "I'm an early stage startup, do you offer any discounts?", answer: - "

Building a startup is hard. Prisma helps you stay laser-focused on what matters the most, which is building features and winning users.

We offer $10k in credits to eligible startups. Learn more at prisma.io/startups.

", + '

Building a startup is hard. Prisma helps you stay laser-focused on what matters the most, which is building features and winning users.

We offer $10k in credits to eligible startups. Learn more at prisma.io/startups.

', }, { question: "How do I upgrade my plan if I am using Prisma Postgres via Vercel?", answer: - "

If you're using Prisma Postgres via Vercel, your billing is handled directly by Vercel. To upgrade your plan, you'll need to do so in the Vercel Dashboard. The instructions are available in our docs.

", + '

If you\'re using Prisma Postgres via Vercel, your billing is handled directly by Vercel. To upgrade your plan, you\'ll need to do so in the Vercel Dashboard. The instructions are available in our docs.

', }, ]; diff --git a/apps/site/src/app/pricing/pricing-hero-plans.tsx b/apps/site/src/app/pricing/pricing-hero-plans.tsx index 4517a2d7fe..50aa7ebf45 100644 --- a/apps/site/src/app/pricing/pricing-hero-plans.tsx +++ b/apps/site/src/app/pricing/pricing-hero-plans.tsx @@ -63,10 +63,7 @@ export function PricingHeroPlans({
- onCurrencyChange(value as Symbol)}> @@ -89,7 +86,7 @@ export function PricingHeroPlans({ key={planKey} className={`relative rounded-2xl border ${ highlighted - ? "border-stroke-ppg" + ? "border-stroke-ppg mt-4 md:mt-0" : "border-stroke-neutral-weak" } bg-background-default p-5 text-foreground-neutral shadow-[0px_18px_42px_0px_rgba(23,43,77,0.08)]`} > @@ -125,15 +122,10 @@ export function PricingHeroPlans({ )}
-

- {plan.subtitle} -

+

{plan.subtitle}

{plan.price[currency]} - - {" "} - / month - + / month

diff --git a/apps/site/src/app/pricing/pricing-page-content.tsx b/apps/site/src/app/pricing/pricing-page-content.tsx index 8d9103deee..72e038dc6f 100644 --- a/apps/site/src/app/pricing/pricing-page-content.tsx +++ b/apps/site/src/app/pricing/pricing-page-content.tsx @@ -3,6 +3,7 @@ import * as React from "react"; import type { Symbol } from "./pricing-data"; import { PricingCalculator } from "./pricing-calculator"; +import { PricingComparisonTable } from "./pricing-comparison-table"; import { PricingHeroPlans } from "./pricing-hero-plans"; export function PricingPageContent() { @@ -15,6 +16,18 @@ export function PricingPageContent() {
+ +
+
+

+ Compare plans +

+

+ All of the features below are included with Prisma Postgres. +

+
+ +
); } diff --git a/packages/ui/src/data/footer.ts b/packages/ui/src/data/footer.ts index 0a640e6ece..8702219a5a 100644 --- a/packages/ui/src/data/footer.ts +++ b/packages/ui/src/data/footer.ts @@ -14,11 +14,10 @@ const footerItems = [ url: "/studio", _type: "footerLinkType", }, - { - title: "Optimize", - url: "/optimize", +{ + title: "Accelerate", + url: "/accelerate", _type: "footerLinkType", - //tag: "Early Access" }, { _type: "footerLinkType", @@ -188,13 +187,8 @@ const shareSocials = [ { label: "LinkedIn", icon: "fa-brands fa-square-linkedin", - url: ({ - current_page, - text_data, - }: { - current_page: string; - text_data: string; - }) => `https://www.linkedin.com/sharing/share-offsite/?url=${current_page}`, + url: ({ current_page, text_data }: { current_page: string; text_data: string }) => + `https://www.linkedin.com/sharing/share-offsite/?url=${current_page}`, }, { label: "X", @@ -215,13 +209,8 @@ const shareSocials = [ { label: "Bluesky", icon: "fa-brands fa-bluesky", - url: ({ - current_page, - text_data, - }: { - current_page: string; - text_data: string; - }) => `https://bsky.app/intent/compose?text=${text_data}${current_page}`, + url: ({ current_page, text_data }: { current_page: string; text_data: string }) => + `https://bsky.app/intent/compose?text=${text_data}${current_page}`, }, { label: "Copy link", icon: "fa-solid fa-link", copy: true }, ];