diff --git a/.github/workflows/og_images.yml b/.github/workflows/og_images.yml index c3cc6568e73..afec7f34149 100644 --- a/.github/workflows/og_images.yml +++ b/.github/workflows/og_images.yml @@ -14,7 +14,7 @@ jobs: env: SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }} - PROJECT_ID: ${{ secrets.PROJECT_ID }} + PROJECT_ID: ${{ secrets.OG_IMAGE_SUPABASE_PROJECT_ID }} steps: - name: Check out repo diff --git a/.github/workflows/prettier.yml b/.github/workflows/prettier.yml index aef4d8f166d..f1314528f5b 100644 --- a/.github/workflows/prettier.yml +++ b/.github/workflows/prettier.yml @@ -11,9 +11,16 @@ jobs: steps: - name: Check out repo uses: actions/checkout@v3 + - name: Setup node + uses: actions/setup-node@v3 + with: + node-version: 18 + cache: 'npm' + - name: Download dependencies + run: npm ci - name: Run prettier run: |- - npx prettier -c 'apps/**/*.{js,jsx,ts,tsx,css,md,json}' + npx prettier -c 'apps/**/*.{js,jsx,ts,tsx,css,md,mdx,json}' # [Joshen] Temp disable the following due to an issue # https://github.com/EPMatt/reviewdog-action-prettier/issues/34 # uses: EPMatt/reviewdog-action-prettier@v1 @@ -42,9 +49,16 @@ jobs: steps: - name: Check out repo uses: actions/checkout@v3 + - name: Setup node + uses: actions/setup-node@v3 + with: + node-version: 18 + cache: 'npm' + - name: Download dependencies + run: npm ci - name: Run prettier run: |- - npx prettier -c 'i18n/**/*.{js,jsx,ts,tsx,css,md,json}' + npx prettier -c 'i18n/**/*.{js,jsx,ts,tsx,css,md,mdx,json}' # uses: EPMatt/reviewdog-action-prettier@v1 # with: # github_token: ${{ secrets.github_token }} diff --git a/.github/workflows/search.yml b/.github/workflows/search.yml new file mode 100644 index 00000000000..b4631ceca5d --- /dev/null +++ b/.github/workflows/search.yml @@ -0,0 +1,62 @@ +name: Generate Embeddings for Search + +on: + push: + branches: + - master + paths: + - '.github/workflows/search.yml' + - 'supabase/migrations/**' + - 'apps/docs/**' + - 'spec/**' + workflow_dispatch: + inputs: + refresh: + description: 'Refresh all pages' + required: false + type: boolean + schedule: + - cron: '0 0 * * *' + +jobs: + deploy: + runs-on: ubuntu-latest + + env: + OPENAI_KEY: ${{ secrets.OPENAI_KEY }} + SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }} + PROJECT_ID: ${{ secrets.SEARCH_SUPABASE_PROJECT_ID }} + NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.SEARCH_SUPABASE_URL }} + SUPABASE_SERVICE_ROLE_KEY: ${{ secrets.SEARCH_SUPABASE_SERVICE_ROLE_KEY }} + SUPABASE_DB_PASSWORD: ${{ secrets.SEARCH_SUPABASE_DB_PASSWORD }} + SEARCH_GITHUB_APP_ID: ${{ secrets.SEARCH_GITHUB_APP_ID }} + SEARCH_GITHUB_APP_INSTALLATION_ID: ${{ secrets.SEARCH_GITHUB_APP_INSTALLATION_ID }} + SEARCH_GITHUB_APP_PRIVATE_KEY: ${{ secrets.SEARCH_GITHUB_APP_PRIVATE_KEY }} + + steps: + - name: Check out repo + uses: actions/checkout@v3 + + - name: Setup node + uses: actions/setup-node@v3 + with: + node-version: 18 + + - name: Download dependencies + run: npm ci + + - name: Link Supabase project + run: npx supabase link --project-ref $PROJECT_ID + + - name: Run migrations + run: npx supabase db push + + - name: Update embeddings + working-directory: ./apps/docs + if: ${{ !inputs.refresh }} + run: npm run embeddings + + - name: Refresh embeddings + working-directory: ./apps/docs + if: ${{ inputs.refresh }} + run: npm run embeddings:refresh diff --git a/.prettierrc b/.prettierrc index b9bda117c38..c60d3ab91ef 100644 --- a/.prettierrc +++ b/.prettierrc @@ -5,5 +5,7 @@ "singleQuote": true, "printWidth": 100, "endOfLine": "lf", - "sqlKeywordCase": "lower" + "sqlKeywordCase": "lower", + "pluginSearchDirs": false, + "plugins": ["prettier-plugin-sql-cst"] } diff --git a/README.md b/README.md index f3506927e0a..bf770cbaa39 100644 --- a/README.md +++ b/README.md @@ -149,8 +149,8 @@ Our approach for client libraries is modular. Each sub-library is a standalone i Kotlin supabase-kt - postgrest-kt - gotrue-kt + postgrest-kt + gotrue-kt realtime-kt storage-kt functions-kt @@ -231,7 +231,7 @@ Our approach for client libraries is modular. Each sub-library is a standalone i - [Norwegian (Bokmål) / Norsk (Bokmål)](/i18n/README.nb-no.md) - [Persian / فارسی](/i18n/README.fa.md) - [Polish / Polski](/i18n/README.pl.md) -- [Portuguese / Portuguese](/i18n/README.pt.md) +- [Portuguese / Português](/i18n/README.pt.md) - [Portuguese (Brazilian) / Português Brasileiro](/i18n/README.pt-br.md) - [Romanian / Română](/i18n/README.ro.md) - [Russian / Pусский](/i18n/README.ru.md) diff --git a/apps/docs/.env.example b/apps/docs/.env.example index 7fa24758cb1..81e97461ea0 100644 --- a/apps/docs/.env.example +++ b/apps/docs/.env.example @@ -5,6 +5,9 @@ NEXT_PUBLIC_SUPABASE_ANON_KEY= # PRIVATE OPENAI_KEY= SUPABASE_SERVICE_ROLE_KEY= +SEARCH_GITHUB_APP_ID= +SEARCH_GITHUB_APP_INSTALLATION_ID= +SEARCH_GITHUB_APP_PRIVATE_KEY= # Set IS_PLATFORM to true if you have the api keys and urls NEXT_PUBLIC_IS_PLATFORM=false diff --git a/apps/docs/.gitignore b/apps/docs/.gitignore index fd62e0e6867..ba0b52697ed 100644 --- a/apps/docs/.gitignore +++ b/apps/docs/.gitignore @@ -12,6 +12,7 @@ .env.local .env.development.local .env.test.local +.env.staging.local .env.production.local npm-debug.log* @@ -20,4 +21,4 @@ yarn-error.log* **/*/generated/**/* !**/*/generated/.gitkeep -!**/*/generated/**/.gitkeep \ No newline at end of file +!**/*/generated/**/.gitkeep diff --git a/apps/docs/DEVELOPERS.md b/apps/docs/DEVELOPERS.md index 5c5b74e39de..a998eaba7d2 100644 --- a/apps/docs/DEVELOPERS.md +++ b/apps/docs/DEVELOPERS.md @@ -96,4 +96,6 @@ On the Next.JS side of things, these work almost exactly the same as the client #### Search -Search is handled through Algolia. When the site is built, a [search script](https://github.com/supabase/supabase/blob/master/apps/docs/scripts/build-search.ts) runs through all of the types of content, generating search objects that are sent to Algolia to index. +Search is handled using a Supabase instance. During CI, [a script](https://github.com/supabase/supabase/blob/master/apps/docs/scripts/search/generate-embeddings.ts) aggregates all content sources (eg. guides, reference docs, etc), indexes them using OpenAI embeddings, and stores them in a Supabase database. + +At runtime, an [Edge Function](https://github.com/supabase/supabase/blob/master/supabase/functions) is executed that performs a similarity search between the user's query and the above content sources using [`pgvector`](https://github.com/pgvector/pgvector) embeddings. diff --git a/apps/docs/components/CustomHTMLElements/CustomHTMLElements.utils.ts b/apps/docs/components/CustomHTMLElements/CustomHTMLElements.utils.ts index eb214e4963b..0103cef6aa7 100644 --- a/apps/docs/components/CustomHTMLElements/CustomHTMLElements.utils.ts +++ b/apps/docs/components/CustomHTMLElements/CustomHTMLElements.utils.ts @@ -79,7 +79,7 @@ export const unHighlightSelectedTocItems = () => { } export const highlightSelectedNavItem = (id: string) => { - const navMenuItems = document.querySelectorAll('.function-link-item a') + const navMenuItems = document.querySelectorAll('.function-link-item a') // find any currently active items and remove them const currentActiveItems = document.querySelectorAll('.function-link-list .text-brand-900') @@ -87,7 +87,6 @@ export const highlightSelectedNavItem = (id: string) => { // Add active class to the current item navMenuItems.forEach((item) => { - // @ts-ignore if (item.href.split('/').at(-1) === id) { item.classList.add('text-brand-900') } diff --git a/apps/docs/components/DocsCoverLogo.tsx b/apps/docs/components/DocsCoverLogo.tsx new file mode 100644 index 00000000000..0634f188f18 --- /dev/null +++ b/apps/docs/components/DocsCoverLogo.tsx @@ -0,0 +1,497 @@ +import React from 'react' +import { LazyMotion, domAnimation, m } from 'framer-motion' + +const DocsCoverLogo = () => { + const pathMotionConfig = { + initial: { pathLength: 0 }, + animate: { pathLength: 1 }, + transition: { + duration: 1, + delay: 0.2, + ease: [0.5, 0.11, 0.13, 1], + }, + } + const logoMotionConfig = { + initial: { fillOpacity: 0 }, + animate: { fillOpacity: 1 }, + transition: { + duration: 1, + delay: 0.5, + ease: [0.25, 0.25, 0, 1], + }, + } + + return ( +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ ) +} + +export default DocsCoverLogo diff --git a/apps/docs/components/FunctionsExamples.tsx b/apps/docs/components/FunctionsExamples.tsx index a741c0c1751..d9326121c34 100644 --- a/apps/docs/components/FunctionsExamples.tsx +++ b/apps/docs/components/FunctionsExamples.tsx @@ -6,6 +6,12 @@ const examples = [ description: 'Use the Supabase client inside your Edge Function.', href: 'https://github.com/supabase/supabase/blob/master/examples/edge-functions/supabase/functions/select-from-table-with-auth-rls/index.ts', }, + { + name: 'Type-Safe SQL with Kysely', + description: + 'Combining Kysely with Deno Postgres gives you a convenient developer experience for interacting directly with your Postgres database.', + href: '/guides/functions/kysely-postgres', + }, { name: 'With CORS headers', description: 'Send CORS headers for invoking from the browser.', diff --git a/apps/docs/components/HomePageCover.tsx b/apps/docs/components/HomePageCover.tsx new file mode 100644 index 00000000000..edf3252ca64 --- /dev/null +++ b/apps/docs/components/HomePageCover.tsx @@ -0,0 +1,129 @@ +import Link from 'next/link' +import { IconBackground, IconPanel, IconPlay } from 'ui' +import { useBreakpoint } from 'common' +import DocsCoverLogo from './DocsCoverLogo' + +const HomePageCover = (props) => { + const isXs = useBreakpoint(639) + const iconSize = isXs ? 'sm' : 'lg' + + const GettingStarted = () => ( +
+
+
+
+ + + +

Getting Started

+
+

+ Discover how to set up a database to an app making queries in just a few minutes. +

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ ) + + return ( +
+
+
+ +
+

{props.meta?.title}

+

+ Learn how to get up and running with Supabase through tutorials, APIs and platform + resources. +

+
+
+
+ +
+
+
+ ) +} + +export default HomePageCover diff --git a/apps/docs/components/MDX/social_provider_settings_supabase.mdx b/apps/docs/components/MDX/social_provider_settings_supabase.mdx index 1cc3771e6f3..38e0d9e5bfe 100644 --- a/apps/docs/components/MDX/social_provider_settings_supabase.mdx +++ b/apps/docs/components/MDX/social_provider_settings_supabase.mdx @@ -3,4 +3,4 @@ - Click on [`Providers`](https://app.supabase.com/project/_/auth/providers) under the Configuration section - Click on **{props.provider}** from the accordion list to expand and turn **{props.provider} Enabled** to ON - Enter your **{props.provider} Client ID** and **{props.provider} Client Secret** saved in the previous step -- Click `Save` \ No newline at end of file +- Click `Save` diff --git a/apps/docs/components/Navigation/Footer.tsx b/apps/docs/components/Navigation/Footer.tsx index c21718dce72..c58c7c94f93 100644 --- a/apps/docs/components/Navigation/Footer.tsx +++ b/apps/docs/components/Navigation/Footer.tsx @@ -1,66 +1,163 @@ -import Image from 'next/image' import Link from 'next/link' -import { Button, IconGitHub, IconTwitter, IconYoutube } from '~/../../packages/ui' -import footerData from '~/data/footer.json' -import { useTheme } from 'common/Providers' +import { Button } from '~/../../packages/ui' +import { primaryLinks, secondaryLinks } from '~/data/footer' +import { LayoutMainContent } from '../../layouts/DefaultLayout' -const Footer = () => { - const { isDarkMode } = useTheme() - return ( -
-
-
-
- Supabase 2022 - — - {footerData.map((item) => ( - - {item.title} - - ))} -
-
- - - + + + -
+ + + + + + + +
- ) -} + +) export default Footer diff --git a/apps/docs/components/Navigation/Navigation.types.ts b/apps/docs/components/Navigation/Navigation.types.ts index 76afaa7b1c6..a644cc7c70d 100644 --- a/apps/docs/components/Navigation/Navigation.types.ts +++ b/apps/docs/components/Navigation/Navigation.types.ts @@ -22,3 +22,14 @@ export interface References { currentVersion?: string } } + +type MenuItem = { + label: string + icon?: string + href?: string + level?: string + hasLightIcon?: boolean + community?: boolean +} + +export type HomepageMenuItems = MenuItem[][] diff --git a/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx b/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx index db93e1616a2..fb51bb98ba7 100644 --- a/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx +++ b/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx @@ -4,155 +4,18 @@ import Link from 'next/link' import { useRouter } from 'next/router' import { Fragment } from 'react' import { Badge } from '~/../../packages/ui' +import { cn } from 'ui/src/utils/cn' +import { HOMEPAGE_MENU_ITEMS } from './NavigationMenu.constants' +import HomeMenuIconPicker from './HomeMenuIconPicker' -const home = [ - [ - { - label: 'Home', - icon: '/img/icons/menu/home', - href: '/', - level: 'home', - }, - { - label: 'Getting Started', - icon: '/img/icons/menu/getting-started', - href: '/guides/getting-started', - level: 'gettingstarted', - }, - ], - [ - { - label: 'Database', - icon: '/img/icons/menu/database', - href: '/guides/database', - level: 'database', - }, - { - label: 'Serverless APIs', - icon: '/img/icons/menu/reference', - href: '/guides/api', - level: 'api', - }, - { - label: 'Auth', - icon: '/img/icons/menu/auth', - href: '/guides/auth', - level: 'auth', - }, - { - label: 'Edge Functions', - icon: '/img/icons/menu/functions', - href: '/guides/functions', - level: 'functions', - }, - { - label: 'Realtime', - icon: '/img/icons/menu/realtime', - href: '/guides/realtime', - level: 'realtime', - }, - { - label: 'Storage', - icon: '/img/icons/menu/storage', - href: '/guides/storage', - level: 'storage', - }, - ], - [ - { - label: 'Platform', - icon: '/img/icons/menu/platform', - href: '/guides/platform', - level: 'platform', - }, - { - label: 'Resources', - icon: '/img/icons/menu/platform', - href: '/guides/resources', - level: 'resources', - }, - { - label: 'Self-Hosting', - icon: '/img/icons/menu/platform', - href: '/guides/self-hosting', - level: 'self_hosting', - }, - { - label: 'Integrations', - icon: '/img/icons/menu/integrations', - hasLightIcon: true, - href: '/guides/integrations', - level: 'integrations', - }, - ], - [ - { - label: 'Client Library Reference', - }, - { - label: 'JavaScript', - icon: '/img/icons/menu/reference-javascript', - href: '/reference/javascript/introduction', - level: 'reference_javascript', - }, - { - label: 'Flutter', - icon: '/img/icons/menu/reference-dart', - href: '/reference/dart/introduction', - level: 'reference_dart', - }, - { - label: 'Python', - icon: '/img/icons/menu/reference-python', - href: '/reference/python/introduction', - level: 'reference_python', - community: true, - }, - { - label: 'C#', - icon: '/img/icons/menu/reference-csharp', - href: '/reference/csharp/introduction', - level: 'reference_csharp', - community: true, - }, - { - label: 'Swift', - icon: '/img/icons/menu/reference-swift', - href: '/reference/swift/introduction', - level: 'reference_swift', - community: true, - }, - { - label: 'Tools', - }, - { - label: 'Management API', - icon: '/img/icons/menu/reference-api', - href: '/reference/api/introduction', - level: 'reference_javascript', - }, - { - label: 'Supabase CLI', - icon: '/img/icons/menu/reference-cli', - href: '/guides/cli', - level: 'reference_javascript', - }, - ], -] - -const NavigationMenuHome = ({ active }) => { +const NavigationMenuHome = () => { const router = useRouter() const { isDarkMode } = useTheme() return ( -
-