diff --git a/apps/docs/public/humans.txt b/apps/docs/public/humans.txt index afe7e39f78960..08392a4c0a097 100644 --- a/apps/docs/public/humans.txt +++ b/apps/docs/public/humans.txt @@ -45,6 +45,7 @@ Deji I Div Arora Divit D Douglas Hunley +Dustin Keib Eduardo Gurgel Egor Romanov Eleftheria Trivyzaki diff --git a/apps/studio/components/interfaces/Auth/AuthProvidersFormValidation.tsx b/apps/studio/components/interfaces/Auth/AuthProvidersFormValidation.tsx index b804e61a7577a..e7dfdf7d0f331 100644 --- a/apps/studio/components/interfaces/Auth/AuthProvidersFormValidation.tsx +++ b/apps/studio/components/interfaces/Auth/AuthProvidersFormValidation.tsx @@ -448,6 +448,12 @@ const EXTERNAL_PROVIDER_APPLE = { type: 'string', isSecret: true, }, + EXTERNAL_APPLE_EMAIL_OPTIONAL: { + title: 'Allow users without an email', + description: + 'Allows the user to successfully authenticate when the provider does not return an email address.', + type: 'boolean', + }, }, validationSchema: object().shape({ EXTERNAL_APPLE_ENABLED: boolean().required(), @@ -525,6 +531,7 @@ const EXTERNAL_PROVIDER_APPLE = { then: (schema) => schema.required('At least one Client ID is required when Apple sign-in is enabled.'), }), + EXTERNAL_APPLE_EMAIL_OPTIONAL: boolean().optional(), }), misc: { iconKey: 'apple-icon', @@ -566,6 +573,12 @@ const EXTERNAL_PROVIDER_AZURE = { descriptionOptional: 'Optional', type: 'string', }, + EXTERNAL_AZURE_EMAIL_OPTIONAL: { + title: 'Allow users without an email', + description: + 'Allows the user to successfully authenticate when the provider does not return an email address.', + type: 'boolean', + }, }, validationSchema: object().shape({ EXTERNAL_AZURE_ENABLED: boolean().required(), @@ -580,6 +593,7 @@ const EXTERNAL_PROVIDER_AZURE = { otherwise: (schema) => schema, }), EXTERNAL_AZURE_URL: string().matches(urlRegex(), 'Must be a valid URL').optional(), + EXTERNAL_AZURE_EMAIL_OPTIONAL: boolean().optional(), }), misc: { iconKey: 'microsoft-icon', @@ -606,6 +620,12 @@ const EXTERNAL_PROVIDER_BITBUCKET = { type: 'string', isSecret: true, }, + EXTERNAL_BITBUCKET_EMAIL_OPTIONAL: { + title: 'Allow users without an email', + description: + 'Allows the user to successfully authenticate when the provider does not return an email address.', + type: 'boolean', + }, }, validationSchema: object().shape({ EXTERNAL_BITBUCKET_ENABLED: boolean().required(), @@ -645,6 +665,12 @@ const EXTERNAL_PROVIDER_DISCORD = { type: 'string', isSecret: true, }, + EXTERNAL_DISCORD_EMAIL_OPTIONAL: { + title: 'Allow users without an email', + description: + 'Allows the user to successfully authenticate when the provider does not return an email address.', + type: 'boolean', + }, }, validationSchema: object().shape({ EXTERNAL_DISCORD_ENABLED: boolean().required(), @@ -658,6 +684,7 @@ const EXTERNAL_PROVIDER_DISCORD = { then: (schema) => schema.required('Client Secret is required'), otherwise: (schema) => schema, }), + EXTERNAL_DISCORD_EMAIL_OPTIONAL: boolean().optional(), }), misc: { iconKey: 'discord-icon', @@ -684,6 +711,12 @@ const EXTERNAL_PROVIDER_FACEBOOK = { type: 'string', isSecret: true, }, + EXTERNAL_FACEBOOK_EMAIL_OPTIONAL: { + title: 'Allow users without an email', + description: + 'Allows the user to successfully authenticate when the provider does not return an email address.', + type: 'boolean', + }, }, validationSchema: object().shape({ EXTERNAL_FACEBOOK_ENABLED: boolean().required(), @@ -697,6 +730,7 @@ const EXTERNAL_PROVIDER_FACEBOOK = { then: (schema) => schema.required('"Facebook secret" is required'), otherwise: (schema) => schema, }), + EXTERNAL_FACEBOOK_EMAIL_OPTIONAL: boolean().optional(), }), misc: { iconKey: 'facebook-icon', @@ -723,6 +757,12 @@ const EXTERNAL_PROVIDER_FIGMA = { type: 'string', isSecret: true, }, + EXTERNAL_FIGMA_EMAIL_OPTIONAL: { + title: 'Allow users without an email', + description: + 'Allows the user to successfully authenticate when the provider does not return an email address.', + type: 'boolean', + }, }, validationSchema: object().shape({ EXTERNAL_FIGMA_ENABLED: boolean().required(), @@ -736,6 +776,7 @@ const EXTERNAL_PROVIDER_FIGMA = { then: (schema) => schema.required('Client Secret is required'), otherwise: (schema) => schema, }), + EXTERNAL_FIGMA_EMAIL_OPTIONAL: boolean().optional(), }), misc: { iconKey: 'figma-icon', @@ -762,6 +803,12 @@ const EXTERNAL_PROVIDER_GITHUB = { type: 'string', isSecret: true, }, + EXTERNAL_GITHUB_EMAIL_OPTIONAL: { + title: 'Allow users without an email', + description: + 'Allows the user to successfully authenticate when the provider does not return an email address.', + type: 'boolean', + }, }, validationSchema: object().shape({ EXTERNAL_GITHUB_ENABLED: boolean().required(), @@ -775,6 +822,7 @@ const EXTERNAL_PROVIDER_GITHUB = { then: (schema) => schema.required('Client Secret is required'), otherwise: (schema) => schema, }), + EXTERNAL_GITHUB_EMAIL_OPTIONAL: boolean().optional(), }), misc: { iconKey: 'github-icon', @@ -808,6 +856,12 @@ const EXTERNAL_PROVIDER_GITLAB = { descriptionOptional: 'Optional', type: 'string', }, + EXTERNAL_GITLAB_EMAIL_OPTIONAL: { + title: 'Allow users without an email', + description: + 'Allows the user to successfully authenticate when the provider does not return an email address.', + type: 'boolean', + }, }, validationSchema: object().shape({ EXTERNAL_GITLAB_ENABLED: boolean().required(), @@ -822,6 +876,7 @@ const EXTERNAL_PROVIDER_GITLAB = { otherwise: (schema) => schema, }), EXTERNAL_GITLAB_URL: string().matches(urlRegex(), 'Must be a valid URL').optional(), + EXTERNAL_GITLAB_EMAIL_OPTIONAL: boolean().optional(), }), misc: { iconKey: 'gitlab-icon', @@ -859,6 +914,12 @@ const EXTERNAL_PROVIDER_GOOGLE = { "Allows ID tokens with any nonce to be accepted, which is less secure. Useful in situations where you don't have access to the nonce used to issue the ID token, such as with iOS.", type: 'boolean', }, + EXTERNAL_GOOGLE_EMAIL_OPTIONAL: { + title: 'Allow users without an email', + description: + 'Allows the user to successfully authenticate when the provider does not return an email address.', + type: 'boolean', + }, }, validationSchema: object().shape({ EXTERNAL_GOOGLE_ENABLED: boolean().required(), @@ -882,6 +943,7 @@ const EXTERNAL_PROVIDER_GOOGLE = { ), }), EXTERNAL_GOOGLE_SKIP_NONCE_CHECK: boolean().required(), + EXTERNAL_GOOGLE_EMAIL_OPTIONAL: boolean().optional(), }), misc: { iconKey: 'google-icon', @@ -912,6 +974,12 @@ const EXTERNAL_PROVIDER_KAKAO = { type: 'string', isSecret: true, }, + EXTERNAL_KAKAO_EMAIL_OPTIONAL: { + title: 'Allow users without an email', + description: + 'Allows the user to successfully authenticate when the provider does not return an email address.', + type: 'boolean', + }, }, validationSchema: object().shape({ EXTERNAL_KAKAO_ENABLED: boolean().required(), @@ -925,6 +993,7 @@ const EXTERNAL_PROVIDER_KAKAO = { then: (schema) => schema.required('Client Secret Code is required'), otherwise: (schema) => schema, }), + EXTERNAL_KAKAO_EMAIL_OPTIONAL: boolean().optional(), }), misc: { iconKey: 'kakao-icon', @@ -957,6 +1026,12 @@ const EXTERNAL_PROVIDER_KEYCLOAK = { description: '', type: 'string', }, + EXTERNAL_KEYCLOAK_EMAIL_OPTIONAL: { + title: 'Allow users without an email', + description: + 'Allows the user to successfully authenticate when the provider does not return an email address.', + type: 'boolean', + }, }, validationSchema: object().shape({ EXTERNAL_KEYCLOAK_ENABLED: boolean().required(), @@ -976,6 +1051,7 @@ const EXTERNAL_PROVIDER_KEYCLOAK = { schema.matches(urlRegex(), 'Must be a valid URL').required('Realm URL is required'), otherwise: (schema) => schema.matches(urlRegex(), 'Must be a valid URL'), }), + EXTERNAL_KEYCLOAK_EMAIL_OPTIONAL: boolean().optional(), }), misc: { iconKey: 'keycloak-icon', @@ -1003,6 +1079,12 @@ const EXTERNAL_PROVIDER_LINKEDIN_OIDC = { type: 'string', isSecret: true, }, + EXTERNAL_LINKEDIN_OIDC_EMAIL_OPTIONAL: { + title: 'Allow users without an email', + description: + 'Allows the user to successfully authenticate when the provider does not return an email address.', + type: 'boolean', + }, }, validationSchema: object().shape({ EXTERNAL_LINKEDIN_OIDC_ENABLED: boolean().required(), @@ -1016,6 +1098,7 @@ const EXTERNAL_PROVIDER_LINKEDIN_OIDC = { then: (schema) => schema.required('API Secret Key is required'), otherwise: (schema) => schema, }), + EXTERNAL_LINKEDIN_OIDC_EMAIL_OPTIONAL: boolean().optional(), }), misc: { iconKey: 'linkedin-icon', @@ -1042,6 +1125,12 @@ const EXTERNAL_PROVIDER_NOTION = { type: 'string', isSecret: true, }, + EXTERNAL_NOTION_EMAIL_OPTIONAL: { + title: 'Allow users without an email', + description: + 'Allows the user to successfully authenticate when the provider does not return an email address.', + type: 'boolean', + }, }, validationSchema: object().shape({ EXTERNAL_NOTION_ENABLED: boolean().required(), @@ -1055,6 +1144,7 @@ const EXTERNAL_PROVIDER_NOTION = { then: (schema) => schema.required('OAuth client secret is required'), otherwise: (schema) => schema, }), + EXTERNAL_NOTION_EMAIL_OPTIONAL: boolean().optional(), }), misc: { iconKey: 'notion-icon', @@ -1081,6 +1171,12 @@ const EXTERNAL_PROVIDER_TWITCH = { type: 'string', isSecret: true, }, + EXTERNAL_TWITCH_EMAIL_OPTIONAL: { + title: 'Allow users without an email', + description: + 'Allows the user to successfully authenticate when the provider does not return an email address.', + type: 'boolean', + }, }, validationSchema: object().shape({ EXTERNAL_TWITCH_ENABLED: boolean().required(), @@ -1094,6 +1190,7 @@ const EXTERNAL_PROVIDER_TWITCH = { then: (schema) => schema.required('Client secret is required'), otherwise: (schema) => schema, }), + EXTERNAL_TWITCH_EMAIL_OPTIONAL: boolean().optional(), }), misc: { iconKey: 'twitch-icon', @@ -1120,6 +1217,12 @@ const EXTERNAL_PROVIDER_TWITTER = { type: 'string', isSecret: true, }, + EXTERNAL_TWITTER_EMAIL_OPTIONAL: { + title: 'Allow users without an email', + description: + 'Allows the user to successfully authenticate when the provider does not return an email address.', + type: 'boolean', + }, }, validationSchema: object().shape({ EXTERNAL_TWITTER_ENABLED: boolean().required(), @@ -1133,6 +1236,7 @@ const EXTERNAL_PROVIDER_TWITTER = { then: (schema) => schema.required('API Secret Key is required'), otherwise: (schema) => schema, }), + EXTERNAL_TWITTER_EMAIL_OPTIONAL: boolean().optional(), }), misc: { iconKey: 'twitter-icon', @@ -1159,6 +1263,12 @@ const EXTERNAL_PROVIDER_SLACK = { type: 'string', isSecret: true, }, + EXTERNAL_SLACK_EMAIL_OPTIONAL: { + title: 'Allow users without an email', + description: + 'Allows the user to successfully authenticate when the provider does not return an email address.', + type: 'boolean', + }, }, validationSchema: object().shape({ EXTERNAL_SLACK_ENABLED: boolean().required(), @@ -1172,6 +1282,7 @@ const EXTERNAL_PROVIDER_SLACK = { then: (schema) => schema.required('Client Secret is required'), otherwise: (schema) => schema, }), + EXTERNAL_SLACK_EMAIL_OPTIONAL: boolean().optional(), }), misc: { iconKey: 'slack-icon', @@ -1199,6 +1310,12 @@ const EXTERNAL_PROVIDER_SLACK_OIDC = { type: 'string', isSecret: true, }, + EXTERNAL_SLACK_OIDC_EMAIL_OPTIONAL: { + title: 'Allow users without an email', + description: + 'Allows the user to successfully authenticate when the provider does not return an email address.', + type: 'boolean', + }, }, validationSchema: object().shape({ EXTERNAL_SLACK_OIDC_ENABLED: boolean().required(), @@ -1212,6 +1329,7 @@ const EXTERNAL_PROVIDER_SLACK_OIDC = { then: (schema) => schema.required('Client Secret is required'), otherwise: (schema) => schema, }), + EXTERNAL_SLACK_OIDC_EMAIL_OPTIONAL: boolean().optional(), }), misc: { iconKey: 'slack-icon', @@ -1238,6 +1356,12 @@ const EXTERNAL_PROVIDER_SPOTIFY = { type: 'string', isSecret: true, }, + EXTERNAL_SPOTIFY_EMAIL_OPTIONAL: { + title: 'Allow users without an email', + description: + 'Allows the user to successfully authenticate when the provider does not return an email address.', + type: 'boolean', + }, }, validationSchema: object().shape({ EXTERNAL_SPOTIFY_ENABLED: boolean().required(), @@ -1251,6 +1375,7 @@ const EXTERNAL_PROVIDER_SPOTIFY = { then: (schema) => schema.required('Client Secret is required'), otherwise: (schema) => schema, }), + EXTERNAL_SPOTIFY_EMAIL_OPTIONAL: boolean().optional(), }), misc: { iconKey: 'spotify-icon', @@ -1327,6 +1452,12 @@ const EXTERNAL_PROVIDER_ZOOM = { type: 'string', isSecret: true, }, + EXTERNAL_ZOOM_EMAIL_OPTIONAL: { + title: 'Allow users without an email', + description: + 'Allows the user to successfully authenticate when the provider does not return an email address.', + type: 'boolean', + }, }, validationSchema: object().shape({ EXTERNAL_ZOOM_ENABLED: boolean().required(), @@ -1340,6 +1471,7 @@ const EXTERNAL_PROVIDER_ZOOM = { then: (schema) => schema.required('Client secret is required'), otherwise: (schema) => schema, }), + EXTERNAL_ZOOM_EMAIL_OPTIONAL: boolean().optional(), }), misc: { iconKey: 'zoom-icon', diff --git a/apps/studio/components/interfaces/Database/RestoreToNewProject/PreviousRestoreItem.tsx b/apps/studio/components/interfaces/Database/RestoreToNewProject/PreviousRestoreItem.tsx index 5a2dfd1745676..ab65a4768f943 100644 --- a/apps/studio/components/interfaces/Database/RestoreToNewProject/PreviousRestoreItem.tsx +++ b/apps/studio/components/interfaces/Database/RestoreToNewProject/PreviousRestoreItem.tsx @@ -5,15 +5,11 @@ import { CloneStatus } from 'data/projects/clone-status-query' import { TimestampInfo } from 'ui-patterns' import { StatusBadge } from './StatusBadge' -export const PreviousRestoreItem = ({ - clone, -}: { - clone: NonNullable[number] -}) => { +export const PreviousRestoreItem = ({ clone }: { clone: CloneStatus['clones'][number] }) => { if (clone.status === 'REMOVED') { return (
-
{(clone.target_project as any).name}
+
{clone.target_project?.name ?? 'Unknown project'}
@@ -28,10 +24,10 @@ export const PreviousRestoreItem = ({ } else { return ( -
{(clone.target_project as any).name}
+
{clone.target_project?.name ?? 'Unknown project'}
diff --git a/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainConfig.tsx b/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainConfig.tsx index ff61476ee0c1d..f3ee01982a244 100644 --- a/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainConfig.tsx +++ b/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainConfig.tsx @@ -5,7 +5,10 @@ import { useFlag, useParams } from 'common' import { FormHeader } from 'components/ui/Forms/FormHeader' import Panel from 'components/ui/Panel' import UpgradeToPro from 'components/ui/UpgradeToPro' -import { useCustomDomainsQuery } from 'data/custom-domains/custom-domains-query' +import { + type CustomDomainsData, + useCustomDomainsQuery, +} from 'data/custom-domains/custom-domains-query' import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query' import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import CustomDomainActivate from './CustomDomainActivate' @@ -14,7 +17,7 @@ import CustomDomainVerify from './CustomDomainVerify' import CustomDomainsConfigureHostname from './CustomDomainsConfigureHostname' import CustomDomainsShimmerLoader from './CustomDomainsShimmerLoader' -const CustomDomainConfig = () => { +export const CustomDomainConfig = () => { const { ref } = useParams() const { data: organization } = useSelectedOrganizationQuery() @@ -30,6 +33,7 @@ const CustomDomainConfig = () => { isLoading: isCustomDomainsLoading, isError, isSuccess, + status: customDomainStatus, } = useCustomDomainsQuery( { projectRef: ref }, { @@ -44,7 +48,7 @@ const CustomDomainConfig = () => { } ) - const { status, customDomain } = customDomainData || {} + const { status } = customDomainData || {} return (
@@ -99,7 +103,7 @@ const CustomDomainConfig = () => { ) : ( - {isSuccess && ( + {isSuccess ? (
{(status === '1_not_started' || status === '2_initiated' || @@ -116,6 +120,11 @@ const CustomDomainConfig = () => { )}
+ ) : ( + )}
)} @@ -123,4 +132,15 @@ const CustomDomainConfig = () => { ) } -export default CustomDomainConfig +interface CustomDomainConfigFallthroughProps { + fetchStatus: 'error' | 'success' | 'loading' + data: CustomDomainsData | undefined +} + +function CustomDomainConfigFallthrough({ fetchStatus, data }: CustomDomainConfigFallthroughProps) { + console.error(`Failing to display UI for custom domains: +Fetch status: ${fetchStatus} +Custom domain status: ${data?.status}`) + + return null +} diff --git a/apps/studio/components/interfaces/Settings/General/index.ts b/apps/studio/components/interfaces/Settings/General/index.ts index a211542638e3a..daebfc2f9e473 100644 --- a/apps/studio/components/interfaces/Settings/General/index.ts +++ b/apps/studio/components/interfaces/Settings/General/index.ts @@ -1,5 +1,5 @@ export { default as ComplianceConfig } from './ComplianceConfig/ProjectComplianceMode' -export { default as CustomDomainConfig } from './CustomDomainConfig/CustomDomainConfig' +export { CustomDomainConfig } from './CustomDomainConfig/CustomDomainConfig' export { default as DeleteProjectButton } from './DeleteProjectPanel/DeleteProjectButton' export { default as General } from './General' export { default as TransferProjectButton } from './TransferProjectPanel/TransferProjectButton' diff --git a/apps/studio/components/interfaces/Support/SupportFormV2.tsx b/apps/studio/components/interfaces/Support/SupportFormV2.tsx index 883f88881db81..3d3871bf3d1b5 100644 --- a/apps/studio/components/interfaces/Support/SupportFormV2.tsx +++ b/apps/studio/components/interfaces/Support/SupportFormV2.tsx @@ -467,6 +467,7 @@ export const SupportFormV2 = ({
- {table !== undefined && ( + {table != undefined && ( { - if (isSuccessProjects && !isFetching && !isFetchingNextPage && !!onInitialLoad) { - onInitialLoad(projects) + // isLoadingProjects is true only during initial load. If the variables for the query change (slug), isLoadingProjects + // will be true again. + if (!isLoadingProjects && isSuccessProjects) { + onInitialLoad?.(projects) } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isSuccessProjects, isFetching, isFetchingNextPage, slug]) + }, [isLoadingProjects, isSuccessProjects]) return ( diff --git a/apps/studio/static-data/integrations/firebase_wrapper/overview.md b/apps/studio/static-data/integrations/firebase_wrapper/overview.md index 9433175384d1d..aae9cdc77c288 100644 --- a/apps/studio/static-data/integrations/firebase_wrapper/overview.md +++ b/apps/studio/static-data/integrations/firebase_wrapper/overview.md @@ -1,3 +1,3 @@ Firebase is an app development platform built around non-relational technologies. The Firebase Wrapper supports connecting to below objects. -The Firebase Wrapper is aforeign data wrapper which allows you to read data from Firebase within your Postgres database. +The Firebase Wrapper is a foreign data wrapper which allows you to read data from Firebase within your Postgres database. diff --git a/apps/www/_blog/2025-10-03-1000-yc-companies.mdx b/apps/www/_blog/2025-10-03-1000-yc-companies.mdx new file mode 100644 index 0000000000000..293406893e9ae --- /dev/null +++ b/apps/www/_blog/2025-10-03-1000-yc-companies.mdx @@ -0,0 +1,103 @@ +--- +title: '1000 Y Combinator Founders Choose Supabase' +description: 'Leading startups accelerate product development with Supabase backend platform.' +author: gregorykress +image: select/2025/1000-yc-companies/og.png +thumb: select/2025/1000-yc-companies/thumb.png +launchweek: 'select-2025' +categories: + - launch-week +tags: + - select +date: '2025-10-03:10:00:00' +toc_depth: 2 +--- + +Today we’re excited to share that more than **1,000 Y Combinator companies have chosen Supabase** to build and scale their products. These companies include some of the most innovative startups in the world today, including [Resend](https://supabase.com/customers/resend), [Quivr](https://supabase.com/customers/quivr), and [Markprompt](https://supabase.com/customers/markprompt). **In the most recent Y Combinator batch, 55% of companies chose to build on Supabase**. + +Y Combinator (YC) is the world’s most influential startup accelerator, known for backing companies like Airbnb, Stripe, and Dropbox at their earliest stages (including Supabase!). Its model of intensive mentorship, a powerful alumni network, and direct access to top investors has made it the gold standard for launching high-growth technology startups. + +Likewise, Supabase was built to help the fastest and most ambitious builders. We are proud to be the platform of choice for YC companies. + +## 1,000 YC companies on Supabase + +If you are building your startup on Supabase, you are in good company. Supabase has become the backend of choice for over 1,000 Y Combinator companies. These companies encompass all types of industries, including AI, developer platforms, marketplaces, B2B SaaS, consumer products, and much more. With Supabase, founders can ship product and scale quickly: + +- **Launch fast**: Database, storage and auth solution out of the box. +- **Flexibility**: Iterate quickly leveraging the suite of tools on the platform. +- **Scale**: Grow from prototype to production without retooling. + +Some of the companies built on Supabase include: + +Leaping AI + +Leaping AI chose Supabase for scalability. + + + Supabase makes Postgres management and scaling very easy. Integration with auth also simplifies a + lot of things and get you running quickly. Supabase — supagood. + + +Cekura + +Cekura AI chose Supabase for security. + + + We were up and running with Supabase in no time. The combination of easy setup and + production-ready auth gave us the confidence to focus on our product instead of infrastructure. + For a startup, that speed makes all the difference. + + +Zaymo + +Zaymo chose Supabase for speed. + + + Supabase has been game-changing for us. It was the obvious choice to start out, and it has scaled + with us. Every time I start thinking it might be time to switch off, they launch a new feature or + I find an extension that is exactly what I need. It has literally saved me weeks of time. + + +Cheers + +Cheers chose Supabase right from the start. + + + We've been building on Supabase since day 1 and absolutely love it. We'd die before we switch off + Supabase. + + +## A platform for builders + +The most important part of finding product market fit is getting products in the hands of your customers as fast as possible and iterating on their feedback until you find something that works. Supabase is a fully functional back end out of the box, with all the power of Postgres under the hood. Developers and non-developers alike can start in minutes, using an integrated suite of tools, and scaling without retooling or vendor lock-in. + +- [Database](https://supabase.com/database), [Auth](https://supabase.com/auth), [Storage](https://supabase.com/storage), [Edge Functions](https://supabase.com/edge-functions), [Realtime](https://supabase.com/realtime), and [Vector](https://supabase.com/modules/vector) search. +- Seamless integration with popular frameworks. +- Predictable pricing that scales with usage. +- World-class support. + +Startups that choose Supabase can build and scale their product without the backend bottleneck. + +## Builders are everywhere + +Of course, you don’t need to be backed by Y Combinator to build a successful startup. Fast-growing companies like [Udio](https://supabase.com/customers/udio), [Euka](https://supabase.com/customers/euka), and [Pebblely](https://supabase.com/customers/pebblely) are also built on Supabase. Supabase is proud to partner with more than 80 other startup accelerators and early-stage investors across the global startup ecosystem, a program that we are rapidly expanding. Why? Because we believe in the power of builders to change the world - and we want to help you build faster! diff --git a/apps/www/_blog/2025-10-03-login-with-solana-ethereum.mdx b/apps/www/_blog/2025-10-03-login-with-solana-ethereum.mdx new file mode 100644 index 0000000000000..a0617744510dd --- /dev/null +++ b/apps/www/_blog/2025-10-03-login-with-solana-ethereum.mdx @@ -0,0 +1,110 @@ +--- +title: 'gm 👋 web3, welcome aboard to Sign in with Web3 (Solana, Ethereum)' +description: 'Ethereum and Solana wallet authentication now supported in Supabase Auth.' +author: stojan +image: select/2025/login-w-solana-ethereum/og.png +thumb: select/2025/login-w-solana-ethereum/thumb.png +launchweek: 'select-2025' +categories: + - launch-week +tags: + - select +date: '2025-10-03:10:00:00' +toc_depth: 2 +--- + +Today we're announcing [support for Web3 logins using Ethereum and Solana](https://supabase.com/docs/guides/auth/auth-web3). This has been one of the historically most requested features for Supabase. + +It's all based on the widely adopted [Sign in with Ethereum standard (EIP-4361)](https://eips.ethereum.org/EIPS/eip-4361), which both Ethereum and Solana off-chain wallet authentication is based on. This protocol is widely adopted across all of the popular wallet applications (both software and hardware) today, so building a Web3 application on top of Supabase has never been easier. + +## How does it work? + +We wanted to make it simple. The Sign in with Ethereum standard defines a particular message structure, one that looks like so: + +``` +example.com wants you to sign in with your Ethereum account: +0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 + +I accept the ExampleOrg Terms of Service: + +URI: +Version: 1 +Chain ID: 1 +Nonce: 32891756 +Issued At: 2021-09-30T16:25:24Z +Resources: +- +``` + +It's interpreted both by the wallet application, which presents a secure login confirmation dialog, while also being validated by Supabase Auth before issuing a user session. + +Most of these details are already handled for you by the Supabase JavaScript SDK, so it's really as simple as calling this in your Web3 app: + +```tsx +await supabase.auth.signInWithWeb3({ + chain: 'ethereum', // or 'solana' + statement: 'I <3 Supabase!', +}) +``` + +The API is powerful enough to support more modern approaches to building Web3 applications such as using the [Solana Wallet Adapter](https://solana.com/developers/courses/intro-to-solana/interact-with-wallets#solanas-wallet-adapter) system or the [Ethereum Wallet Discovery Mechanism](https://docs.metamask.io/wallet/tutorials/react-dapp-local-state). + +You can configure these on the Supabase Dashboard, or in the Supabase CLI: + +```toml +[auth.web3.solana] +enabled = true + +[auth.web3.ethereum] +enabled = true + +``` + +Don't forget to configure rate-limits and CAPTCHA, as Web3 apps are usually more prone to abuse by bots: + +```toml +[auth.rate_limit] +# Number of Web3 logins that can be made in a 5 minute interval per IP address. +web3 = 30 + +[auth.captcha] +enabled = true +provider = "hcaptcha" # or other supported providers +secret = "0x0000000000000000000000000000000000000000" + +``` + +## How we built it? + +At Supabase we cherish our community and our contributors. For this feature, we asked our community for help by co-sponsoring a bounty with the Solana Foundation. We asked them to [help us find a contributor](https://x.com/nickfrosty/status/1880046815950836179) who knows the ecosystem well to help us launch: +![request for contributors](/images/blog/select/2025/login-w-solana-ethereum/twitter-nickfrosty.png) + +And we [found](https://x.com/Bewinxed/status/1880148679165976930) someone great! + +![Omar (Bewinxed) twitter answer](/images/blog/select/2025/login-w-solana-ethereum/twitter-bewinxed.png) + + + +Being in the Web3 space, specifically in Solana since 2021, I've used Supabase on a few projects. So as soon as I saw the tweet saying Supabase needed help implementing Sign in with Solana, I had to jump in! + +It was interesting seeing the difference when building for Supabase scale, as opposed to building small personal projects. We put in a lot of effort to provide the Web3 community with the great DX Supabase is known for, security and standards compliance. + + + +Once we made Sign in with Solana available in April, we decided to further our collaboration and continue working on the Sign in with Ethereum implementation. Omar has continued working with us on other exciting features coming soon! + +## Start using Sign in with Web3 today + +Real-world use cases for Web3 authentication are already here. Developers are using wallet-based sign-in to power: + +- NFT marketplaces where collectors can trade digital assets securely +- DAOs that rely on wallet verification for membership and voting +- Token-gated applications that unlock features based on wallet contents +- DeFi dashboards that let users manage assets without creating yet another password + +You can get started right now: + +- Check out the [docs for Sign in with Web3](https://supabase.com/docs/guides/auth/auth-web3) +- [Sign up for Supabase](https://www.supabase.com/dashboard) and try it in your project + +We can’t wait to see what you build. diff --git a/apps/www/_blog/2025-10-03-remote-mcp-server.mdx b/apps/www/_blog/2025-10-03-remote-mcp-server.mdx new file mode 100644 index 0000000000000..fdcb0bc33cf2a --- /dev/null +++ b/apps/www/_blog/2025-10-03-remote-mcp-server.mdx @@ -0,0 +1,136 @@ +--- +title: 'Announcing the Supabase Remote MCP Server' +description: 'Remote MCP server enables AI agents to connect with Supabase projects.' +author: gregnr +image: select/2025/remote-mcp-server/og.png +thumb: select/2025/remote-mcp-server/thumb.png +launchweek: 'select-2025' +categories: + - launch-week +tags: + - select +date: '2025-10-03:10:00:00' +toc_depth: 2 +--- + +Today we are launching our remote MCP server, allowing you to connect your Supabase projects with _many_ more AI agents than before, including ChatGPT, Claude, and Builder.io. We also added support for MCP auth (OAuth2), a faster and more secure way to connect agents with your Supabase account (via browser-based authentication). Last but not least, we’re adding official MCP support for local Supabase instances created through the [CLI](https://supabase.com/docs/guides/local-development/cli/getting-started). + +Now all you need is a single URL to connect your favorite AI agent to Supabase: + +``` +https://mcp.supabase.com/mcp +``` + +Or if you’re running Supabase locally: + +```bash +http://localhost:54321/mcp +``` + +On top of this, we're adding even more tools to Supabase MCP that we hope will make you more productive. + +## What is MCP? + +MCP stands for [Model Context Protocol](https://modelcontextprotocol.io/). It standardizes how Large Language Models (LLMs) talk to platforms like Supabase. We released the initial version of our Supabase MCP server back in April which allowed folks to connect their favorite AI tools (like [Cursor](https://www.cursor.com/) or [Claude Code](https://docs.anthropic.com/en/docs/claude-code/overview)) directly with Supabase. Since launch, we've added many new features: + +- Fetching and deploying Edge Functions +- Fetching logs from any service in the Supabase stack +- Scoping the server to only one project +- Putting the server in read-only mode (implemented at the Postgres role level) + +Today we are adding even more tools to the tool belt, along with a new way to connect: Remote HTTP. + +## What is remote MCP? + +The MCP protocol supports 2 official methods for running servers, known as transports: + +- **stdio:** The MCP server runs directly on your local machine (using a runtime like `npx`) and communicates over a standard I/O interface. This was the transport used by most MCP servers originally, including Supabase. +- **Remote (HTTP):** The MCP server runs remotely over an HTTP web server. + +When we first launched the Supabase MCP server, the HTTP transport was going through some spec changes which many clients didn't support yet (streamable HTTP). We wanted to support all clients immediately without investing a ton of time into an unstable transport, so we released our server as an `stdio` MCP server. To run this, you needed to install Node.js and configuring your MCP client with this `npx` command: + +``` +npx -y @supabase/mcp-server-supabase@latest ... +``` + +This worked great at the time, because it meant that folks could connect their AI agents with Supabase immediately without a lot of infrastructure work on our end. But it came with some downsides: + +1. **Limited MCP clients:** Most web-based AI agents (like ChatGPT, Claude.ai, Builder.io) are limited to HTTP-based MCP servers due to the environments they run in. APIs like OpenAI's Response API also [have support for MCP](https://platform.openai.com/docs/guides/tools-remote-mcp) - but only with remote MCP servers, not `stdio`. +2. **Authentication was clunky:** Folks needed to manually generate a personal access token (PAT) in order to authenticate with their Supabase account which added friction to the setup experience and not very secure (it was easy to accidentally commit this to source control). +3. **Errors were hard to debug:** Not only did everyone need Node.js installed to run the server, they also needed to make sure their environment was configured correctly so that the correct version was used by each client (if you used `nvm`). Every operating system also had slight differences that required modifying the `npx` command accordingly. + +On the other hand, Remote MCP only requires a single URL: + +```bash +https://mcp.supabase.com/mcp + +# or http://localhost:54321/mcp for local +``` + +We built this interactive widget to help you connect popular MCP clients to Supabase and customize the URL to your preferences (like project-scoped mode and read-only mode): + +{/* __ */} + +## New features + +Our philosophy on Supabase MCP comes down to two ideas: + +1. Supabase MCP should be used for development. It was designed from the beginning to assist with app development and shouldn’t be connected to production databases. See our post on [Defense in Depth for MCP Servers](https://supabase.com/blog/defense-in-depth-mcp). +2. MCP is just another way to access the same platform features that you already use in the web dashboard and CLI. But - since it’s being used by an LLM, it should also lean into the strengths of an AI-first UX. + +With these in mind, we added the following new features to assist AI agents while they help build your app: + +- Feature groups +- Doc search +- Security and performance advisors +- Storage + +### Feature groups + +Feature groups allow you to pick and choose which tools you want to expose to your agent. This is useful in two ways: + +1. **Security:** if you know that you never want your agent to deploy edge functions, you can remove the `functions` feature group so that those tools are never exposed to the LLM. +2. **Tool limits:** many MCP clients limit the number of tools you can connect to them, so feature groups allow you to only connect the tools that you use regularly. + +Today we support the following feature groups: + +- [`account`](https://github.com/supabase-community/supabase-mcp#account) +- [`docs`](https://github.com/supabase-community/supabase-mcp#knowledge-base) +- [`database`](https://github.com/supabase-community/supabase-mcp#database) +- [`debugging`](https://github.com/supabase-community/supabase-mcp#debugging) +- [`development`](https://github.com/supabase-community/supabase-mcp#development) +- [`functions`](https://github.com/supabase-community/supabase-mcp#edge-functions) +- [`storage`](https://github.com/supabase-community/supabase-mcp#storage) +- [`branching`](https://github.com/supabase-community/supabase-mcp#branching-experimental-requires-a-paid-plan) + +See the [MCP docs](https://supabase.com/docs/guides/getting-started/mcp) for instructions on how to enable or disable these groups. + +### Doc search + +A big challenge with LLMs is knowledge cutoff. Early LLMs had a _pretty good_ understanding of Supabase, but it was still nowhere near complete or up-to-date. Now the latest leading LLMs have a _very good_ understanding of Supabase, but will still lag behind any new features, bug fixes, or other updates that we make. + +To help with this, we added a new tool to Supabase MCP: `search_docs`. This tool exposes the latest up-to-date Supabase docs powered by our Content API - a GraphQL based search API that uses [hybrid search](https://supabase.com/docs/guides/ai/hybrid-search) (semantic + keyword) to find relevant documentation for a given query (formatted as markdown). + +The result ends up looking like similar to [self-RAG](https://arxiv.org/abs/2310.11511): whenever your agent needs clarification on a topic, it can use this tool to find the most relevant Supabase documentation. + +### Security and performance advisors + +How do you know if LLMs are really following best coding practices? When a project reaches even a moderate level of complexity, the amount of context and moving parts becomes a real challenge to navigate, even for humans. + +Our solution is a feature that already exists on our platform - advisors. [Advisors](https://supabase.com/dashboard/project/_/advisors/security) are essentially lints on your database that help you follow security and performance best practices. We added a new `get_advisors` MCP tool that fetches these same advisors so that your agent can both discover and fix any outstanding issues on your database. + +### Storage + +We also added initial support for [Supabase Storage](https://supabase.com/docs/guides/storage) on our MCP server. This first version allows your agent to see which buckets exist on your project and update their configuration, but in the future we’ll look into more abilities like listing files and their details. + +This feature was actually a community contribution (thanks [Nico](https://github.com/Ngineer101)!). If there are ever missing features that you’d like to see, [PR’s](https://github.com/supabase-community/supabase-mcp/issues/new/choose) are always welcome! + +## What’s next? + +We have more exciting plans for MCP at Supabase: + +1. **Security:** Today our OAuth2 implementation requires you to make a binary decision on permissions: either grant _all_ permissions to your MCP client, or _none_. This isn’t ideal if you know that you never want to, say, allow your client to access to your Edge Functions. + +To improve this, we’re working to support fine-grain permissions that can be toggled during authorization. It’s a big task to re-work our permission infrastructure to support this, but we believe it’s worth it. 2. **Double down on local:** We’re very excited to support local Supabase instances in this release, but we also believe there is a lot more that can be done. Supabase MCP is designed to be used for development, so we want the local experience to be first-class. 3. **Build your own MCP:** You might have thought about building _your own_ MCP server on top of Supabase. We’re using the playbook and lessons learned from our own MCP server to provide the tools you need to do the same - including remote MCP and auth. Stay tuned! + +We’re keen to continue investing in MCP and excited to see how you use these new features! diff --git a/apps/www/_blog/2025-10-03-supabase-series-e.mdx b/apps/www/_blog/2025-10-03-supabase-series-e.mdx new file mode 100644 index 0000000000000..ffcd572048c4f --- /dev/null +++ b/apps/www/_blog/2025-10-03-supabase-series-e.mdx @@ -0,0 +1,24 @@ +--- +title: 'Supabase Series E' +description: 'Raised funding from Accel, Peak XV, Figma, and existing investors.' +author: paul_copplestone +image: select/2025/announcing-series-e/og.png +thumb: select/2025/announcing-series-e/thumb.png +launchweek: 'select-2025' +categories: + - launch-week +tags: + - select +date: '2025-10-03:12:00:00' +toc_depth: 2 +--- + +Supabase has raised a Series E from insiders, led by Accel and Peak XV. Figma has joined the round with all of existing investors: YC, Coatue, Felicis, Craft, and Square Peg. + +We raised $120 at a $5B pre-money valuation. One of the ways we will use the money is for employee secondaries: every single round we have allowed our employees to sell 25% of their vested stock. This round is no different, and we will continue to do this for future rounds. + +Additionally, we are accelerating hiring for key open source initiatives like [Multigres](https://supabase.com/blog/multigres-vitess-for-postgres) and [OrioleDB](https://supabase.com/blog/supabase-acquires-oriole). Supabase is home to over 30 ex-founders. We are 100% distributed, with no offices, spread across 37 countries. We are a group of humans who are focused on doing their best work. If that sounds like a place you want to work, apply today: + +[supabase.com/careers](https://supabase.com/careers) + +One more thing: our community continues to grow it’s one of the things Ant & I are most proud of. This time, we wanted to allow Supabase and Postgres contributors to invest. In the coming months we will do a $1M community round open to early customers and contributors. diff --git a/apps/www/components/Announcement/Badge.tsx b/apps/www/components/Announcement/Badge.tsx index 052088e3e7eee..41df7114f1651 100644 --- a/apps/www/components/Announcement/Badge.tsx +++ b/apps/www/components/Announcement/Badge.tsx @@ -32,6 +32,7 @@ const AnnouncementBadge = ({ className={cn( ` announcement-link + text-nowrap group/announcement relative flex flex-row diff --git a/apps/www/lib/authors.json b/apps/www/lib/authors.json index 6e5af52174d17..60f1ec884e8e6 100644 --- a/apps/www/lib/authors.json +++ b/apps/www/lib/authors.json @@ -684,5 +684,12 @@ "position": "CSO", "author_url": "#", "author_image_url": "/images/blog/avatars/bilharmer.jpg" + }, + { + "author_id": "gregorykress", + "author": "Greg Kress", + "position": "Founder Advocate", + "author_url": "https://www.linkedin.com/in/gregorykress", + "author_image_url": "/images/blog/avatars/gregorykress.jpg" } ] diff --git a/apps/www/public/images/blog/avatars/arkadiy-telegin.jpg b/apps/www/public/images/blog/avatars/arkadiy-telegin.jpg new file mode 100644 index 0000000000000..2523f4741b809 Binary files /dev/null and b/apps/www/public/images/blog/avatars/arkadiy-telegin.jpg differ diff --git a/apps/www/public/images/blog/avatars/danny-jones.jpg b/apps/www/public/images/blog/avatars/danny-jones.jpg new file mode 100644 index 0000000000000..86dad76dadc5d Binary files /dev/null and b/apps/www/public/images/blog/avatars/danny-jones.jpg differ diff --git a/apps/www/public/images/blog/avatars/dylan-allen.jpg b/apps/www/public/images/blog/avatars/dylan-allen.jpg new file mode 100644 index 0000000000000..ab256392dd188 Binary files /dev/null and b/apps/www/public/images/blog/avatars/dylan-allen.jpg differ diff --git a/apps/www/public/images/blog/avatars/gregorykress.jpg b/apps/www/public/images/blog/avatars/gregorykress.jpg new file mode 100644 index 0000000000000..23f605ffbd70c Binary files /dev/null and b/apps/www/public/images/blog/avatars/gregorykress.jpg differ diff --git a/apps/www/public/images/blog/avatars/omar-bewinxed.jpg b/apps/www/public/images/blog/avatars/omar-bewinxed.jpg new file mode 100644 index 0000000000000..a0b803069a7b4 Binary files /dev/null and b/apps/www/public/images/blog/avatars/omar-bewinxed.jpg differ diff --git a/apps/www/public/images/blog/avatars/sidhant-kabra.jpg b/apps/www/public/images/blog/avatars/sidhant-kabra.jpg new file mode 100644 index 0000000000000..39cfc127b6a64 Binary files /dev/null and b/apps/www/public/images/blog/avatars/sidhant-kabra.jpg differ diff --git a/apps/www/public/images/blog/select/2025/1000-yc-companies/cekura.png b/apps/www/public/images/blog/select/2025/1000-yc-companies/cekura.png new file mode 100644 index 0000000000000..d438c705b3679 Binary files /dev/null and b/apps/www/public/images/blog/select/2025/1000-yc-companies/cekura.png differ diff --git a/apps/www/public/images/blog/select/2025/1000-yc-companies/cheers.png b/apps/www/public/images/blog/select/2025/1000-yc-companies/cheers.png new file mode 100644 index 0000000000000..2f7f11625caf0 Binary files /dev/null and b/apps/www/public/images/blog/select/2025/1000-yc-companies/cheers.png differ diff --git a/apps/www/public/images/blog/select/2025/1000-yc-companies/leaping-ai.png b/apps/www/public/images/blog/select/2025/1000-yc-companies/leaping-ai.png new file mode 100644 index 0000000000000..d14d9d558b620 Binary files /dev/null and b/apps/www/public/images/blog/select/2025/1000-yc-companies/leaping-ai.png differ diff --git a/apps/www/public/images/blog/select/2025/1000-yc-companies/og.png b/apps/www/public/images/blog/select/2025/1000-yc-companies/og.png new file mode 100644 index 0000000000000..77f48cb78254c Binary files /dev/null and b/apps/www/public/images/blog/select/2025/1000-yc-companies/og.png differ diff --git a/apps/www/public/images/blog/select/2025/1000-yc-companies/thumb.png b/apps/www/public/images/blog/select/2025/1000-yc-companies/thumb.png new file mode 100644 index 0000000000000..29f6414c1c1ef Binary files /dev/null and b/apps/www/public/images/blog/select/2025/1000-yc-companies/thumb.png differ diff --git a/apps/www/public/images/blog/select/2025/1000-yc-companies/zaymo.png b/apps/www/public/images/blog/select/2025/1000-yc-companies/zaymo.png new file mode 100644 index 0000000000000..8c858ddfc7214 Binary files /dev/null and b/apps/www/public/images/blog/select/2025/1000-yc-companies/zaymo.png differ diff --git a/apps/www/public/images/blog/select/2025/announcing-series-e/og.png b/apps/www/public/images/blog/select/2025/announcing-series-e/og.png new file mode 100644 index 0000000000000..11b340d5a7763 Binary files /dev/null and b/apps/www/public/images/blog/select/2025/announcing-series-e/og.png differ diff --git a/apps/www/public/images/blog/select/2025/announcing-series-e/thumb.png b/apps/www/public/images/blog/select/2025/announcing-series-e/thumb.png new file mode 100644 index 0000000000000..e5f6e3d7dea07 Binary files /dev/null and b/apps/www/public/images/blog/select/2025/announcing-series-e/thumb.png differ diff --git a/apps/www/public/images/blog/select/2025/login-w-solana-ethereum/og.png b/apps/www/public/images/blog/select/2025/login-w-solana-ethereum/og.png new file mode 100644 index 0000000000000..b219feaad636c Binary files /dev/null and b/apps/www/public/images/blog/select/2025/login-w-solana-ethereum/og.png differ diff --git a/apps/www/public/images/blog/select/2025/login-w-solana-ethereum/thumb.png b/apps/www/public/images/blog/select/2025/login-w-solana-ethereum/thumb.png new file mode 100644 index 0000000000000..6d3099a763b10 Binary files /dev/null and b/apps/www/public/images/blog/select/2025/login-w-solana-ethereum/thumb.png differ diff --git a/apps/www/public/images/blog/select/2025/login-w-solana-ethereum/twitter-bewinxed.png b/apps/www/public/images/blog/select/2025/login-w-solana-ethereum/twitter-bewinxed.png new file mode 100644 index 0000000000000..a06f8359d4c1c Binary files /dev/null and b/apps/www/public/images/blog/select/2025/login-w-solana-ethereum/twitter-bewinxed.png differ diff --git a/apps/www/public/images/blog/select/2025/login-w-solana-ethereum/twitter-nickfrosty.png b/apps/www/public/images/blog/select/2025/login-w-solana-ethereum/twitter-nickfrosty.png new file mode 100644 index 0000000000000..1c20cafeb0701 Binary files /dev/null and b/apps/www/public/images/blog/select/2025/login-w-solana-ethereum/twitter-nickfrosty.png differ diff --git a/apps/www/public/images/blog/select/2025/remote-mcp-server/og.png b/apps/www/public/images/blog/select/2025/remote-mcp-server/og.png new file mode 100644 index 0000000000000..24f575e6f3eff Binary files /dev/null and b/apps/www/public/images/blog/select/2025/remote-mcp-server/og.png differ diff --git a/apps/www/public/images/blog/select/2025/remote-mcp-server/thumb.png b/apps/www/public/images/blog/select/2025/remote-mcp-server/thumb.png new file mode 100644 index 0000000000000..2b8330ba3b634 Binary files /dev/null and b/apps/www/public/images/blog/select/2025/remote-mcp-server/thumb.png differ diff --git a/package.json b/package.json index d532c33d6f39c..27bd203d3635b 100644 --- a/package.json +++ b/package.json @@ -62,17 +62,6 @@ "type": "git", "url": "git+https://github.com/supabase/supabase.git" }, - "pnpm": { - "overrides": { - "@supabase/supabase-js>@supabase/auth-js": "catalog:", - "@tanstack/directive-functions-plugin>vite": "catalog:", - "@tanstack/react-start-plugin>vite": "catalog:", - "esbuild": "^0.25.2", - "@redocly/respect-core>form-data": "^4.0.4", - "tmp": "^0.2.4" - }, - "neverBuiltDependencies": ["libpg-query"] - }, "engines": { "pnpm": ">=10.16", "node": ">=22" diff --git a/packages/ui-patterns/src/Banners/SelectBanner.tsx b/packages/ui-patterns/src/Banners/SelectBanner.tsx index 0a763f251855d..22ac3d92d43ad 100644 --- a/packages/ui-patterns/src/Banners/SelectBanner.tsx +++ b/packages/ui-patterns/src/Banners/SelectBanner.tsx @@ -3,8 +3,12 @@ import Link from 'next/link' export function SelectBanner() { const selectSiteUrl = 'https://select.supabase.com/' - const desc = ['Our first user conference', 'Oct 3 2025', 'Guillermo Rauch, Dylan Field, and more'] - const cta = 'Save your seat' + const desc = [ + 'Our first user conference', + 'Oct 3 2025', + 'Patrick Collison, Dylan Field, and more', + ] + const cta = 'Watch live' const baseStyles = 'flex flex-col justify-center border-l border-muted py-8 ' const textBlockStyles = diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 397ad1df060e7..8bee5b77bd360 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,31 +1,56 @@ packages: - - 'apps/*' - - 'packages/*' - - 'blocks/*' - - 'e2e/*' + - apps/* + - packages/* + - blocks/* + - e2e/* catalog: - '@types/node': ^22.0.0 - '@types/react': '^18.3.0' - '@types/react-dom': '^18.3.0' '@supabase/auth-js': 2.72.0-rc.11 - '@supabase/supabase-js': ^2.47.14 '@supabase/realtime-js': ^2.11.3 - 'next': ^15.5.2 - 'react': '^18.3.0' - 'react-dom': '^18.3.0' - 'tailwindcss': '3.4.1' - 'typescript': '~5.9.0' - 'valtio': '^1.12.0' - 'vite': '^6.2.7' - 'zod': '^3.25.76' + '@supabase/supabase-js': ^2.47.14 + '@types/node': ^22.0.0 + '@types/react': ^18.3.0 + '@types/react-dom': ^18.3.0 + next: ^15.5.2 + react: ^18.3.0 + react-dom: ^18.3.0 + tailwindcss: 3.4.1 + typescript: ~5.9.0 + valtio: ^1.12.0 + vite: ^6.2.7 + zod: ^3.25.76 + +ignoredBuiltDependencies: + - '@parcel/watcher' + - '@sentry/cli' + - contentlayer2 + - core-js + - es5-ext + - esbuild + - libpg-query + - msw + - node-pty + - protobufjs + - sharp minimumReleaseAge: 10080 + minimumReleaseAgeExclude: - - 'ai' + - ai - '@ai-sdk/*' - '@supabase/mcp-server-supabase' - '@supabase/mcp-utils' - - '@supabase/auth-js' + - '@supabase/auth-js' - '@supabase/supabase-js' - '@supabase/realtime-js' + +onlyBuiltDependencies: + - supabase + +overrides: + '@redocly/respect-core>form-data': ^4.0.4 + '@supabase/supabase-js>@supabase/auth-js': 'catalog:' + '@tanstack/directive-functions-plugin>vite': 'catalog:' + '@tanstack/react-start-plugin>vite': 'catalog:' + esbuild: ^0.25.2 + tmp: ^0.2.4