docs: update Refine branding (#40378)

* docs: update Refine svg in HeroFrameworks

* docs: use capital R for Refine mentions

* docs: use main branch for Refine repository references

* docs: update connect interface example code for Refine

* docs: update Refine quick start tutorial with Refine v5

* examples(refine-user-management): upgrade to Refine v5

* docs: update Refine getting started tutorial with Refine v5

* chore(studio): update Refine icon on Connect modal

* docs: update Refine svg

* docs: update welcome screen screenshot in Refine tutorial

* docs: update dimensions of welcome screen screenshot in Refine tutorial

* chore: remove leftover dist assets from Refine example

* chore(linter): add Refine to Rule001 and Rule003

* chore: format getting started with Refine.mdx

* chore: remove .prettierrc file from the example
This commit is contained in:
Batuhan Wilhelm
2025-11-18 16:34:00 +03:00
committed by GitHub
parent ac8ee2309c
commit 8cfe645f2b
33 changed files with 8063 additions and 219 deletions
+1 -1
View File
@@ -88,7 +88,7 @@ const HomePageCover = (props) => {
href: '/guides/getting-started/quickstarts/nuxtjs',
},
{
tooltip: 'refine',
tooltip: 'Refine',
icon: '/docs/img/icons/refine-icon',
href: '/guides/getting-started/quickstarts/refine',
},
@@ -392,7 +392,7 @@ export const gettingstarted: NavMenuConstant = {
url: '/guides/getting-started/quickstarts/redwoodjs' as `/${string}`,
},
{
name: 'refine',
name: 'Refine',
url: '/guides/getting-started/quickstarts/refine',
},
],
@@ -438,7 +438,7 @@ export const gettingstarted: NavMenuConstant = {
url: '/guides/getting-started/tutorials/with-sveltekit' as `/${string}`,
},
{
name: 'refine',
name: 'Refine',
url: '/guides/getting-started/tutorials/with-refine' as `/${string}`,
},
],
+4 -4
View File
@@ -187,10 +187,10 @@ hideToc: true
enabled: isFeatureEnabled('docs:framework_quickstarts'),
},
{
title: 'refine',
title: 'Refine',
href: '/guides/getting-started/quickstarts/refine',
description:
'Learn how to create a Supabase project, add some sample data to your database, and query the data from a refine app.',
'Learn how to create a Supabase project, add some sample data to your database, and query the data from a Refine app.',
icon: '/docs/img/icons/refine-icon',
enabled: isFeatureEnabled('docs:framework_quickstarts'),
},
@@ -286,10 +286,10 @@ hideToc: true
icon: '/docs/img/icons/svelte-icon',
},
{
title: 'refine',
title: 'Refine',
href: '/guides/getting-started/tutorials/with-refine',
description:
'Learn how to build a user management app with refine and Supabase Database, Auth, and Storage functionality.',
'Learn how to build a user management app with Refine and Supabase Database, Auth, and Storage functionality.',
icon: '/docs/img/icons/refine-icon',
}
]
@@ -1,6 +1,6 @@
---
title: 'Use Supabase with refine'
subtitle: 'Learn how to create a Supabase project, add some sample data to your database, and query the data from a refine app.'
title: 'Use Supabase with Refine'
subtitle: 'Learn how to create a Supabase project, add some sample data to your database, and query the data from a Refine app.'
breadcrumb: 'Framework Quickstarts'
hideToc: true
---
@@ -15,11 +15,11 @@ hideToc: true
<StepHikeCompact.Step step={2}>
<StepHikeCompact.Details title="Create a refine app">
<StepHikeCompact.Details title="Create a Refine app">
Create a [refine](https://github.com/refinedev/refine) app using the [create refine-app](https://refine.dev/docs/getting-started/quickstart/).
Create a [Refine](https://github.com/refinedev/refine) app using the [create refine-app](https://refine.dev/docs/getting-started/quickstart/).
The `refine-supabase` preset adds `@refinedev/supabase` supplementary package that supports Supabase in a refine app. `@refinedev/supabase` out-of-the-box includes the Supabase dependency: [supabase-js](https://github.com/supabase/supabase-js).
The `refine-supabase` preset adds `@refinedev/supabase` supplementary package that supports Supabase in a Refine app. `@refinedev/supabase` out-of-the-box includes the Supabase dependency: [supabase-js](https://github.com/supabase/supabase-js).
</StepHikeCompact.Details>
@@ -34,9 +34,9 @@ hideToc: true
</StepHikeCompact.Step>
<StepHikeCompact.Step step={3}>
<StepHikeCompact.Details title="Open your refine app in VS Code">
<StepHikeCompact.Details title="Open your Refine app in VS Code">
You will develop your app, connect to the Supabase backend and run the refine app in VS Code.
You will develop your app, connect to the Supabase backend and run the Refine app in VS Code.
</StepHikeCompact.Details>
@@ -54,7 +54,7 @@ hideToc: true
<StepHikeCompact.Step step={4}>
<StepHikeCompact.Details title="Start the app">
Start the app, go to http://localhost:5173 in a browser, and you should be greeted with the refine Welcome page.
Start the app, go to http://localhost:5173 in a browser, and you should be greeted with the Refine Welcome page.
</StepHikeCompact.Details>
@@ -65,7 +65,7 @@ hideToc: true
```
<StepHikeCompact.Code>
![refine welcome page](/docs/img/refine-qs-welcome-page.png)
![Refine welcome page](/docs/img/refine-qs-welcome-page.png)
</StepHikeCompact.Code>
</StepHikeCompact.Code>
@@ -75,7 +75,7 @@ hideToc: true
<StepHikeCompact.Step step={5}>
<StepHikeCompact.Details title="Update `supabaseClient`">
You now have to update the `supabaseClient` with the `SUPABASE_URL` and `SUPABASE_KEY` of your Supabase API. The `supabaseClient` is used in auth provider and data provider methods that allow the refine app to connect to your Supabase backend.
You now have to update the `supabaseClient` with the `SUPABASE_URL` and `SUPABASE_KEY` of your Supabase API. The `supabaseClient` is used in auth provider and data provider methods that allow the Refine app to connect to your Supabase backend.
<ProjectConfigVariables variable="url" />
<ProjectConfigVariables variable="publishable" />
@@ -110,7 +110,7 @@ hideToc: true
You have to then configure resources and define pages for `instruments` resource.
Use the following command to automatically add resources and generate code for pages for `instruments` using refine Inferencer.
Use the following command to automatically add resources and generate code for pages for `instruments` using Refine Inferencer.
This defines pages for `list`, `create`, `show` and `edit` actions inside the `src/pages/instruments/` directory with `<HeadlessInferencer />` component.
@@ -118,7 +118,7 @@ hideToc: true
<Admonition type="note">
The `<HeadlessInferencer />` is a refine Inferencer component that automatically generates necessary code for the `list`, `create`, `show` and `edit` pages.
The `<HeadlessInferencer />` is a Refine Inferencer component that automatically generates necessary code for the `list`, `create`, `show` and `edit` pages.
More on [how the Inferencer works is available in the docs here](https://refine.dev/docs/packages/documentation/inferencer/).
@@ -151,13 +151,13 @@ hideToc: true
<StepHikeCompact.Code>
```tsx name=src/App.tsx
import { Refine, WelcomePage } from "@refinedev/core";
import { Refine } from "@refinedev/core";
import { RefineKbar, RefineKbarProvider } from "@refinedev/kbar";
import routerBindings, {
import routerProvider, {
DocumentTitleHandler,
NavigateToResource,
UnsavedChangesNotifier,
} from "@refinedev/react-router-v6";
} from "@refinedev/react-router";
import { dataProvider, liveProvider } from "@refinedev/supabase";
import { BrowserRouter, Route, Routes } from "react-router-dom";
@@ -174,7 +174,7 @@ hideToc: true
dataProvider={dataProvider(supabaseClient)}
liveProvider={liveProvider(supabaseClient)}
authProvider={authProvider}
routerProvider={routerBindings}
routerProvider={routerProvider}
options={{
syncWithLocation: true,
warnWhenUnsavedChanges: true,
@@ -1,6 +1,6 @@
---
title: 'Build a User Management App with refine'
description: 'Learn how to use Supabase in your refine App.'
title: 'Build a User Management App with Refine'
description: 'Learn how to use Supabase in your Refine App.'
---
<$Partial path="quickstart_intro.mdx" />
@@ -13,11 +13,11 @@ If you get stuck while working through this guide, refer to the [full example on
</Admonition>
## About refine
## About Refine
[refine](https://github.com/refinedev/refine) is a React-based framework used to rapidly build data-heavy applications like admin panels, dashboards, storefronts and any type of CRUD apps. It separates app concerns into individual layers, each backed by a React context and respective provider object. For example, the auth layer represents a context served by a specific set of [`authProvider`](https://refine.dev/docs/tutorial/understanding-authprovider/index/) methods that carry out authentication and authorization actions such as logging in, logging out, getting roles data, etc. Similarly, the data layer offers another level of abstraction that is equipped with [`dataProvider`](https://refine.dev/docs/tutorial/understanding-dataprovider/index/) methods to handle CRUD operations at appropriate backend API endpoints.
[Refine](https://github.com/refinedev/refine) is a React-based framework used to rapidly build data-heavy applications like admin panels, dashboards, storefronts and any type of CRUD apps. It separates app concerns into individual layers, each backed by a React context and respective provider object. For example, the auth layer represents a context served by a specific set of [`authProvider`](https://refine.dev/docs/tutorial/understanding-authprovider/index/) methods that carry out authentication and authorization actions such as logging in, logging out, getting roles data, etc. Similarly, the data layer offers another level of abstraction that is equipped with [`dataProvider`](https://refine.dev/docs/tutorial/understanding-dataprovider/index/) methods to handle CRUD operations at appropriate backend API endpoints.
refine provides hassle-free integration with Supabase backend with its supplementary [`@refinedev/supabase`](https://github.com/refinedev/refine/tree/master/packages/supabase) package. It generates `authProvider` and `dataProvider` methods at project initialization, so we don't need to expend much effort to define them ourselves. We just need to choose Supabase as our backend service while creating the app with `create refine-app`.
Refine provides hassle-free integration with Supabase backend with its supplementary [`@refinedev/supabase`](https://github.com/refinedev/refine/tree/main/packages/supabase) package. It generates `authProvider` and `dataProvider` methods at project initialization, so we don't need to expend much effort to define them ourselves. We just need to choose Supabase as our backend service while creating the app with `create refine-app`.
<Admonition type="note">
@@ -29,9 +29,9 @@ It is possible to customize the `authProvider` for Supabase and as we'll see bel
## Building the app
Let's start building the refine app from scratch.
Let's start building the Refine app from scratch.
### Initialize a refine app
### Initialize a Refine app
We can use [create refine-app](https://refine.dev/docs/tutorial/getting-started/headless/create-project/#launch-the-refine-cli-setup) command to initialize
an app. Run the following in the terminal:
@@ -44,13 +44,13 @@ In the above command, we are using the `refine-supabase` preset which chooses th
The `refine-supabase` preset installs the `@refinedev/supabase` package which out-of-the-box includes the Supabase dependency: [supabase-js](https://github.com/supabase/supabase-js).
We also need to install `@refinedev/react-hook-form` and `react-hook-form` packages that allow us to use [React Hook Form](https://react-hook-form.com) inside refine apps. Run:
We also need to install `@refinedev/react-hook-form` and `react-hook-form` packages that allow us to use [React Hook Form](https://react-hook-form.com) inside Refine apps. Run:
```bash
npm install @refinedev/react-hook-form react-hook-form
```
With the app initialized and packages installed, at this point before we begin discussing refine concepts, let's try running the app:
With the app initialized and packages installed, at this point before we begin discussing Refine concepts, let's try running the app:
```bash
cd app-name
@@ -110,13 +110,12 @@ The `App.tsx` file initially looks like this:
```tsx name=src/App.tsx
import { Refine, WelcomePage } from '@refinedev/core'
import { RefineKbar, RefineKbarProvider } from '@refinedev/kbar'
import routerBindings, {
import routerProvider, {
DocumentTitleHandler,
UnsavedChangesNotifier,
} from '@refinedev/react-router-v6'
} from '@refinedev/react-router'
import { dataProvider, liveProvider } from '@refinedev/supabase'
import { BrowserRouter, Route, Routes } from 'react-router-dom'
import { BrowserRouter, Route, Routes } from 'react-router'
import './App.css'
import authProvider from './authProvider'
import { supabaseClient } from './utility'
@@ -129,7 +128,7 @@ function App() {
dataProvider={dataProvider(supabaseClient)}
liveProvider={liveProvider(supabaseClient)}
authProvider={authProvider}
routerProvider={routerBindings}
routerProvider={routerProvider}
options={{
syncWithLocation: true,
warnWhenUnsavedChanges: true,
@@ -188,11 +187,11 @@ We also want to remove `register`, `updatePassword`, `forgotPassword` and `getPe
<$CodeTabs>
```ts name=src/authProvider.ts
import { AuthBindings } from '@refinedev/core'
import { AuthProvider } from '@refinedev/core'
import { supabaseClient } from './utility'
const authProvider: AuthBindings = {
const authProvider: AuthProvider = {
login: async ({ email }) => {
try {
const { error } = await supabaseClient.auth.signInWithOtp({ email })
@@ -285,7 +284,7 @@ export default authProvider
### Set up a login component
We have chosen to use the headless refine core package that comes with no supported UI framework. So, let's set up a plain React component to manage logins and sign ups.
We have chosen to use the headless Refine core package that comes with no supported UI framework. So, let's set up a plain React component to manage logins and sign ups.
Create and edit `src/components/auth.tsx`:
@@ -297,7 +296,7 @@ import { useLogin } from '@refinedev/core'
export default function Auth() {
const [email, setEmail] = useState('')
const { isLoading, mutate: login } = useLogin()
const { isPending, mutate: login } = useLogin()
const handleLogin = async (event: { preventDefault: () => void }) => {
event.preventDefault()
@@ -307,7 +306,7 @@ export default function Auth() {
return (
<div className="row flex flex-center container">
<div className="col-6 form-widget">
<h1 className="header">Supabase + refine</h1>
<h1 className="header">Supabase + Refine</h1>
<p className="description">Sign in via magic link with your email below</p>
<form className="form-widget" onSubmit={handleLogin}>
<div>
@@ -321,8 +320,8 @@ export default function Auth() {
/>
</div>
<div>
<button className={'button block'} disabled={isLoading}>
{isLoading ? <span>Loading</span> : <span>Send magic link</span>}
<button className={'button block'} disabled={isPending}>
{isPending ? <span>Loading</span> : <span>Send magic link</span>}
</button>
</div>
</form>
@@ -334,7 +333,7 @@ export default function Auth() {
</$CodeTabs>
Notice we are using the [`useLogin()`](https://refine.dev/docs/api-reference/core/hooks/authentication/useLogin/) refine auth hook to grab the `mutate: login` method to use inside `handleLogin()` function and `isLoading` state for our form submission. The `useLogin()` hook conveniently offers us access to `authProvider.login` method for authenticating the user with OTP.
Notice we are using the [`useLogin()`](https://refine.dev/docs/api-reference/core/hooks/authentication/useLogin/) Refine auth hook to grab the `mutate: login` method to use inside `handleLogin()` function and `isLoading` state for our form submission. The `useLogin()` hook conveniently offers us access to `authProvider.login` method for authenticating the user with OTP.
### Account page
@@ -367,7 +366,7 @@ export default function Account() {
const { mutate: logOut } = useLogout()
const {
refineCore: { formLoading, queryResult, onFinish },
refineCore: { formLoading, query, onFinish },
register,
control,
handleSubmit,
@@ -416,7 +415,7 @@ export default function Account() {
</$CodeTabs>
Notice above that, we are using three refine hooks, namely the [`useGetIdentity()`](https://refine.dev/docs/api-reference/core/hooks/authentication/useGetIdentity/), [`useLogOut()`](https://refine.dev/docs/api-reference/core/hooks/authentication/useLogout/) and [`useForm()`](https://refine.dev/docs/packages/documentation/react-hook-form/useForm/) hooks.
Notice above that, we are using three Refine hooks, namely the [`useGetIdentity()`](https://refine.dev/docs/api-reference/core/hooks/authentication/useGetIdentity/), [`useLogOut()`](https://refine.dev/docs/api-reference/core/hooks/authentication/useLogout/) and [`useForm()`](https://refine.dev/docs/packages/documentation/react-hook-form/useForm/) hooks.
`useGetIdentity()` is a auth hook that gets the identity of the authenticated user. It grabs the current user by invoking the `authProvider.getIdentity` method under the hood.
@@ -437,13 +436,13 @@ Add the routes for `/login` with the `<Auth />` component and the routes for `in
```tsx name=src/App.tsx
import { Authenticated, Refine } from '@refinedev/core'
import { RefineKbar, RefineKbarProvider } from '@refinedev/kbar'
import routerBindings, {
import routerProvider, {
CatchAllNavigate,
DocumentTitleHandler,
UnsavedChangesNotifier,
} from '@refinedev/react-router-v6'
} from '@refinedev/react-router'
import { dataProvider, liveProvider } from '@refinedev/supabase'
import { BrowserRouter, Outlet, Route, Routes } from 'react-router-dom'
import { BrowserRouter, Outlet, Route, Routes } from 'react-router'
import './App.css'
import authProvider from './authProvider'
@@ -459,7 +458,7 @@ function App() {
dataProvider={dataProvider(supabaseClient)}
liveProvider={liveProvider(supabaseClient)}
authProvider={authProvider}
routerProvider={routerBindings}
routerProvider={routerProvider}
options={{
syncWithLocation: true,
warnWhenUnsavedChanges: true,
@@ -468,14 +467,17 @@ function App() {
<Routes>
<Route
element={
<Authenticated fallback={<CatchAllNavigate to="/login" />}>
<Authenticated
key="authenticated-routes"
fallback={<CatchAllNavigate to="/login" />}
>
<Outlet />
</Authenticated>
}
>
<Route index element={<Account />} />
</Route>
<Route element={<Authenticated fallback={<Outlet />} />}>
<Route element={<Authenticated key="auth-pages" fallback={<Outlet />} />}>
<Route path="/login" element={<Auth />} />
</Route>
</Routes>
@@ -501,7 +503,7 @@ npm run dev
And then open the browser to [localhost:5173](http://localhost:5173) and you should see the completed app.
![Supabase refine](/docs/img/supabase-refine-demo.png)
![Supabase Refine](/docs/img/supabase-refine-demo.png)
## Bonus: Profile photos
@@ -636,7 +638,7 @@ return (
size={150}
onUpload={(filePath) => {
onFinish({
...queryResult?.data?.data,
...query?.data?.data,
avatar_url: filePath,
onMutationError: (data: { message: string }) => alert(data?.message),
})
+1 -12
View File
@@ -1,12 +1 @@
<svg width="128" height="128" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1617_18224)">
<circle cx="64" cy="64" r="64" fill="#14141F"/>
<path d="M72.2126 42.443C72.2126 46.7651 68.6722 50.2688 64.3049 50.2688C59.9375 50.2688 56.3971 46.7651 56.3971 42.443C56.3971 38.121 59.9375 34.6173 64.3049 34.6173C68.6722 34.6173 72.2126 38.121 72.2126 42.443Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M53.821 32.3072C56.6017 29.5543 60.3723 28.0053 64.3055 28C68.2388 28.0053 72.0094 29.5543 74.7901 32.3072C77.5709 35.0601 79.1348 38.7921 79.1389 42.6846V85.3204C79.1389 89.2137 77.5761 92.9475 74.7943 95.7004C72.0125 98.4534 68.2396 100 64.3055 100C60.3715 100 56.5986 98.4534 53.8168 95.7004C51.035 92.9475 49.4722 89.2137 49.4722 85.3204V42.6846C49.4762 38.7921 51.0402 35.0601 53.821 32.3072ZM71.6548 35.4115C69.7057 33.4825 67.062 32.3989 64.3055 32.3989C62.9406 32.3989 61.5891 32.6649 60.3282 33.1818C59.0672 33.6987 57.9214 34.4564 56.9563 35.4115C55.9912 36.3666 55.2256 37.5005 54.7033 38.7484C54.1809 39.9963 53.9121 41.3338 53.9121 42.6846V85.3204C53.9121 88.0484 55.0071 90.6646 56.9563 92.5935C58.9054 94.5225 61.549 95.6061 64.3055 95.6061C67.062 95.6061 69.7057 94.5225 71.6548 92.5935C73.604 90.6646 74.699 88.0484 74.699 85.3204V42.6846C74.699 39.9566 73.604 37.3404 71.6548 35.4115Z" fill="white"/>
</g>
<defs>
<clipPath id="clip0_1617_18224">
<rect width="128" height="128" fill="white"/>
</clipPath>
</defs>
</svg>
<svg width="168" height="168" viewBox="0 0 168 168" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M67.8984 3.80062C78.0334 -1.26687 89.9666 -1.26687 100.102 3.80062L148.102 27.8006C160.297 33.899 168 46.3647 168 59.9998V108C168 121.635 160.297 134.101 148.102 140.199L100.102 164.199C89.9666 169.266 78.0334 169.266 67.8984 164.199L19.8984 140.199C7.70321 134.101 0.000125181 121.635 0 108V59.9998C0 46.3647 7.70319 33.899 19.8984 27.8006L67.8984 3.80062Z" fill="black"/><path fill-rule="evenodd" clip-rule="evenodd" d="M94.7331 14.5337C87.9765 11.1554 80.0235 11.1554 73.2669 14.5337L25.2669 38.5337C17.1361 42.5992 12 50.9095 12 60V108C12 117.091 17.1361 125.401 25.2669 129.466L73.2669 153.466C80.0235 156.845 87.9765 156.845 94.7331 153.466L142.733 129.466C150.864 125.401 156 117.091 156 108V60C156 50.9095 150.864 42.5992 142.733 38.5337L94.7331 14.5337ZM60 60C60 46.7452 70.7452 36 84 36C97.2548 36 108 46.7452 108 60V108C108 121.255 97.2548 132 84 132C70.7452 132 60 121.255 60 108V60Z" fill="white"/><path d="M96 60C96 66.6274 90.6274 72 84 72C77.3726 72 72 66.6274 72 60C72 53.3726 77.3726 48 84 48C90.6274 48 96 53.3726 96 60Z" fill="white"/></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 548 KiB

@@ -227,7 +227,7 @@ export const FRAMEWORKS: ConnectionType[] = [
},
{
key: 'refine',
label: 'refine',
label: 'Refine',
icon: 'refine',
guideLink: `${DOCS_URL}/guides/getting-started/quickstarts/refine`,
children: [
@@ -19,7 +19,7 @@ export const ConnectionIcon = ({ icon, iconFolder, supportsDarkMode }: Connectio
const shouldUseDarkMode =
supportsDarkMode ||
['expo', 'nextjs', 'prisma', 'drizzle', 'astro', 'remix'].includes(icon.toLowerCase())
['expo', 'nextjs', 'prisma', 'drizzle', 'astro', 'remix', 'refine'].includes(icon.toLowerCase())
const iconImgSrc = icon.startsWith('http')
? icon
@@ -51,13 +51,13 @@ export const supabaseClient = createClient(SUPABASE_URL, SUPABASE_KEY, {
<ConnectTabContent value="src/App.tsx">
<SimpleCodeBlock className="tsx" parentClassName="min-h-72">
{`
import { Refine, WelcomePage } from "@refinedev/core";
import { Refine } from "@refinedev/core";
import { RefineKbar, RefineKbarProvider } from "@refinedev/kbar";
import routerBindings, {
import routerProvider, {
DocumentTitleHandler,
NavigateToResource,
UnsavedChangesNotifier,
} from "@refinedev/react-router-v6";
} from "@refinedev/react-router";
import { dataProvider, liveProvider } from "@refinedev/supabase";
import { BrowserRouter, Route, Routes } from "react-router-dom";
@@ -74,7 +74,7 @@ function App() {
dataProvider={dataProvider(supabaseClient)}
liveProvider={liveProvider(supabaseClient)}
authProvider={authProvider}
routerProvider={routerBindings}
routerProvider={routerProvider}
options={{
syncWithLocation: true,
warnWhenUnsavedChanges: true,
@@ -0,0 +1,4 @@
<svg width="18" height="18" viewBox="0 0 640 640" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M367.703 11.2611C337.673 -3.7537 302.327 -3.7537 272.297 11.2611L58.9639 117.928C22.8269 135.996 0 172.931 0 213.333V426.667C0 467.069 22.8269 504.004 58.9639 522.072L272.297 628.739C302.327 643.754 337.673 643.754 367.703 628.739L581.036 522.072C617.173 504.004 640 467.069 640 426.667V213.333C640 172.931 617.173 135.996 581.036 117.928L367.703 11.2611ZM213.333 213.333C213.333 154.423 261.09 106.667 320 106.667C378.91 106.667 426.667 154.423 426.667 213.333V426.667C426.667 485.577 378.91 533.333 320 533.333C261.09 533.333 213.333 485.577 213.333 426.667V213.333Z" fill="#fff"/>
<path d="M373.333 213.333C373.333 242.789 349.455 266.667 320 266.667C290.545 266.667 266.667 242.789 266.667 213.333C266.667 183.878 290.545 160 320 160C349.455 160 373.333 183.878 373.333 213.333Z" fill="#fff"/>
</svg>

After

Width:  |  Height:  |  Size: 952 B

@@ -1 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#868181" fill-rule="evenodd"><path d="M13.789.422a4 4 0 0 0-3.578 0l-8 4A4 4 0 0 0 0 8v8a4 4 0 0 0 2.211 3.578l8 4a4 4 0 0 0 3.578 0l8-4A4 4 0 0 0 24 16V8a4 4 0 0 0-2.211-3.578l-8-4ZM8 8a4 4 0 1 1 8 0v8a4 4 0 1 1-8 0V8Z"/><path fill-rule="nonzero" d="M14 8a2 2 0 1 1-4 0 2 2 0 0 1 4 0Z"/></g></svg>
<svg width="18" height="18" viewBox="0 0 640 640" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M367.703 11.2611C337.673 -3.7537 302.327 -3.7537 272.297 11.2611L58.9639 117.928C22.8269 135.996 0 172.931 0 213.333V426.667C0 467.069 22.8269 504.004 58.9639 522.072L272.297 628.739C302.327 643.754 337.673 643.754 367.703 628.739L581.036 522.072C617.173 504.004 640 467.069 640 426.667V213.333C640 172.931 617.173 135.996 581.036 117.928L367.703 11.2611ZM213.333 213.333C213.333 154.423 261.09 106.667 320 106.667C378.91 106.667 426.667 154.423 426.667 213.333V426.667C426.667 485.577 378.91 533.333 320 533.333C261.09 533.333 213.333 485.577 213.333 426.667V213.333Z" fill="#000"/>
<path d="M373.333 213.333C373.333 242.789 349.455 266.667 320 266.667C290.545 266.667 266.667 242.789 266.667 213.333C266.667 183.878 290.545 160 320 160C349.455 160 373.333 183.878 373.333 213.333Z" fill="#000"/>
</svg>

Before

Width:  |  Height:  |  Size: 390 B

After

Width:  |  Height:  |  Size: 952 B

@@ -107,7 +107,7 @@ Congratulations 👏 to [@\_iamkarthikeyan](https://twitter.com/_iamkarthikeyan)
- Build any Front-end like Admin Panel or CRM for your Supabase. [Article](https://blog.jetadmin.io/how-to-build-any-front-end-such-as-admin-panel-or-crm-for-your-supabase-in-minutes/)
- Everything Svelte: a course with all you need to know to build a modern web application. [Course](https://www.everythingsvelte.com/)
- Edgy Edge Functions: a look at a new Edge Function per week. [Youtube Playlist](https://www.youtube.com/playlist?list=PL5S4mPUpp4OulD3olUW8Eq1IYKpUbk5Ob)
- Pixels, an app that provides canvas to create pixel art. [App](https://pixels.refine.dev/) | [GitHub Repo](https://github.com/refinedev/refine/tree/next/examples/pixels)
- Pixels, an app that provides canvas to create pixel art. [App](https://pixels.refine.dev/) | [GitHub Repo](https://github.com/refinedev/refine/tree/main/examples/pixels)
- Supabase Angular authentication with RxJS Observables. [Tutorial](https://dev.to/kylerummens/supabase-angular-authentication-with-rxjs-observables-3d0f)
- Create Calendar Events in React With Google Calendar API and Supabase. [Video Tutorial](https://www.youtube.com/watch?v=tgcCl52EN84)
- Going Serverless with Supabase. [Part 1](https://dev.to/davepar/going-serverless-with-supabase-103h)
@@ -104,7 +104,7 @@ Discover 100+ other apps in this [tweet](https://twitter.com/supabase/status/162
- LangChain supports our database as a vector store, using pgvector. [Doc](https://hwchase17.github.io/langchainjs/docs/modules/indexes/vector_stores/supabase/) <br/>
- refine week: building a CRUD app with refine & Supabase. [Full series](https://refine.dev/week-of-refine/)
- Refine week: building a CRUD app with Refine & Supabase. [Full series](https://refine.dev/week-of-refine/)
- Build an Instagram Web App with Supabase and Next.js. [Tutorial](https://livecycle.io/blogs/nextjs-supabase-instagram/) <br/>
@@ -83,7 +83,7 @@ Added the popular social platform Kakao as new social provider. Allow your users
- Using Supabase with Cloudflare Workers. [Cloudflare TV](https://cloudflare.tv/event/using-supabase-with-cloudflare-workers/dgM90RgD)
- Build a Chatbot with Next.js, LangChain, OpenAI, and Supabase Vector. [Video Tutorial](https://www.youtube.com/watch?v=Tt45NrVIBn8)
- The refine open source Hackathon is in full swing. [Join now](https://discord.com/channels/@me/1118414473108148296/1123933930702262312)
- The Refine open source Hackathon is in full swing. [Join now](https://discord.com/channels/@me/1118414473108148296/1123933930702262312)
- Flutter database and user authentication. [Video guide](https://www.youtube.com/watch?v=r7ysVtZ5Row)
- Google authentication with Expo & Supabase. [Tutorial](https://blog.spirokit.com/google-authentication-with-expo-supabase)
- Building Stripe integrations with Supabase. [Video](https://www.youtube.com/watch?v=D5kOnnB72WA)
+1 -1
View File
@@ -61,7 +61,7 @@ export const frameworks: Framework[] = [
},
{
name: 'Refine',
icon: 'M31.7374 20.9337C32.7027 20.9337 33.6284 21.3132 34.311 21.9887C34.9936 22.6642 35.377 23.5803 35.377 24.5356V39.4661C35.377 40.4214 34.9936 41.3375 34.311 42.013C33.6284 42.6885 32.7027 43.068 31.7374 43.068C30.7721 43.068 29.8463 42.6885 29.1638 42.013C28.4812 41.3375 28.0978 40.4214 28.0978 39.4661V24.5356C28.0978 24.0626 28.1919 23.5942 28.3748 23.1572C28.5577 22.7203 28.8258 22.3232 29.1638 21.9887C29.5018 21.6543 29.903 21.3889 30.3446 21.2079C30.7861 21.0269 31.2594 20.9337 31.7374 20.9337ZM31.7371 27.1915C33.2665 27.1915 34.5063 25.9646 34.5063 24.451C34.5063 22.9375 33.2665 21.7106 31.7371 21.7106C30.2077 21.7106 28.9679 22.9375 28.9679 24.451C28.9679 25.9646 30.2077 27.1915 31.7371 27.1915Z M54.0424 32C54.0424 44.3777 44.0083 54.4118 31.6306 54.4118C19.2529 54.4118 9.21875 44.3777 9.21875 32C9.21875 19.6223 19.2529 9.58813 31.6306 9.58813C44.0083 9.58813 54.0424 19.6223 54.0424 32ZM31.7374 19.3933C30.36 19.3952 29.0396 19.9376 28.0659 20.9016C27.0921 21.8657 26.5444 23.1726 26.543 24.5356V39.4661C26.543 40.8294 27.0902 42.137 28.0644 43.101C29.0385 44.065 30.3597 44.6066 31.7374 44.6066C33.115 44.6066 34.4362 44.065 35.4104 43.101C36.3845 42.137 36.9318 40.8294 36.9318 39.4661V24.5356C36.9304 23.1726 36.3827 21.8657 35.4089 20.9016C34.4352 19.9376 33.1148 19.3952 31.7374 19.3933Z',
icon: 'M33.4814 11.2038C31.6046 10.2654 29.3954 10.2654 27.5186 11.2038L14.1852 17.8705C11.9267 18.9998 10.5 21.3082 10.5 23.8333V37.1667C10.5 39.6918 11.9267 42.0002 14.1852 43.1295L27.5186 49.7962C29.3954 50.7346 31.6046 50.7346 33.4814 49.7962L46.8148 43.1295C49.0733 42.0002 50.5 39.6918 50.5 37.1667V23.8333C50.5 21.3082 49.0733 18.9998 46.8148 17.8705L33.4814 11.2038ZM23.8333 23.8333C23.8333 20.1514 26.8181 17.1667 30.5 17.1667C34.1819 17.1667 37.1667 20.1514 37.1667 23.8333V37.1667C37.1667 40.8486 34.1819 43.8333 30.5 43.8333C26.8181 43.8333 23.8333 40.8486 23.8333 37.1667V23.8333Z M33.8333 23.8333C33.8333 25.6743 32.3409 27.1667 30.5 27.1667C28.6591 27.1667 27.1667 25.6743 27.1667 23.8333C27.1667 21.9924 28.6591 20.5 30.5 20.5C32.3409 20.5 33.8333 21.9924 33.8333 23.8333Z',
docs: 'https://supabase.com/docs/guides/getting-started/quickstarts/refine',
},
]
@@ -1,16 +0,0 @@
/* eslint-env node */
module.exports = {
env: { browser: true, es2020: true },
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react-hooks/recommended",
],
parser: "@typescript-eslint/parser",
parserOptions: { ecmaVersion: "latest", sourceType: "module" },
plugins: ["react-refresh"],
rules: {
"react-refresh/only-export-components": "warn",
},
};
@@ -1,15 +1,15 @@
# Supabase refine User Management
# Supabase Refine User Management
This repo is a quick sample of how you can get started building apps using [refine](https://github.com/refinedev/refine) and Supabase: users can sign up with a magic link and then update their account with public profile information, including a profile image.
This repo is a quick sample of how you can get started building apps using [Refine](https://github.com/refinedev/refine) and Supabase: users can sign up with a magic link and then update their account with public profile information, including a profile image.
## About refine
## About Refine
[refine](https://github.com/refinedev/refine) is a React-based framework for building data-intensive applications in no time ✨
[Refine](https://github.com/refinedev/refine) is a React-based framework for building data-intensive applications in no time ✨
refine offers lots of out-of-the box functionality for rapid development, without compromising extreme customizability. Use-cases include, but are not limited to admin panels, B2B applications and dashboards.
Refine offers lots of out-of-the box functionality for rapid development, without compromising extreme customizability. Use-cases include, but are not limited to admin panels, B2B applications and dashboards.
- To learn more about **refine**, please check out the [Documentation](https://refine.dev/docs)
- [Step up to refine tutorials.](https://refine.dev/docs/tutorial/introduction/index/)
- [Step up to Refine tutorials.](https://refine.dev/docs/tutorial/introduction/index/)
## Available Scripts
@@ -7,7 +7,7 @@
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="refine | Build your React-based CRUD applications, without constraints."
content="Refine | Build your React-based CRUD applications, without constraints."
/>
<meta
data-rh="true"
@@ -20,7 +20,7 @@
content="https://refine.dev/img/refine_social_new.png"
/>
<title>
refine - Build your React-based CRUD applications, without constraints.
Refine - Build your React-based CRUD applications, without constraints.
</title>
</head>
<body>
File diff suppressed because it is too large Load Diff
@@ -4,30 +4,25 @@
"private": true,
"type": "module",
"dependencies": {
"@refinedev/cli": "^2.5.1",
"@refinedev/core": "^4.5.8",
"@refinedev/inferencer": "^3.1.4",
"@refinedev/kbar": "^1.1.0",
"@refinedev/react-hook-form": "^4.4.0",
"@refinedev/react-router-v6": "^4.1.0",
"@refinedev/supabase": "^5.0.0",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-hook-form": "^7.45.0",
"react-router-dom": "^6.8.1"
"@refinedev/cli": "^2.16.50",
"@refinedev/core": "^5.0.5",
"@refinedev/inferencer": "^6.0.2",
"@refinedev/kbar": "^2.0.1",
"@refinedev/react-hook-form": "^5.0.2",
"@refinedev/react-router": "^2.0.3",
"@refinedev/supabase": "^6.0.1",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-hook-form": "^7.57.0",
"react-router": "^7.0.2"
},
"devDependencies": {
"@types/node": "^18.16.2",
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",
"@typescript-eslint/eslint-plugin": "^5.57.1",
"@typescript-eslint/parser": "^5.57.1",
"@vitejs/plugin-react": "^4.0.0",
"eslint": "^8.38.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.3.4",
"typescript": "^4.7.4",
"vite": "^4.3.1"
"@types/node": "^20",
"@types/react": "^19.1.0",
"@types/react-dom": "^19.1.0",
"@vitejs/plugin-react": "^4.2.1",
"typescript": "^5.8.3",
"vite": "^5.4.15"
},
"scripts": {
"dev": "refine dev",
Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

@@ -1,58 +1,58 @@
import { Authenticated, Refine } from '@refinedev/core';
import { RefineKbar, RefineKbarProvider } from '@refinedev/kbar';
import { Authenticated, Refine } from "@refinedev/core";
import routerBindings, {
CatchAllNavigate,
DocumentTitleHandler,
UnsavedChangesNotifier,
} from '@refinedev/react-router-v6';
import { dataProvider, liveProvider } from '@refinedev/supabase';
import { BrowserRouter, Outlet, Route, Routes } from 'react-router-dom';
import './App.css';
import authProvider from './authProvider';
import { supabaseClient } from './utility';
import Account from './components/account';
import Auth from './components/auth';
import routerProvider, {
CatchAllNavigate,
DocumentTitleHandler,
UnsavedChangesNotifier,
} from "@refinedev/react-router";
import { BrowserRouter, Outlet, Route, Routes } from "react-router";
import { supabaseClient } from "./providers/supabase-client";
import { authProvider } from "./providers/auth-provider";
import { dataProvider, liveProvider } from "@refinedev/supabase";
import Account from "./components/account";
import Auth from "./components/auth";
import "./App.css";
function App() {
return (
<BrowserRouter>
<RefineKbarProvider>
<Refine
dataProvider={dataProvider(supabaseClient)}
liveProvider={liveProvider(supabaseClient)}
authProvider={authProvider}
routerProvider={routerBindings}
options={{
syncWithLocation: true,
warnWhenUnsavedChanges: true,
}}
>
<Routes>
<Route
element={
<Authenticated
fallback={<CatchAllNavigate to="/login" />}
>
<Outlet />
</Authenticated>
}
>
<Route index element={<Account />} />
</Route>
<Route
element={<Authenticated fallback={<Outlet />} />}
>
<Route path="/login" element={<Auth />} />
</Route>
</Routes>
<RefineKbar />
<UnsavedChangesNotifier />
<DocumentTitleHandler />
</Refine>
</RefineKbarProvider>
</BrowserRouter>
);
return (
<BrowserRouter>
<Refine
dataProvider={dataProvider(supabaseClient)}
liveProvider={liveProvider(supabaseClient)}
authProvider={authProvider}
routerProvider={routerProvider}
options={{
syncWithLocation: true,
warnWhenUnsavedChanges: true,
}}
>
<Routes>
<Route
element={
<Authenticated
key="authenticated-routes"
fallback={<CatchAllNavigate to="/login" />}
>
<Outlet />
</Authenticated>
}
>
<Route index element={<Account />} />
</Route>
<Route
element={<Authenticated key="auth-pages" fallback={<Outlet />} />}
>
<Route path="/login" element={<Auth />} />
</Route>
</Routes>
<UnsavedChangesNotifier />
<DocumentTitleHandler />
</Refine>
</BrowserRouter>
);
}
export default App;
@@ -1,20 +1,22 @@
import { BaseKey, useGetIdentity, useLogout } from "@refinedev/core";
import { useForm } from "@refinedev/react-hook-form";
import { Controller } from "react-hook-form";
import Avatar from "./avatar";
interface IUserIdentity {
id?: BaseKey;
username: string;
name: string;
};
}
export interface IProfile {
id?: string;
username?: string;
website?: string;
avatar_url?: string;
};
}
export default function Account() {
const { data: userIdentity } = useGetIdentity<IUserIdentity>();
@@ -22,7 +24,7 @@ export default function Account() {
const { mutate: logOut } = useLogout();
const {
refineCore: { formLoading, queryResult, onFinish },
refineCore: { formLoading, query, onFinish },
register,
control,
handleSubmit,
@@ -49,9 +51,10 @@ export default function Account() {
size={150}
onUpload={(filePath) => {
onFinish({
...queryResult?.data?.data,
...query?.data?.data,
avatar_url: filePath,
onMutationError: (data: { message: string; }) => alert(data?.message),
onMutationError: (data: { message: string }) =>
alert(data?.message),
});
field.onChange({
target: {
@@ -104,4 +107,4 @@ export default function Account() {
</form>
</div>
);
};
}
@@ -1,20 +1,23 @@
import { useState } from "react";
import { useLogin } from "@refinedev/core";
export default function Auth() {
const [email, setEmail] = useState("");
const { isLoading, mutate: login } = useLogin();
const handleLogin = async (event: { preventDefault: () => void }) => {
event.preventDefault();
login({ email });
};
const [email, setEmail] = useState("");
const { isPending, mutate: login } = useLogin();
const handleLogin = async (event: { preventDefault: () => void }) => {
event.preventDefault();
login({ email });
};
return (
<div className="row flex flex-center container">
<div className="col-6 form-widget">
<h1 className="header">Supabase + refine</h1>
<p className="description">Sign in via magic link with your email below</p>
<h1 className="header">Supabase + Refine</h1>
<p className="description">
Sign in via magic link with your email below
</p>
<form className="form-widget" onSubmit={handleLogin}>
<div>
<input
@@ -27,12 +30,12 @@ export default function Auth() {
/>
</div>
<div>
<button className={"button block"} disabled={isLoading}>
{isLoading ? <span>Loading</span> : <span>Send magic link</span>}
<button className={"button block"} disabled={isPending}>
{isPending ? <span>Loading</span> : <span>Send magic link</span>}
</button>
</div>
</form>
</div>
</div>
);
};
}
@@ -1,5 +1,6 @@
import { useEffect, useState } from "react";
import { supabaseClient } from "../utility/supabaseClient";
import { supabaseClient } from "../providers/supabase-client";
type TAvatarProps = {
url?: string;
@@ -7,11 +8,7 @@ type TAvatarProps = {
onUpload: (filePath: string) => void;
};
export default function Avatar({
url,
size,
onUpload,
}: TAvatarProps) {
export default function Avatar({ url, size, onUpload }: TAvatarProps) {
const [avatarUrl, setAvatarUrl] = useState("");
const [uploading, setUploading] = useState(false);
@@ -96,4 +93,4 @@ export default function Avatar({
</div>
</div>
);
};
}
@@ -9,5 +9,5 @@ const root = createRoot(container);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
</React.StrictMode>,
);
@@ -1,8 +1,8 @@
import { AuthBindings } from "@refinedev/core";
import { AuthProvider } from "@refinedev/core";
import { supabaseClient } from "./utility";
import { supabaseClient } from "./supabase-client";
const authProvider: AuthBindings = {
export const authProvider: AuthProvider = {
login: async ({ email }) => {
try {
const { error } = await supabaseClient.auth.signInWithOtp({ email });
@@ -12,8 +12,8 @@ const authProvider: AuthBindings = {
return {
success: true,
};
};
}
throw error;
} catch (e: any) {
alert(e.message);
@@ -87,5 +87,3 @@ const authProvider: AuthBindings = {
return null;
},
};
export default authProvider;
@@ -1,14 +1,17 @@
import { createClient } from "@refinedev/supabase";
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
const supabasePublishableKey = import.meta.env.VITE_SUPABASE_ANON_KEY;
export const supabaseClient = createClient(supabaseUrl, supabasePublishableKey, {
db: {
schema: "public",
export const supabaseClient = createClient(
supabaseUrl,
supabasePublishableKey,
{
db: {
schema: "public",
},
auth: {
persistSession: true,
},
},
auth: {
persistSession: true,
},
});
);
@@ -1 +0,0 @@
export * from "./supabaseClient";
@@ -16,7 +16,7 @@
"noEmit": true,
"jsx": "react-jsx"
},
"include": ["src", "vite.config.ts"],
"include": ["src"],
"references": [
{
"path": "./tsconfig.node.json"
+1
View File
@@ -174,6 +174,7 @@ may_uppercase = [
"Reciprocal Ranked Fusion",
"Redis",
"RedwoodJS",
"Refine",
"Remix",
"Render",
"Retrieval Plugin",
+1
View File
@@ -277,6 +277,7 @@ allow_list = [
"README",
"Redis",
"RedwoodJS",
"Refine",
"Roboflow",
"SDKs",
"SQLAlchemy",