Merge branch 'fs/lwd4' of github.com:supabase/supabase into fs/lwd4

This commit is contained in:
Copple committed 2023-08-10 16:04:24 +02:00
commit 56e810f794
4 files changed
+81 -87

No files matched your search

@@ -17,17 +17,17 @@ We've been running our [Integrations Marketplace](/partners) in “stealth mode
![Featured](/images/blog/launch-week-8/day-4/featured-integrations.png)
Supabase Integrations allows Partners to extend the Supabase platform with useful tooling. Today we're adding [OAuth2.0 Applications](https://supabase.com/docs/guides/platform/oauth-apps/publish-an-oauth-app). For Supabase users, this makes it even easier to connect your favorite tools to the Supabase projects. Within minutes you can:
Supabase Integrations allows Partners to extend the Supabase platform with useful tooling. Today we're adding [OAuth2.0 Applications](https://supabase.com/docs/guides/platform/oauth-apps/publish-an-oauth-app). For Supabase users, this makes it even easier to connect their favorite tools to their Supabase projects. Within minutes you can:
- Add your favorite [Low Code](https://supabase.com/partners/integrations#low-code) tools on top of your Supabase database.
- Integrate your favorite [DevTools](https://supabase.com/partners/integrations#devtools): including secrets managers and database management tools.
- Add [caching](https://supabase.com/partners/integrations#caching%20/%20offline-first) to your Supabase database.
- Don't link the Supabase admin dashboard? Try [one of these](https://supabase.com/partners/integrations#data%20platform).
- Not a fan of the Supabase admin dashboard? Try [one of these](https://supabase.com/partners/integrations#data%20platform).
- Try out a different [SMS and email provider](https://supabase.com/partners/integrations#messaging).
## Featured Partners
For the initial launch we're started with a few development partners who we worked with to build and test the OAuth functionality.
For the initial launch we've started with a few partners to help us build and test the OAuth functionality.
### Cloudflare
@@ -49,7 +49,7 @@ Read more on [Resend's blog](https://resend.com/blog/how-to-configure-supabase-t
![Snaplet x Supabase](/images/blog/launch-week-8/day-4/marketplace-snaplet.jpg)
Snaplet is a tool for Typescript developers to copy your database, transform sensitive data, and share it with your team without worrying about PII. If you followed our [Tuesday launch](https://supabase.com/blog/supabase-local-dev#database-seeding) you'll be familiar with Snaplet - they are one of the best tools for [generating seed data](https://supabase.com/docs/guides/cli/seeding-your-database#generating-seed-data) for your local development environment. Now they are making it even easier with their official OAuth App build production-like development environments for you team.
Snaplet is a tool for Typescript developers to copy your database, transform sensitive data, and share it with your team without worrying about PII. If you followed our [Tuesday launch](https://supabase.com/blog/supabase-local-dev#database-seeding) you'll be familiar with Snaplet - they are one of the best tools for [generating seed data](https://supabase.com/docs/guides/cli/seeding-your-database#generating-seed-data) for your local development environment. Now they are making it even easier, with their official OAuth App, to spin up production-like development environments for your team.
[Learn more on snaplet.dev](https://www.snaplet.dev/post/now-live-supabase-x-snaplet-integration).
@@ -73,7 +73,7 @@ Learn more about the Vercel integration [updates we're launching](/blog/using-su
![Windmill x Supabase](/images/blog/launch-week-8/day-4/marketplace-windmill.jpg)
[Windmill](https://windmill.dev) (YC [S22](https://www.ycombinator.com/companies/windmill)) is an open-source open source alternative to Retool and a modern Airflow. They provide a developer platform to quickly build production-grade complex workflows and integrations from minimal Python and Typescript scripts. Their one-click integration with Supabase makes it simple to launch new databases, process large quantities of data (maybe even convert them into [embeddings](https://supabase.com/vector)), and build internal dashboards.
[Windmill](https://windmill.dev) (YC [S22](https://www.ycombinator.com/companies/windmill)) is an open source alternative to Retool and a modern Airflow. They provide a developer platform to quickly build production-grade complex workflows and integrations from minimal Python and Typescript scripts. Their one-click integration with Supabase makes it simple to launch new databases, process large quantities of data (maybe even convert them into [embeddings](https://supabase.com/vector)), and build internal dashboards.
Read the [official blog post on windmill.dev](https://www.windmill.dev/blog/2023/08/10/supabase-partnership).
@@ -97,6 +97,24 @@ export const TwitterSpacesSvg = () => (
</svg>
)
export const ProductHuntSvg = () => (
<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_3061_22934)">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M8.00078 15.5094C12.0787 15.5094 15.3844 12.2037 15.3844 8.12578C15.3844 4.04782 12.0787 0.742188 8.00078 0.742188C3.92282 0.742188 0.617188 4.04782 0.617188 8.12578C0.617188 12.2037 3.92282 15.5094 8.00078 15.5094ZM6.89312 8.12578H8.98527C9.279 8.12578 9.56071 8.00909 9.76841 7.80139C9.97612 7.59369 10.0928 7.31198 10.0928 7.01824C10.0928 6.7245 9.97612 6.4428 9.76841 6.23509C9.56071 6.02739 9.279 5.9107 8.98527 5.9107H6.89312V8.12578ZM5.41641 4.43398H8.98527C9.67065 4.43398 10.328 4.70625 10.8126 5.1909C11.2973 5.67554 11.5695 6.33285 11.5695 7.01824C11.5695 7.70363 11.2973 8.36095 10.8126 8.84559C10.328 9.33023 9.67065 9.6025 8.98527 9.6025H6.89312V11.8176H5.41641V4.43398Z"
fill="#8F8F8F"
/>
</g>
<defs>
<clipPath id="clip0_3061_22934">
<rect width="16" height="16" fill="currentColor" transform="translate(0 0.378906)" />
</clipPath>
</defs>
</svg>
)
export const CheckCircleSolidIcon = () => (
<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
@@ -337,6 +355,7 @@ export const SectionButtons = ({
url,
hackernews,
twitter_spaces,
product_hunt,
mobileGrid,
}: {
blog?: string
@@ -346,6 +365,7 @@ export const SectionButtons = ({
url?: string
hackernews?: string
twitter_spaces?: string
product_hunt?: string
mobileGrid?: boolean
}) => {
return (
@@ -403,6 +423,14 @@ export const SectionButtons = ({
</div>
</ChipLink>
)}
{product_hunt && (
<ChipLink href={product_hunt} target="_blank" className="col-span-full">
Product Hunt
<div className="bg-[#313131] rounded-full hidden sm:inline-block p-1 ml-2">
<ProductHuntSvg />
</div>
</ChipLink>
)}
{twitter_spaces && (
<ChipLink href={twitter_spaces} target="_blank" className="col-span-full">
Twitter Spaces
@@ -1,16 +1,11 @@
import Image from 'next/image'
import { motion } from 'framer-motion'
import Link from 'next/link'
import { Accordion } from 'ui'
import { useBreakpoint } from 'common/hooks/useBreakpoint'
import days, { WeekDayProps } from './lw8_data'
import SectionContainer from '~/components/Layouts/SectionContainer'
import { AccordionHeader, CartTitle, CheckCircleSolidIcon, SectionButtons } from './components'
import Link from 'next/link'
export const defaultEase = [0.25, 0.25, 0, 1]
export const defaultDuratonIn = 0.25
export const defaultDuratonOut = 0.1
import SectionContainer from '~/components/Layouts/SectionContainer'
import days, { WeekDayProps } from './lw8_data'
export default function LW8Releases() {
const [preRelease, day1, day2, day3, day4, day5] = days
@@ -55,14 +50,11 @@ export default function LW8Releases() {
>
{preRelease.steps.length > 0 && (
<div className="flex flex-col gap-5 lg:flex-row pb-4">
<motion.div
<div
className={`
min-h-[400px] relative overflow-hidden group/pre0 flex-1 flex flex-col items-center justify-between
basis-1/2 lg:basis-1/3 border border-[#111718] rounded-xl lg:h-full bg-no-repeat py-10 lg:py-12 px-8 lg:px-10 text-2xl bg-contain shadow-lg
`}
initial="default"
animate="default"
whileHover="hover"
>
<div
className="inset-0 absolute group-hover/pre0:scale-105 opacity-10 group-hover/pre0:opacity-100 w-full h-full -z-10 transition-all duration-500 pointer-events-none"
@@ -79,7 +71,7 @@ export default function LW8Releases() {
preRelease.steps[0]?.bg_layers?.map(
(layer, i) =>
!!layer.img && (
<motion.div className="absolute opacity-90 inset-0 w-full h-full -z-10">
<div className="absolute opacity-90 transition-opacity inset-0 w-full h-full -z-10 group-hover/d1:opacity-100">
<Image
src={
!!layer.mobileImg && isTablet
@@ -94,18 +86,15 @@ export default function LW8Releases() {
objectPosition="100%"
objectFit="cover"
/>
</motion.div>
</div>
)
)}
</motion.div>
<motion.div
</div>
<div
className={`
min-h-[400px] relative overflow-hidden group/pre1 flex-1 flex flex-col items-center justify-between
basis-1/2 lg:basis-1/3 border border-[#111718] rounded-xl lg:h-full bg-no-repeat py-10 lg:py-12 px-8 lg:px-10 text-2xl bg-cover shadow-lg
`}
initial="default"
animate="default"
whileHover="hover"
>
<div
className="inset-0 absolute group-hover/pre1:scale-105 opacity-60 group-hover/pre1:opacity-100 w-full h-full -z-10 transition-all duration-500 pointer-events-none"
@@ -125,7 +114,7 @@ export default function LW8Releases() {
preRelease.steps[1]?.bg_layers?.map(
(layer, i) =>
!!layer.img && (
<motion.div className="absolute opacity-90 inset-0 w-full h-full -z-10">
<div className="absolute opacity-90 transition-opacity inset-0 w-full h-full -z-10 group-hover/d1:opacity-100">
<Image
src={
!!layer.mobileImg && isTablet
@@ -140,19 +129,17 @@ export default function LW8Releases() {
objectPosition="20% 50%"
objectFit="cover"
/>
</motion.div>
</div>
)
)}
</motion.div>
<motion.div
</div>
<div
className={`
min-h-[400px] relative overflow-hidden group/pre2 flex-1 flex flex-col items-center justify-between
basis-1/2 lg:basis-1/3 border border-[#111718] rounded-xl lg:h-full bg-no-repeat py-10 lg:py-12 px-8 lg:px-10 text-2xl bg-contain shadow-lg
`}
initial="default"
animate="default"
whileHover="hover"
>
{' '}
<div
className="inset-0 absolute group-hover/pre2:scale-105 opacity-60 group-hover/pre2:opacity-100 w-full h-full -z-10 transition-all duration-500 pointer-events-none"
style={{
@@ -168,7 +155,7 @@ export default function LW8Releases() {
preRelease.steps[2]?.bg_layers?.map(
(layer, i) =>
!!layer.img && (
<motion.div className="absolute opacity-90 inset-0 w-full h-full -z-10">
<div className="absolute opacity-90 transition-opacity inset-0 w-full h-full -z-10 group-hover/d1:opacity-100">
<Image
src={layer.img}
className={`
@@ -181,10 +168,10 @@ export default function LW8Releases() {
}
objectFit="contain"
/>
</motion.div>
</div>
)
)}
</motion.div>
</div>
</div>
)}
</Accordion.Item>
@@ -203,14 +190,11 @@ export default function LW8Releases() {
{day1.steps.length > 0 && (
<div className="flex flex-col gap-5 lg:flex-row pb-4">
<motion.div
<div
className={`
min-h-[400px] relative overflow-hidden group/d1 flex-1 flex flex-col items-center lg:items-start justify-between
basis-1/2 lg:basis-1/3 border border-[#111718] rounded-xl lg:h-full bg-no-repeat py-10 lg:py-12 px-8 lg:px-10 text-2xl bg-contain shadow-lg
`}
initial="default"
animate="default"
whileHover="hover"
>
<div
className="inset-0 absolute group-hover/d1:scale-105 opacity-60 group-hover/d1:opacity-100 w-full h-full -z-10 transition-all duration-500 pointer-events-none"
@@ -231,7 +215,7 @@ export default function LW8Releases() {
day1.steps[0]?.bg_layers?.map(
(layer, i) =>
!!layer.img && (
<motion.div className="absolute opacity-90 inset-0 w-full h-full -z-10">
<div className="absolute opacity-90 transition-opacity inset-0 w-full h-full -z-10 group-hover/d1:opacity-100">
<Image
src={
!!layer.mobileImg && isTablet ? (layer.mobileImg as any) : layer.img
@@ -244,10 +228,10 @@ export default function LW8Releases() {
objectPosition={isTablet ? '50%' : '90% 50%'}
objectFit="contain"
/>
</motion.div>
</div>
)
)}
</motion.div>
</div>
</div>
)}
</div>
@@ -265,14 +249,11 @@ export default function LW8Releases() {
{day2.steps.length > 0 && (
<div className="flex flex-col gap-5 lg:flex-row pb-4">
<motion.div
<div
className={`
min-h-[400px] relative overflow-hidden group/d1 flex-1 flex flex-col items-center lg:items-start justify-between
basis-1/2 lg:basis-1/3 border border-[#111718] rounded-xl lg:h-full bg-no-repeat py-10 lg:py-12 px-8 lg:px-10 text-2xl bg-contain shadow-lg
`}
initial="default"
animate="default"
whileHover="hover"
>
<div
className="inset-0 absolute group-hover/d1:scale-105 opacity-60 group-hover/d1:opacity-100 w-full h-full -z-10 transition-all duration-500 pointer-events-none"
@@ -293,7 +274,7 @@ export default function LW8Releases() {
day2.steps[0]?.bg_layers?.map(
(layer, i) =>
!!layer.img && (
<motion.div className="absolute opacity-90 inset-0 w-full h-full -z-10">
<div className="absolute opacity-90 transition-opacity inset-0 w-full h-full -z-10 group-hover/d1:opacity-100">
<Image
src={
!!layer.mobileImg && isTablet ? (layer.mobileImg as any) : layer.img
@@ -305,10 +286,10 @@ export default function LW8Releases() {
layout="fill"
objectFit="cover"
/>
</motion.div>
</div>
)
)}
</motion.div>
</div>
</div>
)}
</div>
@@ -326,14 +307,11 @@ export default function LW8Releases() {
{day3.steps.length > 0 && (
<div className="flex flex-col gap-5 lg:flex-row pb-4">
<motion.div
<div
className={`
min-h-[400px] relative overflow-hidden group/d1 flex-1 flex flex-col items-center lg:items-start justify-between
basis-1/2 lg:basis-1/3 border border-[#111718] rounded-xl lg:h-full bg-no-repeat py-10 lg:py-12 px-8 lg:px-10 text-2xl bg-contain shadow-lg
`}
initial="default"
animate="default"
whileHover="hover"
>
<div
className="inset-0 absolute group-hover/d1:scale-105 opacity-60 group-hover/d1:opacity-100 w-full h-full -z-10 transition-all duration-500 pointer-events-none"
@@ -360,12 +338,15 @@ export default function LW8Releases() {
</li>
</ul>
</div>
<SectionButtons blog={day3.steps[0].blog} hackernews={day3.steps[0].hackernews} />
<SectionButtons
blog={day3.steps[0].blog}
product_hunt={day3.steps[0].product_hunt}
/>
{day3.steps[0]?.bg_layers &&
day3.steps[0]?.bg_layers?.map(
(layer, i) =>
!!layer.img && (
<motion.div className="absolute opacity-90 inset-0 w-full h-full -z-10">
<div className="absolute opacity-90 transition-opacity inset-0 w-full h-full -z-10 group-hover/d1:opacity-100">
<Image
src={
!!layer.mobileImg && isTablet ? (layer.mobileImg as any) : layer.img
@@ -375,10 +356,10 @@ export default function LW8Releases() {
objectPosition={isTablet ? '50%' : '100% 50%'}
objectFit={i == 1 && isTablet ? 'contain' : 'cover'}
/>
</motion.div>
</div>
)
)}
</motion.div>
</div>
</div>
)}
</div>
@@ -396,14 +377,11 @@ export default function LW8Releases() {
{day4.steps.length > 0 && (
<div className="flex flex-col gap-5 lg:flex-row pb-4">
<motion.div
<div
className={`
min-h-[400px] relative overflow-hidden group/d1 flex-1 flex flex-col items-center lg:items-start justify-between
basis-1/2 lg:flex-shrink xl:basis-2/3 border border-[#111718] rounded-xl lg:h-full bg-no-repeat py-10 lg:py-12 px-8 lg:px-10 text-2xl bg-contain shadow-lg
`}
initial="default"
animate="default"
whileHover="hover"
>
<div
className="inset-0 absolute group-hover/d1:scale-105 opacity-60 group-hover/d1:opacity-100 w-full h-full -z-10 transition-all duration-500 pointer-events-none"
@@ -419,12 +397,12 @@ export default function LW8Releases() {
</Link>
<p className="text-sm text-slate-900">{day4.steps[0]?.description}</p>
</div>
<SectionButtons blog={day4.steps[0].blog} hackernews={day4.steps[0].hackernews} />
<SectionButtons blog={day4.steps[0].blog} />
{day4.steps[0]?.bg_layers &&
day4.steps[0]?.bg_layers?.map(
(layer, i) =>
!!layer.img && (
<motion.div className="absolute opacity-90 inset-0 w-full h-full -z-10">
<div className="absolute opacity-90 transition-opacity inset-0 w-full h-full -z-10 group-hover/d1:opacity-100">
<Image
src={
!!layer.mobileImg && isTablet ? (layer.mobileImg as any) : layer.img
@@ -434,18 +412,15 @@ export default function LW8Releases() {
objectPosition={isTablet ? '50%' : '100% 50%'}
objectFit={i == 1 && isTablet ? 'contain' : 'cover'}
/>
</motion.div>
</div>
)
)}
</motion.div>
<motion.div
</div>
<div
className={`
min-h-[400px] relative overflow-hidden group/d1 flex-1 flex flex-col items-center justify-between
basis-1/2 lg:basis-1/3 border border-[#111718] rounded-xl lg:h-full bg-no-repeat py-10 lg:py-12 px-8 lg:px-10 text-2xl bg-contain shadow-lg
`}
initial="default"
animate="default"
whileHover="hover"
>
<div
className="inset-0 absolute group-hover/d1:scale-105 opacity-60 group-hover/d1:opacity-100 w-full h-full -z-10 transition-all duration-500 pointer-events-none"
@@ -466,7 +441,7 @@ export default function LW8Releases() {
day4.steps[1]?.bg_layers?.map(
(layer, i) =>
!!layer.img && (
<motion.div className="absolute opacity-90 inset-0 w-full h-full -z-10">
<div className="absolute opacity-90 transition-opacity inset-0 w-full h-full -z-10 group-hover/d1:opacity-100">
<Image
src={
!!layer.mobileImg && isTablet ? (layer.mobileImg as any) : layer.img
@@ -475,10 +450,10 @@ export default function LW8Releases() {
layout="fill"
objectFit="cover"
/>
</motion.div>
</div>
)
)}
</motion.div>
</div>
</div>
)}
</div>
@@ -26,7 +26,7 @@ export interface StepProps {
description?: string
github?: string
hackernews?: string
templates?: string
product_hunt?: string
isNew?: boolean
thumb?: string
url?: string
@@ -51,8 +51,8 @@ export interface WeekDayProps {
dd: string
youtube_id: string
videoThumbnail?: string
blogpost: string
docs: string
blogpost?: string
docs?: string
twitter_spaces?: string
steps: StepProps[] | []
}
@@ -103,8 +103,6 @@ const days: WeekDayProps[] = [
dd: 'Mon',
youtube_id: 'RJccSbJ9Go4',
videoThumbnail: images.day_1_thumb,
blogpost: '',
docs: '',
twitter_spaces: 'https://twitter.com/i/spaces/1DXGyvjkeEeJM',
steps: [
{
@@ -128,15 +126,12 @@ const days: WeekDayProps[] = [
dd: 'Tue',
youtube_id: 'N0Wb85m3YMI',
videoThumbnail: images.day_2_thumb,
blogpost: '',
twitter_spaces: 'https://twitter.com/i/spaces/1vAxRAvNQyDJl?s=20',
docs: '',
steps: [
{
title: 'Supabase Local Dev: Migrations, Branching, Observability',
blog: '/blog/supabase-local-dev',
hackernews: '',
video: '',
hackernews: 'https://news.ycombinator.com/item?id=37059400',
twitter_spaces: 'https://twitter.com/i/spaces/1vAxRAvNQyDJl?s=20',
bg_layers: [{ img: images['02-localdev'], mobileImg: images['02-localdev-mobile'] }],
steps: [],
@@ -153,14 +148,13 @@ const days: WeekDayProps[] = [
dd: 'Wed',
youtube_id: '51tCMQPiitQ',
videoThumbnail: images.day_3_thumb,
blogpost: '',
docs: '',
steps: [
{
title: 'Supabase Studio 3.0',
blog: '/blog/supabase-studio-3-0',
hackernews: '',
video: '',
product_hunt: 'https://www.producthunt.com/posts/ai-powered-sql-editor',
twitter_spaces: 'https://twitter.com/i/spaces/1vAxRAvNQyDJl?s=20',
bg_layers: [{ img: images['03-studio3'], mobileImg: images['03-studio3-mobile'] }],
steps: [],
@@ -177,8 +171,7 @@ const days: WeekDayProps[] = [
dd: 'Thu',
youtube_id: 'gtJo1lTxHfs',
videoThumbnail: images.day_4_thumb,
blogpost: '',
docs: '',
twitter_spaces: 'https://twitter.com/supabase/status/1688544207571484672?s=20',
steps: [
{
title: 'Supabase Integrations Marketplace',
@@ -198,13 +191,11 @@ const days: WeekDayProps[] = [
title: '',
shipped: false,
date: '11 Aug',
publishedAt: '2023-08-11T00:00:00.000-07:00',
publishedAt: '2023-08-11T09:00:00.000-07:00',
description: '',
d: 5,
dd: 'Fri',
youtube_id: '',
blogpost: '',
docs: '',
steps: [],
},
]