diff --git a/apps/docs/public/sitemap.xml b/apps/docs/public/sitemap.xml index 90cd255fc9c..35bf4d7ff55 100644 --- a/apps/docs/public/sitemap.xml +++ b/apps/docs/public/sitemap.xml @@ -3867,4 +3867,4 @@ weekly 0.5 - + \ No newline at end of file diff --git a/apps/www/components/AuthWidget/AuthWidgetSection.tsx b/apps/www/components/AuthWidget/AuthWidgetSection.tsx index 275786e644f..f9ee1bbf25a 100644 --- a/apps/www/components/AuthWidget/AuthWidgetSection.tsx +++ b/apps/www/components/AuthWidget/AuthWidgetSection.tsx @@ -7,7 +7,7 @@ import Image from 'next/image' import { ColorSwatchIcon, MenuIcon } from '@heroicons/react/outline' import { Auth, ThemeSupa } from '@supabase/auth-ui-react' -import { useTheme } from '../Providers' +import { useTheme } from 'common/Providers' const supabase = createClient( 'https://rsnibhkhsbfnncjmwnkj.supabase.co', diff --git a/apps/www/components/DarkModeToggle.tsx b/apps/www/components/DarkModeToggle.tsx index c3a1b0f946f..789bdd7a5a4 100644 --- a/apps/www/components/DarkModeToggle.tsx +++ b/apps/www/components/DarkModeToggle.tsx @@ -1,4 +1,4 @@ -import { useTheme } from '~/components/Providers' +import { useTheme } from 'common/Providers' import { IconSun, IconMoon } from 'ui' function DarkModeToggle() { diff --git a/apps/www/components/Footer/index.tsx b/apps/www/components/Footer/index.tsx index e4fb2ee81f5..bcc49c7bcc9 100644 --- a/apps/www/components/Footer/index.tsx +++ b/apps/www/components/Footer/index.tsx @@ -2,7 +2,7 @@ import FooterLinks from 'data/Footer.json' import SectionContainer from '../Layouts/SectionContainer' import DarkModeToggle from '../DarkModeToggle' import Link from 'next/link' -import { useTheme } from '../Providers' +import { useTheme } from 'common/Providers' import { Badge } from 'ui' import Image from 'next/image' import * as supabaseLogoWordmarkDark from 'common/assets/images/supabase-logo-wordmark--dark.png' diff --git a/apps/www/components/Globe.tsx b/apps/www/components/Globe.tsx index 388c6a3d65d..49470073455 100644 --- a/apps/www/components/Globe.tsx +++ b/apps/www/components/Globe.tsx @@ -1,6 +1,6 @@ import createGlobe from 'cobe' import { useEffect, useRef } from 'react' -import { useTheme } from './Providers/index' +import { useTheme } from 'common/Providers' const Globe = () => { const { isDarkMode } = useTheme() diff --git a/apps/www/components/Nav/index.tsx b/apps/www/components/Nav/index.tsx index 387aefacc5d..98782862c93 100644 --- a/apps/www/components/Nav/index.tsx +++ b/apps/www/components/Nav/index.tsx @@ -11,7 +11,7 @@ import Solutions from '~/components/Nav/Product' import Developers from '~/components/Nav/Developers' import Announcement from '~/components/Nav/Announcement' -import { useTheme } from '~/components/Providers' +import { useTheme } from 'common/Providers' import TextLink from '../TextLink' import Image from 'next/image' import * as supabaseLogoWordmarkDark from 'common/assets/images/supabase-logo-wordmark--dark.png' diff --git a/apps/www/components/Pricing/ComputePricingModal.tsx b/apps/www/components/Pricing/ComputePricingModal.tsx new file mode 100644 index 00000000000..526590addf1 --- /dev/null +++ b/apps/www/components/Pricing/ComputePricingModal.tsx @@ -0,0 +1,151 @@ +import React, { Fragment, useMemo } from 'react' +import { useRouter } from 'next/router' +import { useTheme } from 'common/Providers' +import { IconCheckCircle, IconXCircle, Modal } from 'ui' +import pricingAddOn from '~/data/PricingAddOnTable.json' +import { IconPricingIncludedCheck, IconPricingMinus } from './PricingIcons' + +interface Props { + showComputeModal: boolean + setShowComputeModal: React.Dispatch> +} + +export default function ComputePricingModal({ showComputeModal, setShowComputeModal }: Props) { + const { basePath } = useRouter() + const { isDarkMode } = useTheme() + const columnNames = useMemo( + () => + pricingAddOn.database.rows.map((row) => + row.columns.map((column) => ({ key: column.key, title: column.title })) + )[0], + [] + ) + + return ( + setVideoVisible(false)} + hideFooter + header={ +
+ Compute pricing + setShowComputeModal(false)} + /> +
+ } + > +
+
+
+
+
+
+ +
+
+
+

Choose best compute setup for you

+

+ Every project on the Supabase Platform comes with its own dedicated Postgres + instance running inside a virtual machine (VM). The following table describes the + base instance with additional compute add-ons available if you need extra + performance when scaling up Supabase. +

+
+
+
+
+ + + + {columnNames.map((column) => ( + + ))} + + + + {pricingAddOn.database.rows.map((row, i) => ( + + {i === 0 && ( + + + + )} + + {row.columns.map((column) => ( + + ))} + + + ))} + +
+ {column.title} +
+ Included in Free and Pro tiers +
+ {column.key === 'dedicated' ? ( + column.value ? ( + + ) : ( + + ) + ) : ( + column.value + )} +
+
+ + + + {pricingAddOn.database.rows.map((row, i) => ( + + {row.columns.map((column) => ( + + + + + ))} + + ))} + +
+ {column.title} + + {column.key === 'dedicated' ? ( + + ) : ( + column.value + )} +
+
+
+
+ ) +} diff --git a/apps/www/components/PricingAddOnTable.tsx b/apps/www/components/Pricing/PricingAddOnTable.tsx similarity index 99% rename from apps/www/components/PricingAddOnTable.tsx rename to apps/www/components/Pricing/PricingAddOnTable.tsx index dbd7ccf7562..41b9f96698b 100644 --- a/apps/www/components/PricingAddOnTable.tsx +++ b/apps/www/components/Pricing/PricingAddOnTable.tsx @@ -1,7 +1,7 @@ import { Collapsible, IconChevronUp } from 'ui' import classNames from 'classnames' import { Fragment, useMemo, useState } from 'react' -import { Check } from './PricingTableRow' +import { Check } from './PricingIcons' interface PricingAddOnTableProps { pricing: { diff --git a/apps/www/components/Pricing/PricingIcons.tsx b/apps/www/components/Pricing/PricingIcons.tsx new file mode 100644 index 00000000000..5dd4c804921 --- /dev/null +++ b/apps/www/components/Pricing/PricingIcons.tsx @@ -0,0 +1,57 @@ +export const Check = () => ( + + + +) + +export const IconPricingIncludedCheck = (props: any) => ( + + + Included in {props.tier} + +) + +export const IconPricingMinus = (props: any) => ( + <> + + + + Not included in {props.tier} + +) + +export const IconPricingInfo = () => ( + <> + + + + Info + +) diff --git a/apps/www/components/Pricing/PricingTableRow.tsx b/apps/www/components/Pricing/PricingTableRow.tsx new file mode 100644 index 00000000000..3aaacc55236 --- /dev/null +++ b/apps/www/components/Pricing/PricingTableRow.tsx @@ -0,0 +1,149 @@ +import { IconHelpCircle } from 'ui' +import ProductIcon from 'components/ProductIcon' +import React, { Fragment } from 'react' +import ReactTooltip from 'react-tooltip' +import { IconPricingIncludedCheck, IconPricingInfo, IconPricingMinus } from './PricingIcons' + +export const PricingTableRowDesktop = (props: any) => { + const category = props.category + + return ( + <> + + +
+ {props.icon && } +

{category.title}

+
+ + + + + + + + {category.features.map((feat: any, i: number) => { + return ( + + + + {feat.title} + {feat.tooltips?.main && ( + + + + )} + + + {Object.entries(feat.tiers).map((entry: any, i) => { + const tierName = entry[0] + const tierValue = entry[1] + + return ( + + {typeof tierValue === 'boolean' && tierValue === true ? ( + + ) : typeof tierValue === 'boolean' && tierValue === false ? ( +
+ +
+ ) : ( + + {feat.tooltips?.[tierName] && ( + + + + )} + {tierValue} + + )} + + ) + })} + + {i === category.features.length - 1 && ( +
+ )} +
+ ) + })} + + + ) +} + +export const PricingTableRowMobile = (props: any) => { + const category = props.category + const tier = props.tier + + return ( + <> + + + + + + + + + + {category.features.map((feat: any, i: number) => { + return ( + + + + + ) + })} + +
+
+ {category.icon ? : null} + {category.title} +
+
+ Feature + + Included +
+ +

{feat.title}

+
+
+ {typeof feat.tiers[tier] === 'boolean' && feat.tiers[tier] === true ? ( +
+ +
+ ) : typeof feat.tiers[tier] === 'boolean' && feat.tiers[tier] === false ? ( +
+ +
+ ) : ( + {feat.tiers[tier]} + )} +
+ + + ) +} diff --git a/apps/www/components/PricingTableRow.tsx b/apps/www/components/PricingTableRow.tsx deleted file mode 100644 index 2a81769258b..00000000000 --- a/apps/www/components/PricingTableRow.tsx +++ /dev/null @@ -1,164 +0,0 @@ -import { IconHelpCircle } from 'ui' -import ProductIcon from 'components/ProductIcon' -import React from 'react' -import ReactTooltip from 'react-tooltip' - -export const Check = () => ( - - - -) - -const IncludedCheck = (props: any) => ( - <> - - Included in {props.tier} - -) - -const Minus = (props: any) => ( - <> - - Not included in {props.tier} - -) - -export const PricingTableRowDesktop = (props: any) => { - const category = props.category - - return ( - <> - - -
- {props.icon && } -

{category.title}

-
- - - - - - - {category.features.map((feat: any, i: number) => { - return ( - - - {feat.title} - {feat.tooltip && ( - - - - )} - - - {Object.values(feat.tiers).map((tier: any, i) => { - return ( - - {typeof tier === 'boolean' && tier === true ? ( - - ) : typeof tier === 'boolean' && tier === false ? ( -
- -
- ) : ( - {tier} - )} - - ) - })} - - ) - })} - - - ) -} - -export const PricingTableRowMobile = (props: any) => { - const category = props.category - const tier = props.tier - - return ( - <> - - - - - - - - - - {category.features.map((feat: any, i: number) => { - return ( - - - - - ) - })} - -
-
- {category.icon ? : null} - {category.title} -
-
- Feature - - Included -
- -

{feat.title}

-
-
- {typeof feat.tiers[tier] === 'boolean' && feat.tiers[tier] === true ? ( -
- -
- ) : typeof feat.tiers[tier] === 'boolean' && feat.tiers[tier] === false ? ( -
- -
- ) : ( - {feat.tiers[tier]} - )} -
- - - ) -} diff --git a/apps/www/components/ProductIcon.tsx b/apps/www/components/ProductIcon.tsx index d7a24709787..894c7ea5117 100644 --- a/apps/www/components/ProductIcon.tsx +++ b/apps/www/components/ProductIcon.tsx @@ -1,12 +1,22 @@ interface ProductIcon { icon: string + color?: 'black' | 'green' } -function ProductIcon({ icon }: ProductIcon) { +function ProductIcon({ icon, color }: ProductIcon) { return ( -
+
void -} - -interface ThemeProviderProps { - children?: any -} - -export const ThemeContext = createContext({ - isDarkMode: true, - toggleTheme: () => {}, -}) - -export const useTheme = () => useContext(ThemeContext) - -export const ThemeProvider = ({ children }: ThemeProviderProps) => { - const [isDarkMode, setIsDarkMode] = useState(false) - - useEffect(() => { - const key = localStorage.getItem('supabaseDarkMode') - // Default to dark mode if no preference config - setIsDarkMode(!key || key === 'true') - }, []) - - const toggleTheme = () => { - setIsDarkMode(!isDarkMode) - } - - return ( - <> - - {children} - - - ) -} diff --git a/apps/www/data/Pricing.json b/apps/www/data/Pricing.json index 08a9cdba95d..395c309cb9f 100644 --- a/apps/www/data/Pricing.json +++ b/apps/www/data/Pricing.json @@ -5,7 +5,9 @@ "features": [ { "title": "Dedicated Postgres Database", - "tooltip": "A Postgres database with no restrictions? You get it. No pseudo limited users, you are the postgres root user. No caveats.", + "tooltips": { + "main": "A Postgres database with no restrictions? You get it. No pseudo limited users, you are the postgres root user. No caveats." + }, "tiers": { "free": true, "pro": true, @@ -22,46 +24,60 @@ }, { "title": "Database size", - "tooltip": "Billing is based on the average daily database size in GB throughout the billing period.", + "tooltips": { + "main": "Billing is based on the average database size in GB throughout the billing period.", + "pro": "8 GB included, then $0.125 per GB" + }, "tiers": { - "free": "Up to 500 MB", - "pro": "8 GB included, then $0.125 per GB", + "free": "500 MB", + "pro": "8 GB", "enterprise": "Unlimited" } }, { "title": "Automatic backups", - "tooltip": "Backups are entire copies of your database that can be restored in the future.", + "tooltips": { + "main": "Backups are entire copies of your database that can be restored in the future.", + "pro": "7 days of backup (if > 1TB, contact for Enterprise pricing)" + }, "tiers": { "free": false, - "pro": "7 days of backup (if > 1TB, contact enterprise)", + "pro": "7 days", "enterprise": "Custom" } }, { "title": "Point in time recovery", - "tooltip": "PITR cannot be applied retroactively, projects can only be rolled back to the point from which PITR has been applied.", + "tooltips": { + "main": "PITR cannot be applied retroactively, projects can only be rolled back to the point from which PITR has been applied.", + "pro": "$100 per 7 days. If > 28 day rollback period, contact enterprise" + }, "tiers": { "free": false, - "pro": "$100 per 7 day rollback period (if > 28 days, contact enterprise)", + "pro": "$100 per 7 days", "enterprise": true } }, { "title": "Pausing", - "tooltip": "Projects that have no activity or API requests will be paused. They can be reactivated via the dashboard", + "tooltips": { + "main": "Projects that have no activity or API requests will be paused. They can be reactivated via the dashboard" + }, "tiers": { - "free": "Paused after 1 week inactivity", + "free": "After 1 inactive week", "pro": "Never", "enterprise": "Never" } }, { "title": "Database egress", - "tooltip": "Billing is based on the total sum of outgoing traffic of your database in GB throughout your billing period.", + "tooltips": { + "main": "Billing is based on the total sum of outgoing traffic of your database in GB throughout your billing period. Only download operations are counted towards the limit", + "pro": "50GB included per month, then $0.09 per GB" + }, "tiers": { - "free": "Up to 2GB", - "pro": "50GB included per month, then $0.09 per GB", + "free": "2GB", + "pro": "50GB", "enterprise": "Unlimited" } } @@ -73,7 +89,7 @@ "features": [ { "title": "Total Users", - "tooltip": "The maximum number of users your project can have", + "tooltips": { "main": "The maximum number of users your project can have" }, "tiers": { "free": "Unlimited", "pro": "Unlimited", @@ -82,10 +98,13 @@ }, { "title": "MAUs", - "tooltip": "Distinct users requesting your API throughout the billing period.", + "tooltips": { + "main": "Distinct users requesting your API throughout the billing period.", + "pro": "100,000 included, then $0.00325 per MAU" + }, "tiers": { - "free": "Up to 50,000 MAUs", - "pro": "100,000 included, then $0.00325 per MAU", + "free": "50,000", + "pro": "100,000", "enterprise": "Unlimited" } }, @@ -131,7 +150,7 @@ }, { "title": "Supabase Auth emails", - "tooltip": "Rate limits do not apply to Custom SMTP", + "tooltips": { "main": "Rate limits do not apply to Custom SMTP" }, "tiers": { "free": "30 / hour", "pro": "100 / hour", @@ -151,22 +170,29 @@ "storage": { "title": "Storage", "icon": "M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4", + "features": [ { "title": "Storage", - "tooltip": "The sum of all objects' size in your storage buckets.", - "tiers": { - "free": "Up to 1 GB", + "tooltips": { "pro": "100 GB included, then $0.021 per GB", + "main": "The sum of all objects' size in your storage buckets." + }, + "tiers": { + "free": "1 GB", + "pro": "100 GB", "enterprise": "Unlimited" } }, { "title": "Storage egress", - "tooltip": "Total sum of outgoing traffic (egress) from your storage buckets, only download operations are counted.", + "tooltips": { + "main": "Total sum of outgoing traffic (egress) from your storage buckets, only download operations are counted.", + "pro": "200 GB included, then $0.09 per GB" + }, "tiers": { - "free": "Up to 2 GB", - "pro": "200 GB included, then $0.09 per GB", + "free": "2 GB", + "pro": "200 GB", "enterprise": "Unlimited" } }, @@ -180,20 +206,22 @@ }, { "title": "Max file upload size", - "tooltip": "You can change the upload size in the dashboard", + "tooltips": { "main": "You can change the upload size in the dashboard" }, "tiers": { - "free": "Up to 50MB", - "pro": "Up to 5GB", + "free": "50MB", + "pro": "5GB", "enterprise": "Unlimited" } }, { "title": "Asset transformations", - "tooltip": "Distinct count of all images that were transformed in the billing period, ignoring any transformations.", + "tooltips": { + "main": "Distinct count of all images that were transformed in the billing period, ignoring any transformations.", + "pro": "Unlimited for 100 origin images. $5 per 1000 origin images after the first 100" + }, "tiers": { "free": false, - "pro": "Unlimited transformations for 100 origin images, then $5 per 1000 origin images", - "enterprise": "Unlimited" + "pro": "Unlimited for 100 origin images" } } ] @@ -204,27 +232,34 @@ "features": [ { "title": "Invocations", - "tooltip": "Billing is based on the sum of all invocations, independent of response status, throughout your billing period.", + "tooltips": { + "main": "Billing is based on the sum of all invocations, independent of response status, throughout your billing period.", + "pro": "2 Million per month, then $2 per 1 million invocations" + }, + "main": "Billing is based on the sum of all invocations, independent of response status, throughout your billing period.", "tiers": { - "free": "500K per month", - "pro": "2 Million per month, then $2 per 1 million invocations", + "free": "500K/month", + "pro": "2 Million/month", "enterprise": "Unlimited" } }, { "title": "Script size", "tiers": { - "free": "2 mb", - "pro": "10 mb", + "free": "2 MB", + "pro": "10 MB", "enterprise": "Unlimited" } }, { "title": "Number of functions", - "tooltip": "Billing is based on the maximum amount of functions at any point in time throughout your billing period.", + "tooltips": { + "main": "Billing is based on the maximum amount of functions at any point in time throughout your billing period.", + "pro": "100, then $10 per additional 100 functions" + }, "tiers": { "free": "10", - "pro": "100, then $10 per additional 100 functions", + "pro": "100", "enterprise": "Unlimited" } } @@ -244,27 +279,34 @@ }, { "title": "Concurrent Peak Connections", - "tooltip": "We only charge for successful connections - not connection attempts!", + "tooltips": { + "main": "We only charge for successful connections - not connection attempts!", + "pro": "Up to 500, then $10 per 1000" + }, "tiers": { - "free": "Up to 200", - "pro": "Up to 500, then $10 per 1000", + "free": "200", + "pro": "500", "enterprise": "Unlimited concurrent connections and volume discount" } }, { "title": "Messages Per Month", - "tooltip": "Billing is based on the total sum of Realtime messages throughout your billing period.", - "tiers": { + "tooltips": { + "main": "Billing is based on the total sum of Realtime messages throughout your billing period.", "free": "2 Million (including database)", - "pro": "5 Million, then $2.50 per million", + "pro": "5 Million, then $2.50 per million" + }, + "tiers": { + "free": "2 Million", + "pro": "5 Million", "enterprise": "Volume discounts on messages" } }, { "title": "Max Message Size", "tiers": { - "free": "250 Kb", - "pro": "3 Mb", + "free": "250 KB", + "pro": "3 MB", "enterprise": "Custom" } } @@ -378,10 +420,13 @@ }, { "title": "Custom Domains", + "tooltips": { + "enterprise": "Volume discounts available." + }, "tiers": { "free": false, "pro": "$10 per domain per month per project add on", - "enterprise": "1 included, additional custom domains $10 per custom domain per month. Volume discounts available." + "enterprise": "1 included, additional $10/domain/month" } } ] diff --git a/apps/www/data/PricingAddOnTable.json b/apps/www/data/PricingAddOnTable.json new file mode 100644 index 00000000000..e20da275960 --- /dev/null +++ b/apps/www/data/PricingAddOnTable.json @@ -0,0 +1,360 @@ +{ + "database": { + "title": "Optimized Compute", + "features": [ + "For projects that need dedicated compute", + "For scaling number of connections", + "Additional CPU & RAM options", + "Additional Disk IO Bandwidth" + ], + "rows": [ + { + "columns": [ + { "key": "plan", "title": "Plan", "value": "Starter" }, + { "key": "pricing", "title": "Pricing", "value": "$0" }, + { "key": "cpu", "title": "CPU", "value": "2-core ARM" }, + { "key": "dedicated", "title": "Dedicated", "value": false }, + { "key": "memory", "title": "Memory", "value": "1 GB" }, + { "key": "maxDiskIO", "title": "Disk IO Bandwidth up to", "value": "2,606 Mbps" }, + { + "key": "baseDiskIO", + "title": "Baseline Disk IO Bandwidth", + "value": "87 Mbps" + }, + { + "key": "directConnections", + "title": "Connections: Direct", + "value": "10" + }, + { + "key": "poolerConnections", + "title": "Connections: Pooler", + "value": "50" + } + ] + }, + { + "columns": [ + { "key": "plan", "title": "Plan", "value": "Small" }, + { "key": "pricing", "title": "Pricing", "value": "$5" }, + { "key": "cpu", "title": "CPU", "value": "2-core ARM" }, + { "key": "dedicated", "title": "Dedicated", "value": false }, + { "key": "memory", "title": "Memory", "value": "2 GB" }, + { "key": "maxDiskIO", "title": "Maximum Disk IO Bandwidth", "value": "2,606 Mbps" }, + { + "key": "baseDiskIO", + "title": "Baseline Disk IO Bandwidth", + "value": "174 Mbps" + }, + { + "key": "directConnections", + "title": "Connections: Direct (recommended)", + "value": "30" + }, + { + "key": "poolerConnections", + "title": "Connections: Pooler (recommended)", + "value": "75" + } + ] + }, + { + "columns": [ + { "key": "plan", "title": "Plan", "value": "Medium" }, + { "key": "pricing", "title": "Pricing", "value": "$50" }, + { "key": "cpu", "title": "CPU", "value": "2-core ARM" }, + { "key": "dedicated", "title": "Dedicated", "value": false }, + { "key": "memory", "title": "Memory", "value": "4 GB" }, + { "key": "maxDiskIO", "title": "Maximum Disk IO Bandwidth", "value": "2,606 Mbps" }, + { + "key": "baseDiskIO", + "title": "Baseline Disk IO Bandwidth", + "value": "347 Mbps" + }, + { + "key": "directConnections", + "title": "Connections: Direct (recommended)", + "value": "50" + }, + { + "key": "poolerConnections", + "title": "Connections: Pooler (recommended)", + "value": "150" + } + ] + }, + { + "columns": [ + { "key": "plan", "title": "Plan", "value": "Large" }, + { "key": "pricing", "title": "Pricing", "value": "$100" }, + { "key": "cpu", "title": "CPU", "value": "2-core ARM" }, + { "key": "dedicated", "title": "Dedicated", "value": true }, + { "key": "memory", "title": "Memory", "value": "8 GB" }, + { "key": "maxDiskIO", "title": "Maximum Disk IO Bandwidth", "value": "4,750 Mbps" }, + { + "key": "baseDiskIO", + "title": "Baseline Disk IO Bandwidth", + "value": "630 Mbps" + }, + { + "key": "directConnections", + "title": "Connections: Direct (recommended)", + "value": "100" + }, + { + "key": "poolerConnections", + "title": "Connections: Pooler (recommended)", + "value": "300" + } + ] + }, + { + "columns": [ + { "key": "plan", "title": "Plan", "value": "XL" }, + { "key": "pricing", "title": "Pricing", "value": "$200" }, + { "key": "cpu", "title": "CPU", "value": "4-core ARM" }, + { "key": "dedicated", "title": "Dedicated", "value": true }, + { "key": "memory", "title": "Memory", "value": "16 GB" }, + { "key": "maxDiskIO", "title": "Maximum Disk IO Bandwidth", "value": "4,750 Mbps" }, + { + "key": "baseDiskIO", + "title": "Baseline Disk IO Bandwidth", + "value": "1,188 Mbps" + }, + { + "key": "directConnections", + "title": "Connections: Direct (recommended)", + "value": "200" + }, + { + "key": "poolerConnections", + "title": "Connections: Pooler (recommended)", + "value": "600" + } + ] + }, + { + "columns": [ + { "key": "plan", "title": "Plan", "value": "2XL" }, + { "key": "pricing", "title": "Pricing", "value": "$400" }, + { "key": "cpu", "title": "CPU", "value": "8-core ARM" }, + { "key": "dedicated", "title": "Dedicated", "value": true }, + { "key": "memory", "title": "Memory", "value": "32 GB" }, + { "key": "maxDiskIO", "title": "Maximum Disk IO Bandwidth", "value": "4,750 Mbps" }, + { + "key": "baseDiskIO", + "title": "Baseline Disk IO Bandwidth", + "value": "2,375 Mbps" + }, + { + "key": "directConnections", + "title": "Connections: Direct (recommended)", + "value": "350" + }, + { + "key": "poolerConnections", + "title": "Connections: Pooler (recommended)", + "value": "1200" + } + ] + }, + { + "columns": [ + { "key": "plan", "title": "Plan", "value": "4XL" }, + { "key": "pricing", "title": "Pricing", "value": "$950" }, + { "key": "cpu", "title": "CPU", "value": "16-core ARM" }, + { "key": "dedicated", "title": "Dedicated", "value": true }, + { "key": "memory", "title": "Memory", "value": "64 GB" }, + { "key": "maxDiskIO", "title": "Maximum Disk IO Bandwidth", "value": "4,750 Mbps" }, + { + "key": "baseDiskIO", + "title": "Baseline Disk IO Bandwidth", + "value": "4,750 Mbps" + }, + { + "key": "directConnections", + "title": "Connections: Direct (recommended)", + "value": "420" + }, + { + "key": "poolerConnections", + "title": "Connections: Pooler (recommended)", + "value": "2800" + } + ] + }, + { + "columns": [ + { "key": "plan", "title": "Plan", "value": "8XL" }, + { "key": "pricing", "title": "Pricing", "value": "$1,860" }, + { "key": "cpu", "title": "CPU", "value": "32-core ARM" }, + { "key": "dedicated", "title": "Dedicated", "value": true }, + { "key": "memory", "title": "Memory", "value": "128 GB" }, + { "key": "maxDiskIO", "title": "Maximum Disk IO Bandwidth", "value": "9,500 Mbps" }, + { + "key": "baseDiskIO", + "title": "Baseline Disk IO Bandwidth", + "value": "9,500 Mbps" + }, + { + "key": "directConnections", + "title": "Connections: Direct (recommended)", + "value": "450" + }, + { + "key": "poolerConnections", + "title": "Connections: Pooler (recommended)", + "value": "5600" + } + ] + }, + { + "columns": [ + { "key": "plan", "title": "Plan", "value": "12XL" }, + { "key": "pricing", "title": "Pricing", "value": "$2,790" }, + { "key": "cpu", "title": "CPU", "value": "48-core ARM" }, + { "key": "dedicated", "title": "Dedicated", "value": true }, + { "key": "memory", "title": "Memory", "value": "192 GB" }, + { + "key": "maxDiskIO", + "title": "Maximum Disk IO Bandwidth", + "value": "14,250 Mbps" + }, + { + "key": "baseDiskIO", + "title": "Baseline Disk IO Bandwidth", + "value": "14,250 Mbps" + }, + { + "key": "directConnections", + "title": "Connections: Direct (recommended)", + "value": "480" + }, + { + "key": "poolerConnections", + "title": "Connections: Pooler (recommended)", + "value": "8600" + } + ] + }, + { + "columns": [ + { "key": "plan", "title": "Plan", "value": "16XL" }, + { "key": "pricing", "title": "Pricing", "value": "$3,720" }, + { "key": "cpu", "title": "CPU", "value": "64-core ARM" }, + { "key": "dedicated", "title": "Dedicated", "value": true }, + { "key": "memory", "title": "Memory", "value": "256 GB" }, + { + "key": "maxDiskIO", + "title": "Maximum Disk IO Bandwidth", + "value": "19,000 Mbps" + }, + { + "key": "baseDiskIO", + "title": "Baseline Disk IO Bandwidth", + "value": "19,000 Mbps" + }, + { + "key": "directConnections", + "title": "Connections: Direct (recommended)", + "value": "500" + }, + { + "key": "poolerConnections", + "title": "Connections: Pooler (recommended)", + "value": "11,600" + } + ] + } + ] + }, + "support": { + "title": "Support", + "features": [ + "Guaranteed Response Times", + "SLAs", + "Designated Support", + "Advanced Support Scope" + ], + "rows": [ + { + "columns": [ + { "key": "plan", "title": "Plan", "value": "Standard" }, + { "key": "pricing", "title": "Pricing", "value": "Contact Us" }, + { + "key": "severityLevelUrgent", + "title": "1. Severity Level: Urgent", + "value": "1 business hour (24/7x365)" + }, + { + "key": "severityLevelHigh", + "title": "2. Severity Level: High", + "value": "4 business hours (Monday - Friday)" + }, + { + "key": "severityLevelNormal", + "title": "3. Severity Level: Normal", + "value": "1 business day (Monday - Friday)" + }, + { + "key": "severityLevelLow", + "title": "4. Severity Level: Low", + "value": "2 business days (Monday - Friday)" + } + ] + }, + { + "columns": [ + { "key": "plan", "title": "Plan", "value": "Priority" }, + { "key": "pricing", "title": "Pricing", "value": "Contact Us" }, + { + "key": "severityLevelUrgent", + "title": "1. Severity Level: Urgent", + "value": "1 business hour (24/7x365)" + }, + { + "key": "severityLevelHigh", + "title": "2. Severity Level: High", + "value": "2 business hours (Monday - Friday)" + }, + { + "key": "severityLevelNormal", + "title": "3. Severity Level: Normal", + "value": "1 business day (Monday - Friday)" + }, + { + "key": "severityLevelLow", + "title": "4. Severity Level: Low", + "value": "2 business days (Monday - Friday)" + } + ] + }, + { + "columns": [ + { "key": "plan", "title": "Plan", "value": "Priority Plus" }, + { "key": "pricing", "title": "Pricing", "value": "Contact Us" }, + { + "key": "severityLevelUrgent", + "title": "1. Severity Level: Urgent", + "value": "1 business hour (24/7x365)" + }, + { + "key": "severityLevelHigh", + "title": "2. Severity Level: High", + "value": "2 business hours (24/7x365)" + }, + { + "key": "severityLevelNormal", + "title": "3. Severity Level: Normal", + "value": "12 business hours (Monday - Friday)" + }, + { + "key": "severityLevelLow", + "title": "4. Severity Level: Low", + "value": "1 business days (Monday - Friday)" + } + ] + } + ] + } +} diff --git a/apps/www/data/PricingAddOn.json b/apps/www/data/PricingAddOns.json similarity index 99% rename from apps/www/data/PricingAddOn.json rename to apps/www/data/PricingAddOns.json index d756fb75d18..63b69e84725 100644 --- a/apps/www/data/PricingAddOn.json +++ b/apps/www/data/PricingAddOns.json @@ -1,5 +1,5 @@ { - "database": { + "optimized_compute": { "title": "Optimized Compute", "features": [ "For projects that need dedicated compute", diff --git a/apps/www/data/PricingFAQ.json b/apps/www/data/PricingFAQ.json index f6d897e8541..44fa8c58784 100644 --- a/apps/www/data/PricingFAQ.json +++ b/apps/www/data/PricingFAQ.json @@ -1,7 +1,7 @@ [ { "question": "Can I cap my usage so my bill doesn't run over?", - "answer": "Yes. Spend caps are on by default on the pro tier. You can turn spend caps off for usage beyond the tier limits to pay as you grow." + "answer": "Yes. Spend caps are on by default on the Pro tier. You can turn spend caps off for usage beyond the tier limits to pay as you grow." }, { "question": "I'm worried I could end up with a huge bill at the end of the month.", @@ -9,7 +9,7 @@ }, { "question": "When will I be billed?", - "answer": "Our Pro plan is charged up front, and billed on a monthly basis. Additional usage costs are also billed at the end of the month." + "answer": "Our Pro tier is charged up front, and billed on a monthly basis. Additional usage costs are also billed at the end of the month." }, { "question": "Are you going to change your pricing in the future?", diff --git a/apps/www/pages/404.tsx b/apps/www/pages/404.tsx index f0d453140e4..f31fe7d4dd3 100644 --- a/apps/www/pages/404.tsx +++ b/apps/www/pages/404.tsx @@ -5,7 +5,7 @@ import { Button } from 'ui' import DefaultLayout from '../components/Layouts/Default' -import { useTheme } from '~/components/Providers' +import { useTheme } from 'common/Providers' import * as supabaseLogoWordmarkDark from 'common/assets/images/supabase-logo-wordmark--dark.png' import * as supabaseLogoWordmarkLight from 'common/assets/images/supabase-logo-wordmark--light.png' diff --git a/apps/www/pages/_app.tsx b/apps/www/pages/_app.tsx index afe6bd7a1a1..b4fb7a031ce 100644 --- a/apps/www/pages/_app.tsx +++ b/apps/www/pages/_app.tsx @@ -6,7 +6,7 @@ import { useEffect } from 'react' import Meta from '~/components/Favicons' import '../styles/index.css' import { post } from './../lib/fetchWrapper' -import { ThemeProvider } from '~/components/Providers' +import { ThemeProvider } from 'common/Providers' import Head from 'next/head' export default function MyApp({ Component, pageProps }: AppProps) { diff --git a/apps/www/pages/careers/index.tsx b/apps/www/pages/careers/index.tsx index af3b1cff166..e69ad552801 100644 --- a/apps/www/pages/careers/index.tsx +++ b/apps/www/pages/careers/index.tsx @@ -8,7 +8,7 @@ import { Badge, Button, IconCheck } from 'ui' import Globe from '~/components/Globe' import DefaultLayout from '~/components/Layouts/Default' import SectionContainer from '~/components/Layouts/SectionContainer' -import { useTheme } from '~/components/Providers' +import { useTheme } from 'common/Providers' import career from '~/data/career.json' import Styles from './career.module.css' diff --git a/apps/www/pages/launch-week/index.tsx b/apps/www/pages/launch-week/index.tsx index d6b8ce5e077..69620a43bea 100644 --- a/apps/www/pages/launch-week/index.tsx +++ b/apps/www/pages/launch-week/index.tsx @@ -9,7 +9,7 @@ import { createClient, Session } from '@supabase/supabase-js' import { useRouter } from 'next/router' import { useEffect, useState } from 'react' import TicketContainer from '~/components/LaunchWeek/Ticket/TicketContainer' -import { useTheme } from '~/components/Providers' +import { useTheme } from 'common/Providers' import classNames from 'classnames' import styleUtils from '~/components/LaunchWeek/Ticket/utils.module.css' import { SITE_ORIGIN } from '~/lib/constants' diff --git a/apps/www/pages/launch-week/tickets/[username].tsx b/apps/www/pages/launch-week/tickets/[username].tsx index 7bd706c81bd..b39313e2c8e 100644 --- a/apps/www/pages/launch-week/tickets/[username].tsx +++ b/apps/www/pages/launch-week/tickets/[username].tsx @@ -8,7 +8,7 @@ import { SITE_URL, SAMPLE_TICKET_NUMBER } from '~/lib/constants' import { createClient } from '@supabase/supabase-js' import { useEffect, useState } from 'react' import { FastGlobOptionsWithoutCwd } from 'globby' -import { useTheme } from '~/components/Providers' +import { useTheme } from 'common/Providers' type Props = { username: string | null diff --git a/apps/www/pages/launch-week/tickets/index.tsx b/apps/www/pages/launch-week/tickets/index.tsx index fba61ea897e..b7476a0475c 100644 --- a/apps/www/pages/launch-week/tickets/index.tsx +++ b/apps/www/pages/launch-week/tickets/index.tsx @@ -6,7 +6,7 @@ import { SITE_URL } from '~/lib/constants' import { useRouter } from 'next/router' import { createClient, Session } from '@supabase/supabase-js' import { useState, useEffect } from 'react' -import { useTheme } from '~/components/Providers' +import { useTheme } from 'common/Providers' export default function TicketHome() { const { isDarkMode } = useTheme() diff --git a/apps/www/pages/pricing/index.tsx b/apps/www/pages/pricing/index.tsx index 75e03711b85..9b209dc901e 100644 --- a/apps/www/pages/pricing/index.tsx +++ b/apps/www/pages/pricing/index.tsx @@ -1,21 +1,24 @@ -import { ServerIcon, SupportIcon } from '@heroicons/react/outline' -import { Accordion, Button, IconCheck } from 'ui' +import { Accordion, Button, IconCheck, Select } from 'ui' import Solutions from 'data/Solutions.json' import { NextSeo } from 'next-seo' import Link from 'next/link' import { useRouter } from 'next/router' -import React from 'react' +import React, { useState } from 'react' import ReactMarkdown from 'react-markdown' import CTABanner from '~/components/CTABanner' import DefaultLayout from '~/components/Layouts/Default' -import PricingAddOnTable from '~/components/PricingAddOnTable' -import { PricingTableRowDesktop, PricingTableRowMobile } from '~/components/PricingTableRow' +import { PricingTableRowDesktop, PricingTableRowMobile } from '~/components/Pricing/PricingTableRow' import pricing from '~/data/Pricing.json' -import pricingAddOn from '~/data/PricingAddOn.json' import pricingFaq from '~/data/PricingFAQ.json' +import { useTheme } from 'common/Providers' +import ComputePricingModal from '~/components/Pricing/ComputePricingModal' export default function IndexPage() { const router = useRouter() + const { basePath } = useRouter() + const { isDarkMode } = useTheme() + const [showComputeModal, setShowComputeModal] = useState(false) + const [activeMobileTier, setActiveMobileTier] = useState('Free') const meta_title = 'Pricing & fees | Supabase' const meta_description = @@ -30,11 +33,14 @@ export default function IndexPage() { const tiers = [ { name: 'Free', - costUnit: '/month per project', + nameBadge: '', + costUnit: 'per month per project', href: 'https://app.supabase.com/new/new-project', + priceLabel: 'Starting from', priceMonthly: 0, warning: 'Limit of 2 free projects', description: 'Perfect for passion projects & simple websites.', + preface: 'Get started with:', features: [ 'Up to 500MB database & 1GB file storage', 'Up to 2GB bandwidth', @@ -45,15 +51,18 @@ export default function IndexPage() { '1-day log retention', 'Community support', ], - additional: 'Free projects are paused after 1 week of inactivity.', + scale: 'Free projects are paused after 1 week of inactivity.', cta: 'Get Started', }, { name: 'Pro', - costUnit: '/month per project', + nameBadge: '', + costUnit: 'per month per project', href: 'https://app.supabase.com/new/new-project', from: true, + priceLabel: 'Starting from', + warning: '+ usage', priceMonthly: 25, description: 'For production applications with the option to scale.', features: [ @@ -70,16 +79,43 @@ export default function IndexPage() { ], scale: 'Additional fees apply for usage and storage beyond the limits above.', shutdown: '', - preface: 'Everything below included in the base plan', - additional: 'Need more? Turn off your spend cap to Pay As You Grow ', + preface: 'Everything in the Free plan, plus:', + additional: '', cta: 'Get Started', }, + // { + // name: 'Team', + // nameBadge: 'New', + // costUnit: 'per month per org', + // href: 'https://app.supabase.com/new/new-project', + // from: true, + // priceLabel: 'Starting from', + // priceMonthly: 599, + // description: 'For scaling teams with permissions & access controls', + // warning: '+ any additional usage', + // features: [ + // 'Usage-based pricing', + // 'Organization member roles (ABAC)', + // 'SOC2', + // 'Priority email support & SLAs', + // '14 day backups', + // '100,000 monthly active users included', + // 'Standardized Security Questionnaire', + // 'SSO for Supabase Dashboard', + // '1 XS compute instance', + // '28 day log retention', + // ], + // scale: '', + // shutdown: '', + // preface: 'The following features will apply to all projects within the organization:', + // additional: '', + // cta: 'Get Started', + // }, { name: 'Enterprise', href: 'https://forms.supabase.com/enterprise', description: 'For large-scale applications managing serious workloads.', features: [ - `Point in time recovery`, `Designated Support manager & SLAs`, `Enterprise OAuth providers`, `SSO/ SAML`, @@ -87,14 +123,57 @@ export default function IndexPage() { `Custom contracts & invoicing`, `On-premise support`, `24×7×365 premium enterprise support`, + `Custom Security questionnaires`, + `Private Slack channel`, + `Uptime SLA`, ], + priceLabel: 'Custom quotas', + priceMonthly: 'Exclusive pricing', + preface: 'These apply to all projects within the organization:', scale: '', shutdown: '', cta: 'Contact Us', }, ] - const MobileHeaders = ({ + const addons = [ + { + name: 'Optimized Compute', + heroImg: 'addons-compute-hero', + icon: 'compute-upgrade', + price: 'Starts from $5', + description: 'Increase the capability of your database only for what you need.', + leftCtaText: 'Documentation', + leftCtaLink: 'https://supabase.com/docs/guides/platform/compute-add-ons', + rightCtaText: 'See Pricing breakdown', + rightCtaLink: '#open-modal', + }, + { + name: 'Custom Domain', + heroImg: 'addons-domains-hero', + icon: 'custom-domain-upgrade', + price: 'Flat fee $10', + description: + 'Use your own domain for your Supabase project to present a more polished product to your users.', + leftCtaText: 'Documentation', + leftCtaLink: 'https://supabase.com/docs/guides/platform/custom-domains', + rightCtaText: 'See more', + rightCtaLink: 'http://', + }, + { + name: 'Point in Time Recovery', + heroImg: 'addons-pitr-hero', + icon: 'pitr-upgrade', + price: 'Starts from $5', + description: 'Roll back to any specific point in time and ensure that data is not lost.', + leftCtaText: 'Documentation', + leftCtaLink: 'https://supabase.com/docs/guides/platform/backups', + rightCtaText: 'See Pricing breakdown', + rightCtaLink: 'http://', + }, + ] + + const MobileHeader = ({ // title, description, priceDescription, @@ -111,14 +190,18 @@ export default function IndexPage() { from?: boolean }) => { return ( -
-

{tier}

+
+

+ {tier} +

{from && From} - - {showDollarSign && '$'} - {price} - + {showDollarSign ? ( + ${price} + ) : ( + {price} + )} +

{priceDescription}

{description}

@@ -148,13 +231,11 @@ export default function IndexPage() { }} /> -
-
+
+
-

- Pricing -

+

Pricing

Predictable pricing, no surprises

Start building for free, collaborate with a team, then scale to millions of users @@ -172,111 +253,132 @@ export default function IndexPage() { lg:px-8 " > -

+
{tiers.map((tier) => (
-
-
-

{tier.name}

- {tier.warning && ( -
- {tier.warning} -
- )} -
-

{tier.description}

+ {tier.name === 'Pro' && ( +

Most Popular

+ )} +
+
+

+ {tier.name} +

+ {tier.nameBadge && ( + + {tier.nameBadge} + + )} +
+
+

+ {tier.description} +

+ +
- {tier.priceMonthly !== undefined ? ( + >
- - {typeof tier.priceMonthly !== 'string' && '$'} +

+ {tier.priceLabel} +

+

+ {tier.name !== 'Enterprise' && '$'} {tier.priceMonthly} - - - {tier.costUnit} - +

+ {tier.costUnit && ( +

{tier.costUnit}

+ )} + + {tier.warning && ( +

+ + {tier.warning} + +

+ )}
- {tier.from && ( - - + any additional usage - +
+
+
+
+ {tier.preface && ( +

{tier.preface}

+ )} + {/*

Included with plan:

*/} +
    + {tier.features.map((feature) => ( +
  • +
*/} + {feature} + + ))} + + +
+
+ {tier.additional &&

{tier.additional}

} + {tier.scale &&

{tier.scale}

} + {tier.shutdown && ( +

{tier.shutdown}

)}
- ) : ( - Contact Us - )} -
-
-
- {tier.preface &&

{tier.preface}

} - {/*

Included with plan:

*/} -
    - {tier.features.map((feature) => ( -
  • - {/*
    */} -
    */} -

    - {feature} -

    -
  • - ))} -
- -
-
- {tier.additional && ( -

{tier.additional}

- )} - {tier.scale &&

{tier.scale}

} - {tier.shutdown &&

{tier.shutdown}

} + + +
- - -
@@ -284,33 +386,118 @@ export default function IndexPage() {
+
-
-
-

Add-Ons

-

- Level up your Supabase experience with add-ons. -

+
+
+
+

Easily customizable add-ons

+

+ Level up your Supabase experience with add-ons. +

+
+ +
+ {addons.map((addon) => ( +
+
+ +
+
+

{addon.price}

+
+ Compute + {addon.name} +
+

+ {addon.description} +

+
+ + + + + + {addon.name === 'Optimized Compute' ? ( + + ) : ( + '' + )} +
+
+
+ ))} +
+
+ Got something you'd like to see here? + + + + + +
-
- } - pricing={pricingAddOn.database} - /> - } - pricing={pricingAddOn.support} - /> +
+
+ + Available for Pro plan + +

Cost control with spend caps

+

+ The Pro tier has a usage quota included and a spend cap turned on by default. If you + need to go beyond the inclusive limits, simply switch off your spend cap to pay for + additional usage. +

+
+
+
+ +
+
-

Compare Plans

-

+

+ Compare Plans +

+

Start with a hobby project, collaborate with a team, and scale to millions of users.

@@ -320,270 +507,283 @@ export default function IndexPage() {
{/* Free - Mobile */} +
+
+ + +
+
+ {activeMobileTier === 'Free' && ( + <> + + + + + + + + + + + )} - + {activeMobileTier === 'Pro' && ( + <> + + + + + + + + + + + )} - - - - - - - - - - {/* Pro - Mobile */} - - - - - - - - - - - {/* Enterprise - Mobile */} - - - - - - - - - - + {activeMobileTier === 'Enterprise' && ( + <> + + + + + + + + + + + )}
{/* */}
- + - - - - - + {tiers.map((tier) => ( + + ))} + + + + {tiers.map((tier) => ( + + ))} + - + + > - - - - - + + + + + ))} - @@ -635,7 +835,7 @@ export default function IndexPage() {
Pricing plan comparison
Feature by - Plans
- Free -
-
- Pro -
-
- Enterprise -
-
+

+ {tier.name} +

+
+
+

{tier.description}

+
+
- Pricing - -
- $0 -

/project/month

+ {tiers.map((tier) => ( +
+
+
+ <> + + {tier.name !== 'Enterprise' && '$'} + {tier.priceMonthly} + +

per project per month

+ -

Perfect for hobby projects and experiments

+ {tier.warning && ( +

+ + {tier.warning} + +

+ )} - - - - - -
-
-
- $25 -

/project/month + usage costs

- -

- Everything you need to scale your project into production -

- - - - - - -
-
-
- Contact Us -

for a quote

- -

- Designated support team, account manager and technical specialist -

- - - - - - -
-
- @@ -645,7 +845,7 @@ export default function IndexPage() { - @@ -665,17 +865,52 @@ export default function IndexPage() { Can't find the answer to your question, ask someone in the community either on our Discord or GitHub.

-
+
- - @@ -710,6 +945,10 @@ export default function IndexPage() {
+ ) } diff --git a/apps/www/public/images/pricing/addons-compute-hero-light.png b/apps/www/public/images/pricing/addons-compute-hero-light.png new file mode 100644 index 00000000000..23a54cf84b7 Binary files /dev/null and b/apps/www/public/images/pricing/addons-compute-hero-light.png differ diff --git a/apps/www/public/images/pricing/addons-compute-hero.png b/apps/www/public/images/pricing/addons-compute-hero.png new file mode 100644 index 00000000000..0d10d71fdce Binary files /dev/null and b/apps/www/public/images/pricing/addons-compute-hero.png differ diff --git a/apps/www/public/images/pricing/addons-domains-hero-light.png b/apps/www/public/images/pricing/addons-domains-hero-light.png new file mode 100644 index 00000000000..c83fd215c6a Binary files /dev/null and b/apps/www/public/images/pricing/addons-domains-hero-light.png differ diff --git a/apps/www/public/images/pricing/addons-domains-hero.png b/apps/www/public/images/pricing/addons-domains-hero.png new file mode 100644 index 00000000000..bc77e34fd7d Binary files /dev/null and b/apps/www/public/images/pricing/addons-domains-hero.png differ diff --git a/apps/www/public/images/pricing/addons-pitr-hero-light.png b/apps/www/public/images/pricing/addons-pitr-hero-light.png new file mode 100644 index 00000000000..58bb81be2d4 Binary files /dev/null and b/apps/www/public/images/pricing/addons-pitr-hero-light.png differ diff --git a/apps/www/public/images/pricing/addons-pitr-hero.png b/apps/www/public/images/pricing/addons-pitr-hero.png new file mode 100644 index 00000000000..c98b1561685 Binary files /dev/null and b/apps/www/public/images/pricing/addons-pitr-hero.png differ diff --git a/apps/www/public/images/pricing/addons-support-hero-light.png b/apps/www/public/images/pricing/addons-support-hero-light.png new file mode 100644 index 00000000000..c9181965843 Binary files /dev/null and b/apps/www/public/images/pricing/addons-support-hero-light.png differ diff --git a/apps/www/public/images/pricing/addons-support-hero.png b/apps/www/public/images/pricing/addons-support-hero.png new file mode 100644 index 00000000000..8ddb8722434 Binary files /dev/null and b/apps/www/public/images/pricing/addons-support-hero.png differ diff --git a/apps/www/public/images/pricing/addons-support-hero.svg b/apps/www/public/images/pricing/addons-support-hero.svg new file mode 100644 index 00000000000..628bf43d9df --- /dev/null +++ b/apps/www/public/images/pricing/addons-support-hero.svg @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/www/public/images/pricing/addons-support-light.svg b/apps/www/public/images/pricing/addons-support-light.svg new file mode 100644 index 00000000000..040e497a537 --- /dev/null +++ b/apps/www/public/images/pricing/addons-support-light.svg @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/www/public/images/pricing/compute-upgrade-green.svg b/apps/www/public/images/pricing/compute-upgrade-green.svg new file mode 100644 index 00000000000..e8b6258fb32 --- /dev/null +++ b/apps/www/public/images/pricing/compute-upgrade-green.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/apps/www/public/images/pricing/compute-upgrade-light.svg b/apps/www/public/images/pricing/compute-upgrade-light.svg new file mode 100644 index 00000000000..d46f5829371 --- /dev/null +++ b/apps/www/public/images/pricing/compute-upgrade-light.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/www/public/images/pricing/compute-upgrade.svg b/apps/www/public/images/pricing/compute-upgrade.svg new file mode 100644 index 00000000000..292b81d4403 --- /dev/null +++ b/apps/www/public/images/pricing/compute-upgrade.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/www/public/images/pricing/custom-domain-upgrade-light.svg b/apps/www/public/images/pricing/custom-domain-upgrade-light.svg new file mode 100644 index 00000000000..cad9b89e185 --- /dev/null +++ b/apps/www/public/images/pricing/custom-domain-upgrade-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/www/public/images/pricing/custom-domain-upgrade.svg b/apps/www/public/images/pricing/custom-domain-upgrade.svg new file mode 100644 index 00000000000..1f635380026 --- /dev/null +++ b/apps/www/public/images/pricing/custom-domain-upgrade.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/www/public/images/pricing/pitr-upgrade-light.svg b/apps/www/public/images/pricing/pitr-upgrade-light.svg new file mode 100644 index 00000000000..7813f479d93 --- /dev/null +++ b/apps/www/public/images/pricing/pitr-upgrade-light.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/www/public/images/pricing/pitr-upgrade.svg b/apps/www/public/images/pricing/pitr-upgrade.svg new file mode 100644 index 00000000000..05d5238cbce --- /dev/null +++ b/apps/www/public/images/pricing/pitr-upgrade.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/www/public/images/pricing/spend-cap-light.png b/apps/www/public/images/pricing/spend-cap-light.png new file mode 100644 index 00000000000..07d23d08a55 Binary files /dev/null and b/apps/www/public/images/pricing/spend-cap-light.png differ diff --git a/apps/www/public/images/pricing/spend-cap.png b/apps/www/public/images/pricing/spend-cap.png new file mode 100644 index 00000000000..554d7969714 Binary files /dev/null and b/apps/www/public/images/pricing/spend-cap.png differ diff --git a/apps/www/public/images/pricing/support-upgrade-light.svg b/apps/www/public/images/pricing/support-upgrade-light.svg new file mode 100644 index 00000000000..e2143d09436 --- /dev/null +++ b/apps/www/public/images/pricing/support-upgrade-light.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/apps/www/public/images/pricing/support-upgrade.svg b/apps/www/public/images/pricing/support-upgrade.svg new file mode 100644 index 00000000000..d981270ce21 --- /dev/null +++ b/apps/www/public/images/pricing/support-upgrade.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/apps/www/public/sitemap_www.xml b/apps/www/public/sitemap_www.xml index 12142676382..1f593cac4b6 100644 --- a/apps/www/public/sitemap_www.xml +++ b/apps/www/public/sitemap_www.xml @@ -60,12 +60,6 @@ 0.5 - - https://supabase.com/blog/ - weekly - 0.5 - - https://supabase.com/contact/mfa weekly @@ -73,7 +67,7 @@ - https://supabase.com/database + https://supabase.com/blog/ weekly 0.5 @@ -85,13 +79,19 @@ - https://supabase.com/launch-week/ticket-image + https://supabase.com/legal/dpa weekly 0.5 - https://supabase.com/legal/dpa + https://supabase.com/database + weekly + 0.5 + + + + https://supabase.com/launch-week/ticket-image weekly 0.5 @@ -974,24 +974,66 @@ 0.5 + + https://supabase.com/blog/custom-domain-names + weekly + 0.5 + + https://supabase.com/blog/launch-week-6-community-day weekly 0.5 + + https://supabase.com/blog/launch-week-6-wrap-up + weekly + 0.5 + + https://supabase.com/blog/new-in-postgres-15 weekly 0.5 + + https://supabase.com/blog/pg-graphql-v1 + weekly + 0.5 + + + + https://supabase.com/blog/postgres-point-in-time-recovery + weekly + 0.5 + + https://supabase.com/blog/postgrest-11-prerelease weekly 0.5 + + https://supabase.com/blog/vault-now-in-beta + weekly + 0.5 + + + + https://supabase.com/blog/launch-week-6-hackathon-winners + weekly + 0.5 + + + + https://supabase.com/blog/supabase-beta-december-2022 + weekly + 0.5 + + https://supabase.com/alternatives/supabase-vs-firebase weekly diff --git a/apps/www/styles/index.css b/apps/www/styles/index.css index 77922bd7095..ebebd43fc00 100644 --- a/apps/www/styles/index.css +++ b/apps/www/styles/index.css @@ -659,3 +659,36 @@ launch week -webkit-mask-image: linear-gradient(rgba(0, 0, 0, 1), transparent); } + +/* Text with a gradient background */ +[class*='gradient-text-'] { + background-clip: text; + -webkit-text-fill-color: transparent; +} + +[class*='gradient-text-']::selection { + background-color: var(--colors-brand9); + background-clip: unset; + -webkit-text-fill-color: white; +} + +@layer utilities { + .gradient-text-brand-100 { + background-image: linear-gradient(45deg, var(--colors-brand8) 0%, var(--colors-brand9) 100%); + } + .gradient-text-brand-500 { + background-image: linear-gradient(45deg, var(--colors-brand8) 0%, var(--colors-brand9) 100%); + } + + .gradient-text-scale-100 { + background-image: -webkit-linear-gradient(45deg, #fff 0%, var(--colors-green12) 100%); + } + + .gradient-text-scale-500 { + background-image: -webkit-linear-gradient( + 45deg, + var(--colors-scale10) 0%, + var(--colors-scale12) 100% + ); + } +} diff --git a/packages/ui/src/lib/theme/defaultTheme.ts b/packages/ui/src/lib/theme/defaultTheme.ts index 8cf91b927ff..82df294f687 100644 --- a/packages/ui/src/lib/theme/defaultTheme.ts +++ b/packages/ui/src/lib/theme/defaultTheme.ts @@ -117,9 +117,9 @@ export default { flex flex-row gap-3 items-center - w-full - text-left - cursor-pointer + w-full + text-left + cursor-pointer outline-none focus-visible:ring-1 @@ -143,27 +143,27 @@ export default { group border border-scale-700 - + first:rounded-tl-md first:rounded-tr-md last:rounded-bl-md last:rounded-br-md `, trigger: ` flex flex-row items-center - px-6 py-4 - w-full - text-left - cursor-pointer - - font-medium - text-base - bg-transparent + px-6 py-4 + w-full + text-left + cursor-pointer + + font-medium + text-base + bg-transparent outline-none focus-visible:ring-1 focus-visible:z-50 ring-scale-1100 - + transition-colors hover:bg-scale-200 @@ -252,8 +252,8 @@ export default { alert: { base: ` - relative rounded border py-4 px-6 - flex space-x-4 items-start + relative rounded border py-4 px-6 + flex space-x-4 items-start `, header: 'block text-sm font-normal mb-1', description: `text-xs`, @@ -290,11 +290,11 @@ export default { }, }, close: ` - absolute - right-6 top-4 - p-0 m-0 + absolute + right-6 top-4 + p-0 m-0 text-scale-900 - cursor-pointer transition ease-in-out + cursor-pointer transition ease-in-out bg-transparent border-transparent focus:outline-none opacity-50 hover:opacity-100`, }, @@ -306,15 +306,15 @@ export default { card: { base: ` bg-white dark:bg-scaleDark-700 - - border - ${defaults.border.primary} - flex flex-col + border + ${defaults.border.primary} + + flex flex-col rounded-md shadow-lg overflow-hidden relative `, hoverable: 'transition hover:-translate-y-1 hover:shadow-2xl', - head: `px-8 py-6 flex justify-between + head: `px-8 py-6 flex justify-between border-b ${defaults.border.primary} `, content: 'p-8', @@ -328,20 +328,20 @@ export default { base: `w-full justify-between space-y-4`, underlined: { list: ` - flex items-center border-b + flex items-center border-b ${defaults.border.secondary} `, - base: ` - relative - cursor-pointer - text-scale-900 - flex - items-center + base: ` + relative + cursor-pointer + text-scale-900 + flex + items-center space-x-2 - text-center + text-center transition - focus:outline-none - focus-visible:ring + focus:outline-none + focus-visible:ring focus-visible:ring-scale-700 focus-visible:border-scale-900 `, @@ -355,18 +355,18 @@ export default { }, pills: { list: 'flex space-x-1', - base: ` - relative - cursor-pointer - flex - items-center + base: ` + relative + cursor-pointer + flex + items-center space-x-2 - text-center + text-center transition shadow-sm rounded - focus:outline-none - focus-visible:ring + focus:outline-none + focus-visible:ring focus-visible:ring-scale-700 focus-visible:border-scale-900 `, @@ -378,23 +378,23 @@ export default { active: ` bg-scale-1200 text-scale-200 - border-scale-1200 + border-scale-1200 `, }, 'rounded-pills': { list: 'flex flex-wrap gap-2', - base: ` - relative - cursor-pointer - flex - items-center + base: ` + relative + cursor-pointer + flex + items-center space-x-2 - text-center + text-center transition shadow-sm rounded-full - focus:outline-none - focus-visible:ring + focus:outline-none + focus-visible:ring focus-visible:ring-scale-700 focus-visible:border-scale-900 `, @@ -406,7 +406,7 @@ export default { active: ` bg-scale-1200 text-scale-200 - border-scale-1200 + border-scale-1200 `, }, block: 'w-full flex items-center justify-center', @@ -427,15 +427,15 @@ export default { button: { base: ` - relative - cursor-pointer - inline-flex items-center space-x-2 - text-center + relative + cursor-pointer + inline-flex items-center space-x-2 + text-center font-regular - transition ease-out duration-200 - rounded + transition ease-out duration-200 + rounded ${defaults['focus-visible']} - + `, label: `truncate`, container: 'inline-flex font-medium', @@ -449,7 +449,7 @@ export default { secondary: ` bg-scale-1200 text-scale-100 hover:text-scale-800 - focus-visible:text-scale-600 + focus-visible:text-scale-600 bordershadow-scale-1100 hover:bordershadow-scale-900 @@ -462,7 +462,7 @@ export default { dark:bordershadow-scale-700 hover:dark:bordershadow-scale-800 dark:bg-scale-500 dark:hover:bg-scale-600 focus-visible:outline-brand-600 - + `, alternative: ` text-brand-1100 @@ -473,14 +473,14 @@ export default { focus-visible:outline-brand-600 `, outline: ` - text-scale-1200 - bg-transparent + text-scale-1200 + bg-transparent bordershadow-scale-600 hover:bordershadow-scale-700 dark:bordershadow-scale-800 hover:dark:bordershadow-scale-900 focus-visible:outline-scale-700 `, dashed: ` - text-scale-1200 + text-scale-1200 border border-dashed border-scale-700 hover:border-scale-900 @@ -498,7 +498,7 @@ export default { focus-visible:outline-scale-700 `, text: ` - text-scale-1200 + text-scale-1200 hover:bg-scale-500 shadow-none focus-visible:outline-scale-700 @@ -538,13 +538,13 @@ export default { input: { base: ` - block - box-border - w-full - rounded-md - shadow-sm + block + box-border + w-full + rounded-md + shadow-sm transition-all - text-scale-1200 + text-scale-1200 border focus:shadow-md ${defaults.focus} @@ -559,7 +559,7 @@ export default { `, error: ` bg-red-100 - border border-red-700 + border border-red-700 focus:ring-red-500 placeholder:text-red-600 `, @@ -581,13 +581,13 @@ export default { select: { base: ` - block - box-border - w-full - rounded-md - shadow-sm + block + box-border + w-full + rounded-md + shadow-sm transition-all - text-scale-1200 + text-scale-1200 border focus:shadow-md ${defaults.focus} @@ -605,7 +605,7 @@ export default { `, error: ` bg-red-100 - border border-red-700 + border border-red-700 focus:ring-red-500 placeholder:text-red-600 `, @@ -618,7 +618,7 @@ export default { disabled: 'opacity-50', actions_container: 'absolute inset-y-0 right-0 pl-3 pr-1 mr-5 flex items-center', chevron_container: 'absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none', - chevron: 'h-5 w-5 text-scale-600', + chevron: 'h-5 w-5 text-scale-800', }, /* @@ -628,12 +628,12 @@ export default { inputNumber: { base: ` block - box-border - w-full - rounded-md - shadow-sm + box-border + w-full + rounded-md + shadow-sm transition-all - text-scale-1200 + text-scale-1200 border focus:shadow-md ${defaults.focus} @@ -651,7 +651,7 @@ export default { `, error: ` bg-red-100 - border border-red-700 + border border-red-700 focus:ring-red-500 placeholder:text-red-600 `, @@ -668,9 +668,9 @@ export default { /* * Checkbox * - * + * * This Checkbox requires a plugin in your config: - + ``` // tailwind.config.js module.exports = { @@ -681,17 +681,17 @@ export default { ], } ``` - * - * + * + * */ checkbox: { base: ` - bg-transparent + bg-transparent ${defaults.focus} focus:ring-scale-400 - text-brand-900 - border-scale-700 + text-brand-900 + border-scale-700 shadow-sm rounded cursor-pointer @@ -727,9 +727,9 @@ export default { /* * Radio * - * + * * This Radio requires a plugin in your config: - + ``` // tailwind.config.js module.exports = { @@ -740,8 +740,8 @@ export default { ], } ``` - * - * + * + * */ radio: { @@ -750,7 +750,7 @@ export default { ${defaults.focus} focus:ring-brand-400 border-scale-700 - + text-brand-900 shadow-sm cursor-pointer @@ -797,7 +797,7 @@ export default { `, active: ` bg-scale-300 dark:bg-scale-600 z-10 - border-scale-900 dark:border-scale-900 + border-scale-900 dark:border-scale-900 border-1 `, radio_offset: 'left-4', @@ -816,7 +816,7 @@ export default { transition rounded-md border - shadow-sm + shadow-sm `, size: { tiny: `px-5 py-3`, @@ -833,7 +833,7 @@ export default { `, active: ` bg-scale-300 dark:bg-scale-600 z-10 - border-scale-900 dark:border-scale-900 + border-scale-900 dark:border-scale-900 border-1 `, radio_offset: 'left-4', @@ -849,9 +849,9 @@ export default { }, group: `flex flex-row gap-3`, base: ` - transition + transition border - rounded-lg + rounded-lg grow items-center flex-wrap @@ -888,10 +888,10 @@ export default { }, group: `flex flex-row gap-3`, base: ` - transition - border border-scale-700 hover:border-scale-900 + transition + border border-scale-700 hover:border-scale-900 shadow-sm - rounded-lg + rounded-lg grow `, size: { @@ -909,7 +909,7 @@ export default { `, active: ` bg-scale-300 dark:bg-scale-600 z-10 - border-scale-900 dark:border-scale-900 + border-scale-900 dark:border-scale-900 border-1 `, radio_offset: 'left-4', @@ -969,21 +969,21 @@ export default { sidepanel: { base: ` bg-scale-100 dark:bg-scale-300 - flex flex-col - fixed - inset-y-0 - max-w-full + flex flex-col + fixed + inset-y-0 + max-w-full h-screen border-l border-overlay-border shadow-xl `, header: ` - space-y-1 py-4 px-4 bg-overlay-bg sm:px-6 + space-y-1 py-4 px-4 bg-overlay-bg sm:px-6 border-b border-overlay-border `, contents: ` - relative - flex-1 + relative + flex-1 overflow-y-auto `, content: ` @@ -1002,12 +1002,12 @@ export default { align: { left: ` left-0 - data-open:animate-panel-slide-left-out + data-open:animate-panel-slide-left-out data-closed:animate-panel-slide-left-in `, right: ` right-0 - data-open:animate-panel-slide-right-out + data-open:animate-panel-slide-right-out data-closed:animate-panel-slide-right-in `, }, @@ -1023,9 +1023,9 @@ export default { dark:bg-scale-100 h-full w-full left-0 - top-0 + top-0 opacity-75 - data-closed:animate-fade-out-overlay-bg + data-closed:animate-fade-out-overlay-bg data-open:animate-fade-in-overlay-bg `, // this is to reset the button @@ -1041,10 +1041,10 @@ export default { toggle: { base: ` - p-0 relative - inline-flex flex-shrink-0 - border-2 border-transparent - rounded-full + p-0 relative + inline-flex flex-shrink-0 + border-2 border-transparent + rounded-full cursor-pointer transition-colors ease-in-out duration-200 ${defaults.focus} @@ -1054,8 +1054,8 @@ export default { hover:bg-scale-700 `, active: ` - bg-brand-900 - hover:bg-brand-900 + bg-brand-900 + hover:bg-brand-900 `, handle_container: { tiny: 'h-4 w-7', @@ -1066,12 +1066,12 @@ export default { }, handle: { base: ` - inline-block h-5 w-5 - rounded-full + inline-block h-5 w-5 + rounded-full bg-scale-100 dark:bg-scale-900 - shadow ring-0 - transition + shadow ring-0 + transition ease-in-out duration-200 `, tiny: 'h-3 w-3', @@ -1159,7 +1159,7 @@ export default { }, error: { base: ` - text-red-900 + text-red-900 transition-all data-show:mt-2 data-show:animate-slide-down-normal @@ -1187,7 +1187,7 @@ export default { trigger: ` flex - border-none + border-none rounded bg-transparent p-0 outline-none @@ -1279,8 +1279,8 @@ export default { popover: { trigger: ` flex - border-none - + border-none + rounded bg-transparent p-0 @@ -1300,7 +1300,7 @@ export default { data-closed:animate-dropdown-content-hide min-w-fit - origin-popover + origin-popover data-open:animate-dropdown-content-show data-closed:animate-dropdown-content-hide `, @@ -1344,7 +1344,7 @@ export default { cursor-pointer flex space-x-3 items-center outline-none - focus-visible:ring-1 ring-scale-1200 focus-visible:z-10 + focus-visible:ring-1 ring-scale-1200 focus-visible:z-10 group `, content: { @@ -1415,7 +1415,7 @@ export default { }, group: { base: ` - flex space-x-3 + flex space-x-3 mb-2 font-normal `, @@ -1438,20 +1438,20 @@ export default { bg-scale-100 dark:bg-scale-300 my-4 border border-scale-300 dark:border-scale-500 - rounded-md - shadow-xl - data-open:animate-overlay-show - data-closed:animate-overlay-hide - + rounded-md + shadow-xl + data-open:animate-overlay-show + data-closed:animate-overlay-hide + `, header: ` bg-scale-200 dark:bg-scale-400 - space-y-1 py-3 px-4 sm:px-5 + space-y-1 py-3 px-4 sm:px-5 border-b border-scale-300 dark:border-scale-500 `, footer: ` flex justify-end gap-2 - py-3 px-5 + py-3 px-5 border-t border-scale-300 dark:border-scale-500 `, size: { @@ -1469,9 +1469,9 @@ export default { dark:bg-scale-100 h-full w-full left-0 - top-0 + top-0 opacity-75 - data-closed:animate-fade-out-overlay-bg + data-closed:animate-fade-out-overlay-bg data-open:animate-fade-in-overlay-bg `, scroll_overlay: ` @@ -1480,7 +1480,8 @@ export default { grid place-items-center overflow-y-auto - data-open:animate-overlay-show data-closed:animate-overlay-hide + data-open:animate-overlay-show data-closed:animate-overlay-hide + z-50 `, separator: ` w-full @@ -1495,12 +1496,12 @@ export default { listbox: { base: ` - block - box-border - w-full - rounded-md - shadow-sm - text-scale-1200 + block + box-border + w-full + rounded-md + shadow-sm + text-scale-1200 border focus:shadow-md ${defaults.focus} @@ -1524,24 +1525,24 @@ export default { `, error: ` bg-red-100 - border border-red-700 + border border-red-700 focus:ring-red-500 placeholder:text-red-600 `, }, options_container_animate: ` transition - data-open:animate-slide-down + data-open:animate-slide-down data-open:opacity-1 data-closed:animate-slide-up data-closed:opacity-0 `, options_container: ` - bg-scale-100 dark:bg-scale-300 - shadow-lg - border border-solid - border-gray-100 dark:border-gray-600 max-h-60 - rounded-md py-1 text-base + bg-scale-100 dark:bg-scale-300 + shadow-lg + border border-solid + border-gray-100 dark:border-gray-600 max-h-60 + rounded-md py-1 text-base sm:text-sm z-10 overflow-hidden overflow-y-scroll origin-dropdown @@ -1561,7 +1562,7 @@ export default { chevron: 'h-5 w-5 text-scale-600', option: ` w-listbox - transition cursor-pointer select-none relative py-2 pl-3 pr-9 + transition cursor-pointer select-none relative py-2 pl-3 pr-9 text-scale-900 text-sm hover:bg-scale-300 dark:hover:bg-scale-500 @@ -1587,9 +1588,9 @@ export default { inputErrorIcon: { base: ` - flex items-center - right-3 pr-2 pl-2 - inset-y-0 + flex items-center + right-3 pr-2 pl-2 + inset-y-0 pointer-events-none text-red-900 `, @@ -1597,8 +1598,8 @@ export default { inputIconContainer: { base: ` - absolute inset-y-0 - left-0 pl-3 flex + absolute inset-y-0 + left-0 pl-3 flex items-center pointer-events-none text-scale-1100 `,