mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 17:35:10 +03:00
## Summary
The `homeNew` PostHog experiment has concluded. This PR graduates it by
making the new homepage (`ProjectHome`, formerly `HomeV2`) the permanent
default for all users, and removes all dead code from the old
experiment.
## Changes
- Remove `homeNew` PostHog feature flag checks and `home_new` experiment
exposure tracking from 3 files
- Rename `HomeNew/` → `ProjectHome/` directory and `HomeV2` →
`ProjectHome` export
- Delete old `Home/Home.tsx` component (shared components like
`ProjectList/` are kept — still used by org pages)
- Delete `pages/project/[ref]/building.tsx` and add a server-side
redirect from `/project/:ref/building` → `/project/:ref` to prevent 404s
during rollout (old cached JS bundles may still route to `/building`)
- Simplify `ContentWrapper` building-state logic in `ProjectLayout` —
always redirect building projects to home, always suppress building
interstitial on home page
- Always route to `/project/{ref}` after project creation (remove
`/building` path)
- Update all Observability imports from `HomeNew` → `ProjectHome`
## Self-hosted behavior change
Self-hosted Studio previously showed the old `Home` component (client
libraries + example projects) since PostHog flags don't load. This PR
changes self-hosted to show `ProjectHome` (TopSection with service
status + instance diagram, advisor, custom reports). All sections query
backend APIs that exist on self-hosted. E2E tests pass against the
self-hosted build.
## Testing
- [x] `pnpm turbo run build --filter=studio` passes
- [x] No remaining references to `homeNew`, `home_new`, or `HomeNew` in
codebase
- [x] No broken imports to deleted files
- [x] Self-hosted E2E tests pass (145 passed, 1 flaky, 4 skipped)
- [x] `/building` redirect added to both platform and self-hosted config
blocks
**Quick test:**
1. Navigate to any project homepage — should render the ProjectHome
component
2. Create a new project — should redirect to `/project/{ref}` (not
`/building`)
3. Visit a project in `COMING_UP` state on a non-home route — should
redirect to home
4. Visit `/project/{ref}/building` directly — should 302 redirect to
`/project/{ref}`
## Linear
- fixes GROWTH-671
379 lines
14 KiB
TypeScript
379 lines
14 KiB
TypeScript
import { DOCS_URL } from 'lib/constants'
|
|
import { BarChart3, Code, Database, GitBranch, Shield, Table, Upload, UserPlus } from 'lucide-react'
|
|
import { AiIconAnimation, CodeBlock } from 'ui'
|
|
|
|
import type { GettingStartedAction, GettingStartedStep } from './GettingStarted.types'
|
|
import type { GettingStartedStatuses } from './useGettingStartedProgress'
|
|
|
|
type BuildStepsBaseArgs = {
|
|
ref: string | undefined
|
|
openAiChat: (name: string, initialInput: string) => void
|
|
connectActions: GettingStartedAction[]
|
|
statuses: GettingStartedStatuses
|
|
}
|
|
|
|
type BuildCodeStepsArgs = BuildStepsBaseArgs
|
|
|
|
type BuildNoCodeStepsArgs = BuildStepsBaseArgs
|
|
|
|
export const getCodeWorkflowSteps = ({
|
|
ref,
|
|
openAiChat,
|
|
connectActions,
|
|
statuses,
|
|
}: BuildCodeStepsArgs): GettingStartedStep[] => {
|
|
const {
|
|
hasTables,
|
|
hasCliSetup,
|
|
hasSampleData,
|
|
hasRlsPolicies,
|
|
hasAppConnected,
|
|
hasFirstUser,
|
|
hasStorageObjects,
|
|
hasEdgeFunctions,
|
|
hasReports,
|
|
hasGitHubConnection,
|
|
} = statuses
|
|
|
|
return [
|
|
{
|
|
key: 'install-cli',
|
|
status: hasCliSetup ? 'complete' : 'incomplete',
|
|
title: 'Install the Supabase CLI',
|
|
icon: <Code strokeWidth={1} className="text-foreground-muted" size={16} />,
|
|
description:
|
|
'To get started, install the Supabase CLI—our command-line toolkit for managing projects locally, handling migrations, and seeding data—using the npm command below to add it to your workspace.',
|
|
actions: [
|
|
{
|
|
label: 'Install via npm',
|
|
component: (
|
|
<CodeBlock className="w-full text-xs p-3 !bg" language="bash">
|
|
npm install supabase --save-dev
|
|
</CodeBlock>
|
|
),
|
|
},
|
|
],
|
|
},
|
|
{
|
|
key: 'design-db',
|
|
status: hasTables ? 'complete' : 'incomplete',
|
|
title: 'Design your database schema',
|
|
icon: <Database strokeWidth={1} className="text-foreground-muted" size={16} />,
|
|
description:
|
|
'Next, create a schema file that defines the structure of your database, either following our declarative schema guide or asking the AI assistant to generate one for you.',
|
|
actions: [
|
|
{
|
|
label: 'Create schema file',
|
|
href: `${DOCS_URL}/guides/local-development/declarative-database-schemas`,
|
|
variant: 'default',
|
|
},
|
|
{
|
|
label: 'Generate it',
|
|
variant: 'default',
|
|
icon: <AiIconAnimation size={14} />,
|
|
onClick: () =>
|
|
openAiChat(
|
|
'Design my database',
|
|
'Help me create a schema file for my database. We will be using Supabase declarative schemas which you can learn about by searching docs for declarative schema.'
|
|
),
|
|
},
|
|
],
|
|
},
|
|
{
|
|
key: 'add-data',
|
|
status: hasSampleData ? 'complete' : 'incomplete',
|
|
title: 'Seed your database with data',
|
|
icon: <Table strokeWidth={1} className="text-foreground-muted" size={16} />,
|
|
description:
|
|
'Now, create a seed file to populate your database with initial data, using the docs for guidance or letting the AI assistant draft realistic inserts.',
|
|
actions: [
|
|
{
|
|
label: 'Create a seed file',
|
|
href: `${DOCS_URL}/guides/local-development/seeding-your-database`,
|
|
variant: 'default',
|
|
},
|
|
{
|
|
label: 'Generate data',
|
|
variant: 'default',
|
|
icon: <AiIconAnimation size={14} />,
|
|
onClick: () =>
|
|
openAiChat(
|
|
'Generate seed data',
|
|
'Generate SQL INSERT statements for realistic seed data that I can run via the Supabase CLI.'
|
|
),
|
|
},
|
|
],
|
|
},
|
|
{
|
|
key: 'add-rls-policies',
|
|
status: hasRlsPolicies ? 'complete' : 'incomplete',
|
|
title: 'Secure your data with RLS policies',
|
|
icon: <Shield strokeWidth={1} className="text-foreground-muted" size={16} />,
|
|
description:
|
|
"Let's secure your data by enabling Row Level Security (per-row access rules that decide who can read or write specific records) and defining policies in a migration file, either configuring them manually or letting the AI assistant draft policies for your tables.",
|
|
actions: [
|
|
{
|
|
label: 'Create a migration file',
|
|
href: `/project/${ref}/auth/policies`,
|
|
variant: 'default',
|
|
},
|
|
{
|
|
label: 'Create policies for me',
|
|
variant: 'default',
|
|
icon: <AiIconAnimation size={14} />,
|
|
onClick: () =>
|
|
openAiChat(
|
|
'Generate RLS policies',
|
|
'Generate RLS policies for my existing tables in the public schema and guide me through the process of adding them as migration files to my codebase '
|
|
),
|
|
},
|
|
],
|
|
},
|
|
{
|
|
key: 'connect-app',
|
|
status: hasAppConnected ? 'complete' : 'incomplete',
|
|
title: 'Connect your application',
|
|
icon: <Code strokeWidth={1} className="text-foreground-muted" size={16} />,
|
|
description:
|
|
'Your project is ready; open the Connect sheet to grab connection details and setup guidance.',
|
|
actions: connectActions,
|
|
},
|
|
{
|
|
key: 'signup-first-user',
|
|
status: hasFirstUser ? 'complete' : 'incomplete',
|
|
title: 'Sign up your first user',
|
|
icon: <UserPlus strokeWidth={1} className="text-foreground-muted" size={16} />,
|
|
description:
|
|
'Test your authentication setup by creating the first user account, following the docs if you need a step-by-step walkthrough.',
|
|
actions: [
|
|
{
|
|
label: 'Read docs',
|
|
href: `${DOCS_URL}/guides/auth`,
|
|
variant: 'default',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
key: 'upload-file',
|
|
status: hasStorageObjects ? 'complete' : 'incomplete',
|
|
title: 'Upload a file',
|
|
icon: <Upload strokeWidth={1} className="text-foreground-muted" size={16} />,
|
|
description:
|
|
'Integrate file storage by creating a bucket via SQL and uploading a file using our client libraries.',
|
|
actions: [
|
|
{
|
|
label: 'Create a bucket via SQL',
|
|
href: `${DOCS_URL}/guides/storage/buckets/creating-buckets?queryGroups=language&language=sql`,
|
|
variant: 'default',
|
|
},
|
|
{
|
|
label: 'Upload a file',
|
|
href: `${DOCS_URL}/guides/storage/uploads/standard-uploads`,
|
|
variant: 'default',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
key: 'create-edge-function',
|
|
status: hasEdgeFunctions ? 'complete' : 'incomplete',
|
|
title: 'Deploy an Edge Function',
|
|
icon: <Code strokeWidth={1} className="text-foreground-muted" size={16} />,
|
|
description:
|
|
'Add server-side logic by creating and deploying your first Edge Function—a lightweight TypeScript or JavaScript function that runs close to your users—then revisit the list to monitor and iterate on it.',
|
|
actions: [
|
|
{
|
|
label: 'Create and deploy via CLI',
|
|
href: `${DOCS_URL}/guides/functions/quickstart`,
|
|
variant: 'default',
|
|
},
|
|
{ label: 'View functions', href: `/project/${ref}/functions`, variant: 'default' },
|
|
],
|
|
},
|
|
{
|
|
key: 'monitor-progress',
|
|
status: hasReports ? 'complete' : 'incomplete',
|
|
title: "Monitor your project's usage",
|
|
icon: <BarChart3 strokeWidth={1} className="text-foreground-muted" size={16} />,
|
|
description:
|
|
"Track your project's activity by creating custom reports for API, database, and auth events right from the reports dashboard.",
|
|
actions: [{ label: 'Reports', href: `/project/${ref}/reports`, variant: 'default' }],
|
|
},
|
|
{
|
|
key: 'connect-github',
|
|
status: hasGitHubConnection ? 'complete' : 'incomplete',
|
|
title: 'Connect to GitHub',
|
|
icon: <GitBranch strokeWidth={1} className="text-foreground-muted" size={16} />,
|
|
description:
|
|
'Link this project to a GitHub repository to keep production in sync and spin up preview branches from pull requests.',
|
|
actions: [
|
|
{
|
|
label: 'Connect to GitHub',
|
|
href: `/project/${ref}/settings/integrations`,
|
|
variant: 'default',
|
|
},
|
|
],
|
|
},
|
|
]
|
|
}
|
|
|
|
export const getNoCodeWorkflowSteps = ({
|
|
ref,
|
|
openAiChat,
|
|
connectActions,
|
|
statuses,
|
|
}: BuildNoCodeStepsArgs): GettingStartedStep[] => {
|
|
const {
|
|
hasTables,
|
|
hasSampleData,
|
|
hasRlsPolicies,
|
|
hasAppConnected,
|
|
hasFirstUser,
|
|
hasStorageObjects,
|
|
hasEdgeFunctions,
|
|
hasReports,
|
|
hasGitHubConnection,
|
|
} = statuses
|
|
|
|
return [
|
|
{
|
|
key: 'design-db',
|
|
status: hasTables ? 'complete' : 'incomplete',
|
|
title: 'Create your first table',
|
|
icon: <Database strokeWidth={1} className="text-foreground-muted" size={16} />,
|
|
description:
|
|
"To kick off your new project, let's start by creating your very first database table using either the table editor or the AI assistant to shape the structure for you.",
|
|
actions: [
|
|
{ label: 'Create a table', href: `/project/${ref}/editor`, variant: 'default' },
|
|
{
|
|
label: 'Do it for me',
|
|
variant: 'default',
|
|
icon: <AiIconAnimation size={14} />,
|
|
onClick: () =>
|
|
openAiChat(
|
|
'Design my database',
|
|
'I want to design my database schema. Please propose tables, relationships, and SQL to create them for my app. Ask clarifying questions if needed.'
|
|
),
|
|
},
|
|
],
|
|
},
|
|
{
|
|
key: 'add-data',
|
|
status: hasSampleData ? 'complete' : 'incomplete',
|
|
title: 'Add sample data',
|
|
icon: <Table strokeWidth={1} className="text-foreground-muted" size={16} />,
|
|
description:
|
|
"Next, let's add some sample data that you can play with once you connect your app, either by inserting rows yourself or letting the AI assistant craft realistic examples.",
|
|
actions: [
|
|
{ label: 'Add data', href: `/project/${ref}/editor`, variant: 'default' },
|
|
{
|
|
label: 'Do it for me',
|
|
variant: 'default',
|
|
icon: <AiIconAnimation size={14} />,
|
|
onClick: () =>
|
|
openAiChat(
|
|
'Generate sample data',
|
|
'Generate SQL INSERT statements to add realistic sample data to my existing tables. Use safe defaults and avoid overwriting data.'
|
|
),
|
|
},
|
|
],
|
|
},
|
|
{
|
|
key: 'add-rls-policies',
|
|
status: hasRlsPolicies ? 'complete' : 'incomplete',
|
|
title: 'Secure your data with Row Level Security',
|
|
icon: <Shield strokeWidth={1} className="text-foreground-muted" size={16} />,
|
|
description:
|
|
"Now that you have some data, let's secure it by enabling Row Level Security (row-specific access rules that control who can view or modify records) and creating policies yourself or with help from the AI assistant.",
|
|
actions: [
|
|
{
|
|
label: 'Create a policy',
|
|
href: `/project/${ref}/auth/policies`,
|
|
variant: 'default',
|
|
},
|
|
{
|
|
label: 'Do it for me',
|
|
variant: 'default',
|
|
icon: <AiIconAnimation size={14} />,
|
|
onClick: () =>
|
|
openAiChat(
|
|
'Generate RLS policies',
|
|
'Generate RLS policies for my existing tables in the public schema. '
|
|
),
|
|
},
|
|
],
|
|
},
|
|
{
|
|
key: 'connect-app',
|
|
status: hasAppConnected ? 'complete' : 'incomplete',
|
|
title: 'Connect your application',
|
|
icon: <Code strokeWidth={1} className="text-foreground-muted" size={16} />,
|
|
description:
|
|
'Your project is ready; open the Connect sheet to grab connection details and setup guidance.',
|
|
actions: connectActions,
|
|
},
|
|
{
|
|
key: 'signup-first-user',
|
|
status: hasFirstUser ? 'complete' : 'incomplete',
|
|
title: 'Sign up your first user',
|
|
icon: <UserPlus strokeWidth={1} className="text-foreground-muted" size={16} />,
|
|
description:
|
|
'Test your authentication by signing up your first user, referencing the docs if you need sample flows or troubleshooting tips.',
|
|
actions: [
|
|
{
|
|
label: 'Read docs',
|
|
href: `${DOCS_URL}/guides/auth`,
|
|
variant: 'default',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
key: 'upload-file',
|
|
status: hasStorageObjects ? 'complete' : 'incomplete',
|
|
title: 'Upload a file',
|
|
icon: <Upload strokeWidth={1} className="text-foreground-muted" size={16} />,
|
|
description:
|
|
"Let's add file storage to your app by creating a bucket and uploading your first file from the buckets dashboard.",
|
|
actions: [{ label: 'Buckets', href: `/project/${ref}/storage/files`, variant: 'default' }],
|
|
},
|
|
{
|
|
key: 'create-edge-function',
|
|
status: hasEdgeFunctions ? 'complete' : 'incomplete',
|
|
title: 'Add server-side logic',
|
|
icon: <Code strokeWidth={1} className="text-foreground-muted" size={16} />,
|
|
description:
|
|
"Extend your app's functionality by creating an Edge Function—a lightweight serverless function that executes close to your users—for server-side logic directly from the functions page.",
|
|
actions: [
|
|
{
|
|
label: 'Create a function',
|
|
href: `/project/${ref}/functions/new`,
|
|
variant: 'default',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
key: 'monitor-progress',
|
|
status: hasReports ? 'complete' : 'incomplete',
|
|
title: "Monitor your project's health",
|
|
icon: <BarChart3 strokeWidth={1} className="text-foreground-muted" size={16} />,
|
|
description:
|
|
"Keep an eye on your project's performance and usage by setting up custom reports from the reports dashboard.",
|
|
actions: [{ label: 'Create a report', href: `/project/${ref}/reports`, variant: 'default' }],
|
|
},
|
|
{
|
|
key: 'connect-github',
|
|
status: hasGitHubConnection ? 'complete' : 'incomplete',
|
|
title: 'Connect to GitHub',
|
|
icon: <GitBranch strokeWidth={1} className="text-foreground-muted" size={16} />,
|
|
description:
|
|
'Connect your project to GitHub to automatically create preview branches and sync production changes.',
|
|
actions: [
|
|
{
|
|
label: 'Connect to GitHub',
|
|
href: `/project/${ref}/settings/integrations`,
|
|
variant: 'default',
|
|
},
|
|
],
|
|
},
|
|
]
|
|
}
|