diff --git a/apps/www/_alternatives/supabase-vs-firebase.mdx b/apps/www/_alternatives/supabase-vs-firebase.mdx index 893233e3517..20355efa97a 100644 --- a/apps/www/_alternatives/supabase-vs-firebase.mdx +++ b/apps/www/_alternatives/supabase-vs-firebase.mdx @@ -2,8 +2,6 @@ title: Supabase vs Firebase description: Supabase is an Open Source Firebase Alternative with a SQL based Database, Auth, and Cloud Functions author: ant_wilson -image: partner-gallery/partner-showcase-thumb.png -thumb: partner-gallery/partner-showcase-thumb.png tags: - comparison date: '2022-05-26' @@ -44,7 +42,7 @@ Both Firebase and Supabase have invested heavily in client side libraries so you ## How are they different? -Firebase and Supabase differ in several ways. The main one being that Firebase is a document store, whereas Supabase is based on PostgreSQL - a relational, SQL-based database management system. +Firebase and Supabase differ in several ways. The main one being that Firebase is a document store, whereas Supabase is based on PostgreSQL - a relational, SQL-based database management system. There are some other important differences. diff --git a/apps/www/_alternatives/supabase-vs-heroku-postgres.mdx b/apps/www/_alternatives/supabase-vs-heroku-postgres.mdx index 50fadb5b16c..b1fa67553dc 100644 --- a/apps/www/_alternatives/supabase-vs-heroku-postgres.mdx +++ b/apps/www/_alternatives/supabase-vs-heroku-postgres.mdx @@ -2,8 +2,6 @@ title: Supabase vs Heroku Postgres description: Supabase is an alternative to Heroku Postgres with Enterprise Grade Support available author: ant_wilson -image: partner-gallery/partner-showcase-thumb.png -thumb: partner-gallery/partner-showcase-thumb.png tags: - comparison date: '2022-05-26' diff --git a/apps/www/_blog/2022-06-15-loading-data-supabase-python.mdx b/apps/www/_blog/2022-06-15-loading-data-supabase-python.mdx index 3d5f8a75394..d01a2f1631b 100644 --- a/apps/www/_blog/2022-06-15-loading-data-supabase-python.mdx +++ b/apps/www/_blog/2022-06-15-loading-data-supabase-python.mdx @@ -173,6 +173,13 @@ Data can also be viewed directly from the Supabase dashboard. To do this, go to Note: In case you cannot see any of the data, you should hit the Refresh button. ## Conclusion -With Python, data loading into Supabase is easy. It just takes a few easy steps to get started with the Python SDK and Supabase. In the next part of this blog series, we will learn [how to visualize the data that we just loaded into Supabase using Metabase](blog/visualizing-supabase-data-using-metabase). Stay tuned! +With Python, data loading into Supabase is easy. It just takes a few easy steps to get started with the Python SDK and Supabase. In the next part of this blog series, we will learn [how to visualize the data that we just loaded into Supabase using Metabase](/blog/visualizing-supabase-data-using-metabase). Stay tuned! If you have any questions please reach out via [Twitter](https://twitter.com/supabase) or join our [Discord](https://discord.supabase.com). + +## More Python and Supabase resources +- [supabase-py](https://github.com/supabase-community/supabase-py) +- [Slack Consolidate: a slackbot built with Python and Supabase](blog/slack-consolidate-slackbot-to-consolidate-messages) +- [Supabase-py (Database) on Replit](https://replit.com/@Supabase/Supabase-py-Database?v=1) + + diff --git a/apps/www/_blog/2022-06-29-visualizing-supabase-data-using-metabase.mdx b/apps/www/_blog/2022-06-29-visualizing-supabase-data-using-metabase.mdx index cc6c11d2c73..62931872587 100644 --- a/apps/www/_blog/2022-06-29-visualizing-supabase-data-using-metabase.mdx +++ b/apps/www/_blog/2022-06-29-visualizing-supabase-data-using-metabase.mdx @@ -16,7 +16,7 @@ Data helps organizations make better decisions. With a programming language like With Metabase, a powerful visualization tool, you can quickly turn your data into easy-to-understand visuals like graphs, pie charts, flow diagrams, and much more. Then, using Metabase’s intuitive interface, you can cut through the data noise and focus on what’s essential for your business. -In the previous blog of this series**,** we explained [how to use Python to load data into Supabase](https://supabase.com/blog/loading-data-supabase-python). In this blog, we will create different kinds of charts out of the data stored in Supabase using Metabase. +In the previous blog of this series, we explained [how to use Python to load data into Supabase](https://supabase.com/blog/loading-data-supabase-python). In this blog, we will create different kinds of charts out of the data stored in Supabase using Metabase. ## Prerequisites @@ -133,3 +133,8 @@ Data visualization empowers organizations to turn unused data into actionable in With our [free tier Supabase account](https://app.supabase.com/), you can start a new project today and use Metabase to visualize your app data. If you have any questions please reach out via [Twitter](https://twitter.com/supabase) or join our [Discord](https://discord.supabase.com). + +## More Python and Supabase resources +- [supabase-py](https://github.com/supabase-community/supabase-py) +- [Slack Consolidate: a slackbot built with Python and Supabase](blog/slack-consolidate-slackbot-to-consolidate-messages) +- [Supabase-py (Database) on Replit](https://replit.com/@Supabase/Supabase-py-Database?v=1) diff --git a/apps/www/_blog/2022-08-02-supabase-flutter-sdk-1-developer-preview.mdx b/apps/www/_blog/2022-08-02-supabase-flutter-sdk-1-developer-preview.mdx index 9e35158163c..078d2e0134a 100644 --- a/apps/www/_blog/2022-08-02-supabase-flutter-sdk-1-developer-preview.mdx +++ b/apps/www/_blog/2022-08-02-supabase-flutter-sdk-1-developer-preview.mdx @@ -146,7 +146,7 @@ SupaSocialsAuth( ## Final thoughts -These updates are just the tip of the iceberg for 1.0. There are been many bug fixes and features constantly being added to the Supabase Flutter SDK. This could not have been possible with the help from the open source community. Here, I would also like to give a shout out to two other developers who have been a major part of the journey of this SDK: [Vinzent](https://twitter.com/Vinzent03_) and [Daniel Mossaband](https://github.com/DanMossa). They have been a huge part of the Supabase Flutter SDK - not just for the 1.0 release, but throughout the lifetime of the library. +These updates are just the tip of the iceberg for 1.0. There are been many bug fixes and features constantly being added to the Supabase Flutter SDK. This could not have been possible without the help from the open source community. Here, I would also like to give a shout out to two other developers who have been a major part of the journey of this SDK: [Vinzent](https://twitter.com/Vinzent03_) and [Daniel Mossaband](https://github.com/DanMossa). They have been a huge part of the Supabase Flutter SDK - not just for the 1.0 release, but throughout the lifetime of the library. For those of you who want to try out the new SDK, you can get the developer preview version from [supabase-flutter](https://pub.dev/packages/supabase_flutter/versions/1.0.0-dev.1) pub.dev page or can simply copy and paste the following into your pubspec.yaml file. ```yaml diff --git a/apps/www/_blog/2022-08-09-slack-consolidate-slackbot-to-consolidate-messages.mdx b/apps/www/_blog/2022-08-09-slack-consolidate-slackbot-to-consolidate-messages.mdx index 7faa6fc7ab4..2172b0330a7 100644 --- a/apps/www/_blog/2022-08-09-slack-consolidate-slackbot-to-consolidate-messages.mdx +++ b/apps/www/_blog/2022-08-09-slack-consolidate-slackbot-to-consolidate-messages.mdx @@ -2,8 +2,8 @@ title: 'Slack Consolidate: a slackbot built with Python and Supabase' description: A slackbot to consolidate messages from different channels using Supabase, Slack SDK and Python author: rodrigo_mansueli -image: slackbot-consilidate/slackbot-thumb.jpg -thumb: slackbot-consilidate/slackbot-thumb.jpg +image: slackbot-consolidate/slackbot-thumb.jpg +thumb: slackbot-consolidate/slackbot-thumb.jpg tags: - slack - python @@ -35,19 +35,19 @@ Now, it is time to create the bot in Slack and get the API Keys (after granting [https://api.slack.com/apps](https://api.slack.com/apps) -![Green arrow pointing to the ‘Create New App’ button.](/images/blog/slackbot-consilidate/00_create_new_app.png) +![Green arrow pointing to the ‘Create New App’ button.](/images/blog/slackbot-consolidate/00_create_new_app.png) Green arrow pointing to the ‘Create New App’ button. Then, select to create an app from a manifest (this will already set the required permissions) for the app: -![Green arrow pointing to the option ‘From an app manifest’ inside the “Create an app” menu.](/images/blog/slackbot-consilidate/01_create_an_slack_app.png) +![Green arrow pointing to the option ‘From an app manifest’ inside the “Create an app” menu.](/images/blog/slackbot-consolidate/01_create_an_slack_app.png) Green arrow pointing to the option ‘From an app manifest’ inside the “Create an app” menu. Select the Slack workspace to deploy: -![The picture shows a dropdown UI with Supabase selected as the workspace.](/images/blog/slackbot-consilidate/02_pick_workspace.png) +![The picture shows a dropdown UI with Supabase selected as the workspace.](/images/blog/slackbot-consolidate/02_pick_workspace.png) The picture shows a dropdown UI with Supabase selected as the workspace. @@ -88,13 +88,13 @@ token_rotation_enabled: false Enter the manifest above when asked: -![The picture shows the place where you have to paste the manifest file included in the repo.](/images/blog/slackbot-consilidate/03_enter_manifest.png) +![The picture shows the place where you have to paste the manifest file included in the repo.](/images/blog/slackbot-consolidate/03_enter_manifest.png) The picture shows the place where you have to paste the manifest file included in the repo. Then, confirm to create the bot: -![You can see a summary screen to confirm the creation of the bot and the scopes assigned.](/images/blog/slackbot-consilidate/04_confirm_window.png) +![You can see a summary screen to confirm the creation of the bot and the scopes assigned.](/images/blog/slackbot-consolidate/04_confirm_window.png) You can see a summary screen to confirm the creation of the bot and the scopes assigned. @@ -102,7 +102,7 @@ You can see a summary screen to confirm the creation of the bot and the scopes a Install the app on the workspace: -![The picture shows the button to Install the App to the Slack Workspace.](/images/blog/slackbot-consilidate/05_install_workspace.png) +![The picture shows the button to Install the App to the Slack Workspace.](/images/blog/slackbot-consolidate/05_install_workspace.png) The picture shows the button to Install the App to the Slack Workspace. @@ -112,7 +112,7 @@ The command to invite the bot is below: `/invite @SlackConsolidate` -![The picture shows the command /invite @Slackbot in the channel #team-support.](/images/blog/slackbot-consilidate/06_invite_bot_to_channel.png) +![The picture shows the command /invite @Slackbot in the channel #team-support.](/images/blog/slackbot-consolidate/06_invite_bot_to_channel.png) The picture shows the command /invite @Slackbot in the channel #team-support. @@ -151,7 +151,7 @@ CREATE TABLE slack_watcher ( You may want to call [conversations.list](https://api.slack.com/methods/conversations.list) to dump all the channels and channel IDs into a CSV file, then use it to populate the table `slack_channels`. You can also manually get the data, but copying the links to messages in the channels: -![After right-clicking a message in Slack, you can see the option to select the link.](/images/blog/slackbot-consilidate/07_copy_msg_link.png) +![After right-clicking a message in Slack, you can see the option to select the link.](/images/blog/slackbot-consolidate/07_copy_msg_link.png) After right-clicking a message in Slack, you can see the option to select the link. @@ -175,13 +175,13 @@ The name of the channel is not needed. But it is recommended to set, it so you c Using Supabase UI (easier): -![The green arrow points to insert row button inside Supabase.](/images/blog/slackbot-consilidate/08_insert_row.png) +![The green arrow points to insert row button inside Supabase.](/images/blog/slackbot-consolidate/08_insert_row.png) The green arrow points to insert row button inside Supabase. Then, enter the information as needed: -![The picture shows the UI in Supabase to insert a new row to the database table.](/images/blog/slackbot-consilidate/09_insert_row_b.png) +![The picture shows the UI in Supabase to insert a new row to the database table.](/images/blog/slackbot-consolidate/09_insert_row_b.png) The picture shows the UI in Supabase to insert a new row to the database table. @@ -217,7 +217,7 @@ You need to get the supabase URL and API keys from here: [https://app.supabase.com/project/\_/settings/api](https://app.supabase.com/project/_/settings/api) -![The picture illustrates where to get the URL and the service key to setup the environment variables.](/images/blog/slackbot-consilidate/10_copy_supabase_apis.png) +![The picture illustrates where to get the URL and the service key to setup the environment variables.](/images/blog/slackbot-consolidate/10_copy_supabase_apis.png) The picture illustrates where to get the URL and the service key to setup the environment variables. @@ -225,7 +225,7 @@ Slack environment variables: Then, copy the bot and person API Tokens for the bot: -![The picture has arrows pointing to the tokens that will be used as environment variables from Slack.](/images/blog/slackbot-consilidate/11_copy_slack_apis.png) +![The picture has arrows pointing to the tokens that will be used as environment variables from Slack.](/images/blog/slackbot-consolidate/11_copy_slack_apis.png) The picture has arrows pointing to the tokens that will be used as environment variables from Slack. @@ -405,7 +405,7 @@ if __name__ == '__main__': Of course, we aren't doing proper Python example if we don't make a test notebook available: -[![Open in Colab](/images/blog/2022-august/colab-badge.svg)](https://colab.research.google.com/github/mansueli/SlackConsolidate/blob/main/SlackConsolidate_bot.ipynb) +[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/mansueli/SlackConsolidate/blob/main/SlackConsolidate_bot.ipynb) ## Conclusion diff --git a/apps/www/_blog/2022-08-10-launch-week-5-hackathon.mdx b/apps/www/_blog/2022-08-10-launch-week-5-hackathon.mdx new file mode 100644 index 00000000000..cee9067838a --- /dev/null +++ b/apps/www/_blog/2022-08-10-launch-week-5-hackathon.mdx @@ -0,0 +1,118 @@ +--- +title: 'Launch Week 5 Hackathon' +description: Build to win $1500 - Friday 12th to Monday 21st August 2022 +author: ant_wilson +image: lw5-hackathon/thumbnail.jpg +thumb: lw5-hackathon/thumbnail.jpg +tags: + - launch-week +date: '2022-08-10' +toc_depth: 3 +--- + +# The Supabase Open Source Hackathon + +Now is the perfect time to start your new Open Source project! + +[Launch Week](https://supabase.com/launch-week) is about to start and we're running a hackathon in parallel for the entire duration. + +There's a $1500 GitHub sponsorship and [gold Supabase caps](https://store.supabase.com/products/gold-supacap) to be won! + +[Supabase-js v2.0](https://github.com/supabase/supabase-js/releases) and [Flutter SDK v1.0](https://supabase.com/blog/supabase-flutter-sdk-1-developer-preview) will both be announced during Launch Week, they are both available already and using them in your project will gain extra credit! + + + +## Key Facts + +- You have 10 days to build a new **Open Source** project using Supabase. + - Starting 8:00am PT Friday 12th August 2022. +- Build whatever you want - a project, app, tool, library, anything +- Enter as an individual, or as a team of up to 5 people +- Submission deadline is 11:59pm Sunday night PT 21st August 2022 +- There are 5 prize categories. + - Best overall project will win $1500 in GitHub sponsorships! + - Most technically challenging, most fun, best flutter project, and most visually pleasing will all win a Gold Supabase Cap! + +![Gold cap](/images/blog/lw5-hackathon/spool.jpg) + +## Details + +### Schedule + +- The Hackathon begins at 8:00am PT Friday 12th August 2022 +- Work on your project any time for the next 10 days +- Submission deadline (11:59pm PT Sunday 21st August 2022) + +### Prizes + +There are 5 chances to win, there will be prizes for: + +- Best Overall Project ($1500 in GitHub Sponsorship & Gold Cap) +- Most Visually Pleasing (Gold Cap) +- Most Technically Impressive (Gold Cap) +- Most Fun/Interesting (Gold Cap) +- Best Flutter Project (Gold Cap) +- *new* Best Realtime Project (Gold Cap) + +There will be a winner and a runner-up prize for each category. Every team member gets a cap. + +![Gold cap](/images/blog/lw5-hackathon/cap.png) + +### Submission + +You should submit your project using [this form](https://www.madewithsupabase.com/submission). + +### Judges + +The Supabase Founders will be judging, we will be looking for: + +- creativity/inventiveness +- functions correctly/smoothly +- visually pleasing +- technically impressive +- use of Supabase features + - deep usage of a single feature or + - broad usage are both ok +- FUN! 😃 + +### Rules + +- Team size 1-5 (all team members on winning teams will receive a prize) +- You cannot be in multiple teams +- One submission per team +- All design elements, code, etc. for your project must be created **during** the event +- All entries must be Open Source (link to source code required in entry) +- Must use Supabase in some capacity +- Can be any language or framework +- You must submit before the deadline (no late entries) + +### Community + +The Supabase Team will be taking part in the Hackathon and you'll find us live building in our discord all week. Please join us by building in public: + +- Text channel: hackathon +- Audio channel: hackathon + +If you need help or advice when building, find other people to join your team, or if you just want to chill and watch people build, come and join us! + +[Join our Discord](https://discord.supabase.com) + +![Discord Hangout](/images/blog/hackathon/community.png) + +### Launch Week + +Don't forget to checkout the new feature's being announced as part of [Launch Week](/launch-week). + +### Additional Info + +- Any intellectual property developed during the hackathon will belong to the team that developed it. We expect that each team will have an agreement between themselves regarding the IP, but this is not required +- By making a submission you grant Supabase permission to use screenshots, code-snippets and/or links to your project or content of your README on our Twitter, blog, website, email updates, and in the Supabase discord server. Supabase does not make any claims over your IP. +- $1500 prize will be paid by making a GitHub sponsorship to the winning repo, $500/month for 3 months. The goal here is to create a sustainable project that will be continue to be maintained for the duration of the sponsorship period (and hopefully beyond :) ) diff --git a/apps/www/layouts/comparison.tsx b/apps/www/layouts/comparison.tsx index 65dd6b61d72..8146f6b4d80 100644 --- a/apps/www/layouts/comparison.tsx +++ b/apps/www/layouts/comparison.tsx @@ -64,7 +64,7 @@ const LayoutComparison = ({ components, props, gfm, slug }: Props) => { openGraph={{ title: props.blog.title, description: props.blog.description, - url: `https://supabase.com/blog/${props.blog.slug}`, + url: `https://supabase.com/alternatives/${props.blog.slug}`, type: 'article', article: { // diff --git a/apps/www/next.config.js b/apps/www/next.config.js index b3592d6bf27..669d2505efb 100644 --- a/apps/www/next.config.js +++ b/apps/www/next.config.js @@ -6,6 +6,7 @@ module.exports = withMDX({ trailingSlash: false, images: { + dangerouslyAllowSVG: true, domains: [ 'avatars.githubusercontent.com', 'github.com', @@ -16,6 +17,7 @@ module.exports = withMDX({ 'obuldanrptloktxcffvn.supabase.co', 'avatars.githubusercontent.com', 'colab.research.google.com', + 'api.producthunt.com', ], }, async headers() { diff --git a/apps/www/pages/alternatives/[slug].tsx b/apps/www/pages/alternatives/[slug].tsx index ff08d81f396..6ee4340fa47 100644 --- a/apps/www/pages/alternatives/[slug].tsx +++ b/apps/www/pages/alternatives/[slug].tsx @@ -70,7 +70,7 @@ export async function getStaticProps({ params }: any) { nextPost: currentIndex === allPosts.length ? null : nextPost ? nextPost : null, relatedPosts, blog: { - slug: `${params.year}/${params.month}/${params.day}/${params.slug}`, + slug: `${params.slug}`, content: mdxSource, ...data, toc: toc(content, { maxdepth: data.toc_depth ? data.toc_depth : 2 }), diff --git a/apps/www/pages/blog.tsx b/apps/www/pages/blog.tsx index 77040dfafd2..1276cfae372 100644 --- a/apps/www/pages/blog.tsx +++ b/apps/www/pages/blog.tsx @@ -104,10 +104,7 @@ function Blog(props: any) {
{props.categories.map((categoryId: string) => ( - - {/*

{categoryId}

*/} - <> -
+ ))}
diff --git a/apps/www/pages/blog/[slug].tsx b/apps/www/pages/blog/[slug].tsx index 9c05e24c8d1..e7589fe4c26 100644 --- a/apps/www/pages/blog/[slug].tsx +++ b/apps/www/pages/blog/[slug].tsx @@ -100,7 +100,7 @@ export async function getStaticProps({ params }: any) { nextPost: currentIndex === allPosts.length ? null : nextPost ? nextPost : null, relatedPosts, blog: { - slug: `${params.year}/${params.month}/${params.day}/${params.slug}`, + slug: `${params.slug}`, content: mdxSource, ...data, toc: toc(content, { maxdepth: data.toc_depth ? data.toc_depth : 2 }), @@ -181,6 +181,7 @@ function BlogPostPage(props: any) { description: props.blog.description, url: `https://supabase.com/blog/${props.blog.slug}`, type: 'article', + article: { // // to do: add expiration and modified dates @@ -199,6 +200,7 @@ function BlogPostPage(props: any) { url: `https://supabase.com${basePath}/images/blog/${ props.blog.image ? props.blog.image : props.blog.thumb }`, + alt: `${props.blog.title} thumbnail`, }, ], }} diff --git a/apps/www/public/images/blog/lw5-hackathon/cap.png b/apps/www/public/images/blog/lw5-hackathon/cap.png new file mode 100644 index 00000000000..a5696b59b82 Binary files /dev/null and b/apps/www/public/images/blog/lw5-hackathon/cap.png differ diff --git a/apps/www/public/images/blog/lw5-hackathon/spool.jpg b/apps/www/public/images/blog/lw5-hackathon/spool.jpg new file mode 100644 index 00000000000..612f6504f3d Binary files /dev/null and b/apps/www/public/images/blog/lw5-hackathon/spool.jpg differ diff --git a/apps/www/public/images/blog/lw5-hackathon/thumbnail.jpg b/apps/www/public/images/blog/lw5-hackathon/thumbnail.jpg new file mode 100644 index 00000000000..9379f38bf91 Binary files /dev/null and b/apps/www/public/images/blog/lw5-hackathon/thumbnail.jpg differ diff --git a/apps/www/public/images/blog/slackbot-consilidate/00_create_new_app.png b/apps/www/public/images/blog/slackbot-consolidate/00_create_new_app.png similarity index 100% rename from apps/www/public/images/blog/slackbot-consilidate/00_create_new_app.png rename to apps/www/public/images/blog/slackbot-consolidate/00_create_new_app.png diff --git a/apps/www/public/images/blog/slackbot-consilidate/01_create_an_slack_app.png b/apps/www/public/images/blog/slackbot-consolidate/01_create_an_slack_app.png similarity index 100% rename from apps/www/public/images/blog/slackbot-consilidate/01_create_an_slack_app.png rename to apps/www/public/images/blog/slackbot-consolidate/01_create_an_slack_app.png diff --git a/apps/www/public/images/blog/slackbot-consilidate/02_pick_workspace.png b/apps/www/public/images/blog/slackbot-consolidate/02_pick_workspace.png similarity index 100% rename from apps/www/public/images/blog/slackbot-consilidate/02_pick_workspace.png rename to apps/www/public/images/blog/slackbot-consolidate/02_pick_workspace.png diff --git a/apps/www/public/images/blog/slackbot-consilidate/03_enter_manifest.png b/apps/www/public/images/blog/slackbot-consolidate/03_enter_manifest.png similarity index 100% rename from apps/www/public/images/blog/slackbot-consilidate/03_enter_manifest.png rename to apps/www/public/images/blog/slackbot-consolidate/03_enter_manifest.png diff --git a/apps/www/public/images/blog/slackbot-consilidate/04_confirm_window.png b/apps/www/public/images/blog/slackbot-consolidate/04_confirm_window.png similarity index 100% rename from apps/www/public/images/blog/slackbot-consilidate/04_confirm_window.png rename to apps/www/public/images/blog/slackbot-consolidate/04_confirm_window.png diff --git a/apps/www/public/images/blog/slackbot-consilidate/05_install_workspace.png b/apps/www/public/images/blog/slackbot-consolidate/05_install_workspace.png similarity index 100% rename from apps/www/public/images/blog/slackbot-consilidate/05_install_workspace.png rename to apps/www/public/images/blog/slackbot-consolidate/05_install_workspace.png diff --git a/apps/www/public/images/blog/slackbot-consilidate/06_invite_bot_to_channel.png b/apps/www/public/images/blog/slackbot-consolidate/06_invite_bot_to_channel.png similarity index 100% rename from apps/www/public/images/blog/slackbot-consilidate/06_invite_bot_to_channel.png rename to apps/www/public/images/blog/slackbot-consolidate/06_invite_bot_to_channel.png diff --git a/apps/www/public/images/blog/slackbot-consilidate/07_copy_msg_link.png b/apps/www/public/images/blog/slackbot-consolidate/07_copy_msg_link.png similarity index 100% rename from apps/www/public/images/blog/slackbot-consilidate/07_copy_msg_link.png rename to apps/www/public/images/blog/slackbot-consolidate/07_copy_msg_link.png diff --git a/apps/www/public/images/blog/slackbot-consilidate/08_insert_row.png b/apps/www/public/images/blog/slackbot-consolidate/08_insert_row.png similarity index 100% rename from apps/www/public/images/blog/slackbot-consilidate/08_insert_row.png rename to apps/www/public/images/blog/slackbot-consolidate/08_insert_row.png diff --git a/apps/www/public/images/blog/slackbot-consilidate/09_insert_row_b.png b/apps/www/public/images/blog/slackbot-consolidate/09_insert_row_b.png similarity index 100% rename from apps/www/public/images/blog/slackbot-consilidate/09_insert_row_b.png rename to apps/www/public/images/blog/slackbot-consolidate/09_insert_row_b.png diff --git a/apps/www/public/images/blog/slackbot-consilidate/10_copy_supabase_apis.png b/apps/www/public/images/blog/slackbot-consolidate/10_copy_supabase_apis.png similarity index 100% rename from apps/www/public/images/blog/slackbot-consilidate/10_copy_supabase_apis.png rename to apps/www/public/images/blog/slackbot-consolidate/10_copy_supabase_apis.png diff --git a/apps/www/public/images/blog/slackbot-consilidate/11_copy_slack_apis.png b/apps/www/public/images/blog/slackbot-consolidate/11_copy_slack_apis.png similarity index 100% rename from apps/www/public/images/blog/slackbot-consilidate/11_copy_slack_apis.png rename to apps/www/public/images/blog/slackbot-consolidate/11_copy_slack_apis.png diff --git a/apps/www/public/images/blog/slackbot-consilidate/slackbot-thumb.jpg b/apps/www/public/images/blog/slackbot-consolidate/slackbot-thumb.jpg similarity index 100% rename from apps/www/public/images/blog/slackbot-consilidate/slackbot-thumb.jpg rename to apps/www/public/images/blog/slackbot-consolidate/slackbot-thumb.jpg diff --git a/apps/www/public/rss.xml b/apps/www/public/rss.xml index f5333d175a5..1fab3bff1e2 100644 --- a/apps/www/public/rss.xml +++ b/apps/www/public/rss.xml @@ -5,13 +5,19 @@ https://supabase.com Latest news from Supabase en - Mon, 08 Aug 2022 03:03:00 + Tue, 09 Aug 2022 06:06:00 - + + https://supabase.com/blog/launch-week-5-hackathon + Launch Week 5 Hackathon + https://supabase.com/blog/launch-week-5-hackathon + Build to win $1500 - Friday 12th to Monday 21st August 2022 + Tue, 09 Aug 2022 06:06:00 + https://supabase.com/blog/slack-consolidate-slackbot-to-consolidate-messages Slack Consolidate: a slackbot built with Python and Supabase https://supabase.com/blog/slack-consolidate-slackbot-to-consolidate-messages - Different approaches for tracking visitor counts with PostgreSQL. + A slackbot to consolidate messages from different channels using Supabase, Slack SDK and Python Mon, 08 Aug 2022 03:03:00 @@ -19,742 +25,742 @@ Supabase Beta July 2022 https://supabase.com/blog/supabase-beta-update-july-2022 Launch Week Golden Tickets, Flutter SDK 1.0 Developer Preview and more... - Tue, 02 Aug 2022 03:03:00 + Tue, 02 Aug 2022 06:06:00 https://supabase.com/blog/supabase-flutter-sdk-1-developer-preview Supabase Flutter SDK 1.0 Developer Preview https://supabase.com/blog/supabase-flutter-sdk-1-developer-preview Supabase Flutter SDK is getting a major update and we need your help making it better. - Mon, 01 Aug 2022 03:03:00 + Mon, 01 Aug 2022 06:06:00 https://supabase.com/blog/seen-by-in-postgresql Implementing "seen by" functionality with Postgres https://supabase.com/blog/seen-by-in-postgresql Different approaches for tracking visitor counts with PostgreSQL. - Sun, 17 Jul 2022 03:03:00 + Sun, 17 Jul 2022 06:06:00 https://supabase.com/blog/supabase-auth-helpers-with-sveltekit-support Revamped Auth Helpers for Supabase (with SvelteKit support) https://supabase.com/blog/supabase-auth-helpers-with-sveltekit-support Supabase Auth Helpers now have improved developer experience, Sveltekit support, and more. - Tue, 12 Jul 2022 03:03:00 + Tue, 12 Jul 2022 06:06:00 https://supabase.com/blog/beta-update-june-2022 Supabase Beta June 2022 https://supabase.com/blog/beta-update-june-2022 Auth Helpers, Unlimited Free Projects, CLI and more... - Tue, 05 Jul 2022 03:03:00 + Tue, 05 Jul 2022 06:06:00 https://supabase.com/blog/flutter-tutorial-building-a-chat-app Flutter Tutorial: building a Flutter chat app https://supabase.com/blog/flutter-tutorial-building-a-chat-app How to create a real time chat app using Flutter. - Wed, 29 Jun 2022 03:03:00 + Wed, 29 Jun 2022 06:06:00 https://supabase.com/blog/visualizing-supabase-data-using-metabase Visualizing Supabase Data using Metabase https://supabase.com/blog/visualizing-supabase-data-using-metabase How to create different kinds of charts out of data stored in Supabase using Metabase. - Tue, 28 Jun 2022 03:03:00 + Tue, 28 Jun 2022 06:06:00 https://supabase.com/blog/partial-postgresql-data-dumps-with-rls Partial data dumps using Postgres Row Level Security https://supabase.com/blog/partial-postgresql-data-dumps-with-rls Using RLS to create seed files for local PostgreSQL testing. - Mon, 27 Jun 2022 03:03:00 + Mon, 27 Jun 2022 06:06:00 https://supabase.com/blog/loading-data-supabase-python Python data loading with Supabase https://supabase.com/blog/loading-data-supabase-python An example of how to load data into Supabase using supabase-py - Thu, 16 Jun 2022 03:03:00 + Thu, 16 Jun 2022 06:06:00 https://supabase.com/blog/beta-update-may-2022 Supabase Beta May 2022 https://supabase.com/blog/beta-update-may-2022 Product and community updates including wildcard auth redirects, edge functions with webhooks, and Prometheus endpoints for everybody. - Tue, 31 May 2022 03:03:00 + Tue, 31 May 2022 06:06:00 https://supabase.com/blog/how-supabase-accelerates-development-of-all-pull-together How Mike Lyndon is using Supabase to accelerate development of AllPullTogether https://supabase.com/blog/how-supabase-accelerates-development-of-all-pull-together Mike Lyndon is learning web development as he builds AllPullTogether, and Supabase is helping him accelerate what he can accomplish. - Wed, 25 May 2022 03:03:00 + Wed, 25 May 2022 06:06:00 https://supabase.com/blog/partner-gallery-works-with-supabase Works With Supabase - announcing our Partner Gallery https://supabase.com/blog/partner-gallery-works-with-supabase Introducing our Partner Gallery - open source and made with Supabase. - Tue, 19 Apr 2022 03:03:00 + Tue, 19 Apr 2022 06:06:00 https://supabase.com/blog/bring-the-func-hackathon-winners Bring the Func Hackathon Winners 2022 https://supabase.com/blog/bring-the-func-hackathon-winners Celebrating many amazing OSS Hackathon projects using GraphQL and Edge Functions. - Sun, 17 Apr 2022 03:03:00 + Sun, 17 Apr 2022 06:06:00 https://supabase.com/blog/beta-update-march-2022 Supabase Beta March 2022 https://supabase.com/blog/beta-update-march-2022 Functions, GraphQL, and much more. - Thu, 14 Apr 2022 03:03:00 + Thu, 14 Apr 2022 06:06:00 https://supabase.com/blog/supabrew Supabrew - Never Code Thirsty https://supabase.com/blog/supabrew A light and refreshing non-alcoholic beer for devs. - Fri, 01 Apr 2022 03:03:00 + Fri, 01 Apr 2022 06:06:00 https://supabase.com/blog/supabase-realtime-with-multiplayer-features Supabase Realtime, with Multiplayer Features https://supabase.com/blog/supabase-realtime-with-multiplayer-features Today we're announced Realtime, with multiplayer features. Realtime enables broadcast, presence, and listening to database changes delivered over WebSockets. - Fri, 01 Apr 2022 03:03:00 + Fri, 01 Apr 2022 06:06:00 https://supabase.com/blog/hackathon-bring-the-func Hackathon: Bring the Func(🕺) https://supabase.com/blog/hackathon-bring-the-func Build open-source projects with our latest features, win limited edition swag and plant a tree! - Fri, 01 Apr 2022 03:03:00 + Fri, 01 Apr 2022 06:06:00 https://supabase.com/blog/supabase-edge-functions Edge Functions are now available in Supabase https://supabase.com/blog/supabase-edge-functions Today we're launching Edge Functions. Edge Functions let you execute Typescript code close to your users, no matter where they're located. - Wed, 30 Mar 2022 03:03:00 + Wed, 30 Mar 2022 06:06:00 https://supabase.com/blog/supabase-enterprise Introducing Supabase Enterprise https://supabase.com/blog/supabase-enterprise Today we are releasing Supabase Enterprise, a suite of features to scale your project. - Tue, 29 Mar 2022 03:03:00 + Tue, 29 Mar 2022 06:06:00 https://supabase.com/blog/graphql-now-available GraphQL is now available in Supabase https://supabase.com/blog/graphql-now-available GraphQL support is now in general availability on the Supabase platform via our open source PostgreSQL extension, pg_graphql (beta). - Mon, 28 Mar 2022 03:03:00 + Mon, 28 Mar 2022 06:06:00 https://supabase.com/blog/community-day Community Day https://supabase.com/blog/community-day Kicking off Launch Week 4 with contributors, partners, and friends. - Sun, 27 Mar 2022 03:03:00 + Sun, 27 Mar 2022 06:06:00 https://supabase.com/blog/supabase-launch-week-four Supabase Launch Week 4 https://supabase.com/blog/supabase-launch-week-four Launch Week 4: One new feature every day for an entire week. Starting Monday 28th March. - Thu, 24 Mar 2022 03:03:00 + Thu, 24 Mar 2022 06:06:00 https://supabase.com/blog/should-i-open-source-my-company Should I Open Source my Company? https://supabase.com/blog/should-i-open-source-my-company The unexpected upsides of building in public - Thu, 24 Mar 2022 03:03:00 + Thu, 24 Mar 2022 06:06:00 https://supabase.com/blog/audit Postgres Auditing in 150 lines of SQL https://supabase.com/blog/audit PostgreSQL has a robust set of features which we can leverage to create a generic auditing solution in 150 lines of SQL. - Mon, 07 Mar 2022 03:03:00 + Mon, 07 Mar 2022 07:07:00 https://supabase.com/blog/supabase-beta-january-2022 Supabase Beta January 2022 https://supabase.com/blog/supabase-beta-january-2022 New auth providers, SMS providers, and new videos. - Mon, 21 Feb 2022 03:03:00 + Mon, 21 Feb 2022 07:07:00 https://supabase.com/blog/supabase-beta-december-2021 Supabase Beta December 2021 https://supabase.com/blog/supabase-beta-december-2021 New crypto extension, Postgres videos, and a bunch of cool integrations. - Wed, 19 Jan 2022 03:03:00 + Wed, 19 Jan 2022 07:07:00 https://supabase.com/blog/product-hunt-golden-kitty-awards-2021 Golden Kitty Awards Ceremony Watch Party with Supabase https://supabase.com/blog/product-hunt-golden-kitty-awards-2021 Hang out with us while watching the Product Hunt Golden Kitty Awards Ceremony - Wed, 19 Jan 2022 03:03:00 + Wed, 19 Jan 2022 07:07:00 https://supabase.com/blog/holiday-hackdays-winners-2021 Holiday Hackdays Winners 2021 https://supabase.com/blog/holiday-hackdays-winners-2021 Celebrating many amazing projects submitted to our Holiday Hackdays Hackathon. - Thu, 16 Dec 2021 03:03:00 + Thu, 16 Dec 2021 07:07:00 https://supabase.com/blog/beta-november-2021-launch-week-recap Supabase Beta November 2021: Launch Week Recap https://supabase.com/blog/beta-november-2021-launch-week-recap We wrapped up November with Supabase's third Launch Week. Here's all the awesome stuff that got shipped ... - Tue, 14 Dec 2021 03:03:00 + Tue, 14 Dec 2021 07:07:00 https://supabase.com/blog/supabase-holiday-hackdays-hackathon Kicking off the Holiday Hackdays https://supabase.com/blog/supabase-holiday-hackdays-hackathon Build cool stuff and celebrate open-source software with us during the Holiday Hackdays! - Thu, 02 Dec 2021 03:03:00 + Thu, 02 Dec 2021 07:07:00 https://supabase.com/blog/pg-graphql pg_graphql: A GraphQL extension for PostgreSQL https://supabase.com/blog/pg-graphql GraphQL support is in development for PostgreSQL + Supabase. - Thu, 02 Dec 2021 03:03:00 + Thu, 02 Dec 2021 07:07:00 https://supabase.com/blog/launch-week-three-friday-five-more-things Five more things https://supabase.com/blog/launch-week-three-friday-five-more-things It's never just one more thing! - Thu, 02 Dec 2021 03:03:00 + Thu, 02 Dec 2021 07:07:00 https://supabase.com/blog/supabase-acquires-logflare Supabase acquires Logflare https://supabase.com/blog/supabase-acquires-logflare Today, we're ecstatic to announce that Logflare is joining Supabase. - Wed, 01 Dec 2021 03:03:00 + Wed, 01 Dec 2021 07:07:00 https://supabase.com/blog/realtime-row-level-security-in-postgresql Realtime Postgres RLS now available on Supabase https://supabase.com/blog/realtime-row-level-security-in-postgresql Realtime database changes are now broadcast to authenticated users, respecting the same PostgreSQL policies that you use for Row Level Security. - Tue, 30 Nov 2021 03:03:00 + Tue, 30 Nov 2021 07:07:00 https://supabase.com/blog/supabase-studio Supabase Studio https://supabase.com/blog/supabase-studio The same Dashboard that you're using on our Platform is now available for local development and Self-Hosting. - Mon, 29 Nov 2021 03:03:00 + Mon, 29 Nov 2021 07:07:00 https://supabase.com/blog/community-day Community Day https://supabase.com/blog/community-day Kicking off launch week by highlighting the communities around Supabase. - Sun, 28 Nov 2021 03:03:00 + Sun, 28 Nov 2021 07:07:00 https://supabase.com/blog/whats-new-in-postgres-14 New in PostgreSQL 14: What every developer should know https://supabase.com/blog/whats-new-in-postgres-14 A quick look at some new features and functionality in PostgreSQL 14. - Sat, 27 Nov 2021 03:03:00 + Sat, 27 Nov 2021 07:07:00 https://supabase.com/blog/postgrest-9 PostgREST 9 https://supabase.com/blog/postgrest-9 New features and updates in PostgREST version 9. - Fri, 26 Nov 2021 03:03:00 + Fri, 26 Nov 2021 07:07:00 https://supabase.com/blog/supabase-launch-week-the-trilogy Supabase Launch Week III: Holiday Special https://supabase.com/blog/supabase-launch-week-the-trilogy Tis the season to be shipping. - Thu, 25 Nov 2021 03:03:00 + Thu, 25 Nov 2021 07:07:00 https://supabase.com/blog/supabase-how-we-launch How we launch at Supabase https://supabase.com/blog/supabase-how-we-launch The history and methodology of Supabase Launch Week. - Thu, 25 Nov 2021 03:03:00 + Thu, 25 Nov 2021 07:07:00 https://supabase.com/blog/supabase-beta-october-2021 Supabase Beta October 2021 https://supabase.com/blog/supabase-beta-october-2021 Three new Auth providers, multi-schema support, and we're gearing up for another Launch Week. - Sat, 06 Nov 2021 03:03:00 + Sat, 06 Nov 2021 06:06:00 https://supabase.com/blog/supabase-series-a Supabase $30m Series A https://supabase.com/blog/supabase-series-a Supabase just raised $30M, bringing our total funding to $36M. - Wed, 27 Oct 2021 03:03:00 + Wed, 27 Oct 2021 06:06:00 https://supabase.com/blog/replenysh-time-to-value-in-less-than-24-hours Replenysh uses Supabase to implement OTP in less than 24-hours https://supabase.com/blog/replenysh-time-to-value-in-less-than-24-hours Learn how Replenysh uses Supabase to power the circular economy, redefining how brands interact with their customers and products. - Mon, 18 Oct 2021 03:03:00 + Mon, 18 Oct 2021 06:06:00 https://supabase.com/blog/hacktoberfest-hackathon-winners-2021 Hacktoberfest Hackathon Winners 2021 https://supabase.com/blog/hacktoberfest-hackathon-winners-2021 Celebrating many amazing projects submitted to our Hacktoberfest Hackathon. - Wed, 13 Oct 2021 03:03:00 + Wed, 13 Oct 2021 06:06:00 https://supabase.com/blog/supabase-beta-sept-2021 Supabase Beta Sept 2021 https://supabase.com/blog/supabase-beta-sept-2021 Hackathon, Aborting request, UI updates, and now Hiring. - Sun, 03 Oct 2021 03:03:00 + Sun, 03 Oct 2021 06:06:00 https://supabase.com/blog/supabase-hacktoberfest-hackathon-2021 Supabase Hacktoberfest Hackathon 2021 https://supabase.com/blog/supabase-hacktoberfest-hackathon-2021 We're running another Supabase Hackathon during Hacktoberfest! - Mon, 27 Sep 2021 03:03:00 + Mon, 27 Sep 2021 06:06:00 https://supabase.com/blog/supabase-beta-august-2021 Supabase Beta August 2021 https://supabase.com/blog/supabase-beta-august-2021 Fundraising, Realtime Security, custom SMS templates, and deployments in South Korea. - Thu, 09 Sep 2021 03:03:00 + Thu, 09 Sep 2021 06:06:00 https://supabase.com/blog/supabase-beta-july-2021 Supabase Beta July 2021 https://supabase.com/blog/supabase-beta-july-2021 Discord Logins, Vercel Integration, Full text search, and OAuth guides. - Wed, 11 Aug 2021 03:03:00 + Wed, 11 Aug 2021 06:06:00 https://supabase.com/blog/hackathon-winners Open Source Hackathon Winners https://supabase.com/blog/hackathon-winners Let the medal ceremony begin for the best projects submitted during the Supabase Hackathon. - Sun, 08 Aug 2021 03:03:00 + Sun, 08 Aug 2021 06:06:00 https://supabase.com/blog/supabase-swag-store Supabase Swag Store https://supabase.com/blog/supabase-swag-store Today we are officially launching the Supabase Swag Store. - Thu, 29 Jul 2021 03:03:00 + Thu, 29 Jul 2021 06:06:00 https://supabase.com/blog/supabase-functions-updates Updates for Supabase Functions https://supabase.com/blog/supabase-functions-updates The question on everyone's mind - are we launching Supabase Functions? Well, it's complicated. - Thu, 29 Jul 2021 03:03:00 + Thu, 29 Jul 2021 06:06:00 https://supabase.com/blog/1-the-supabase-hackathon The Supabase Hackathon https://supabase.com/blog/1-the-supabase-hackathon A whole week of Hacking for Fun and Prizes. - Thu, 29 Jul 2021 03:03:00 + Thu, 29 Jul 2021 06:06:00 https://supabase.com/blog/supabase-reports-and-metrics Supabase Reports and Metrics https://supabase.com/blog/supabase-reports-and-metrics We're exposing a full set of metrics in your projects, so that you can build better (and faster) products for your users. - Wed, 28 Jul 2021 03:03:00 + Wed, 28 Jul 2021 06:06:00 https://supabase.com/blog/supabase-auth-passwordless-sms-login Supabase Auth v2: Phone Auth now available https://supabase.com/blog/supabase-auth-passwordless-sms-login Phone Auth is available today on all new and existing Supabase projects. - Tue, 27 Jul 2021 03:03:00 + Tue, 27 Jul 2021 06:06:00 https://supabase.com/blog/mobbin-supabase-200000-users Mobbin uses Supabase to authenticate 200,000 users https://supabase.com/blog/mobbin-supabase-200000-users Learn how Mobbin migrated 200,000 users from Firebase for a better authentication experience. - Tue, 27 Jul 2021 03:03:00 + Tue, 27 Jul 2021 06:06:00 https://supabase.com/blog/storage-beta Supabase Storage now in Beta https://supabase.com/blog/storage-beta Supabase Storage moves into Beta. - Mon, 26 Jul 2021 03:03:00 + Mon, 26 Jul 2021 06:06:00 https://supabase.com/blog/spot-flutter-with-postgres Spot: a video sharing app built with Flutter https://supabase.com/blog/spot-flutter-with-postgres Spot is a geolocation-based video-sharing app with some social networking features. - Mon, 26 Jul 2021 03:03:00 + Mon, 26 Jul 2021 06:06:00 https://supabase.com/blog/supabase-postgres-13 Supabase is now on Postgres 13.3 https://supabase.com/blog/supabase-postgres-13 From today, new Supabase projects will be on a version of Supabase Postgres that runs on Postgres 13.3. - Sun, 25 Jul 2021 03:03:00 + Sun, 25 Jul 2021 06:06:00 https://supabase.com/blog/supabase-community-day Supabase Community Day https://supabase.com/blog/supabase-community-day Community Day - Sun, 25 Jul 2021 03:03:00 + Sun, 25 Jul 2021 06:06:00 https://supabase.com/blog/epsilon3-self-hosting Epsilon3 Self-Host Supabase To Revolutionize Space Operations https://supabase.com/blog/epsilon3-self-hosting Learn how the team at Epsilon3 use Supabase to help teams execute secure and reliable operations in an industry that project spend runs into the billions. - Sun, 25 Jul 2021 03:03:00 + Sun, 25 Jul 2021 06:06:00 https://supabase.com/blog/supabase-launch-week-sql Supabase Launch Week II: The SQL https://supabase.com/blog/supabase-launch-week-sql Five days of Supabase. Again. - Wed, 21 Jul 2021 03:03:00 + Wed, 21 Jul 2021 06:06:00 https://supabase.com/blog/roles-postgres-hooks Protecting reserved roles with PostgreSQL Hooks https://supabase.com/blog/roles-postgres-hooks Using Postgres Hooks to protect functionality in your Postgres database. - Thu, 01 Jul 2021 03:03:00 + Thu, 01 Jul 2021 06:06:00 https://supabase.com/blog/supabase-beta-june-2021 Supabase Beta June 2021 https://supabase.com/blog/supabase-beta-june-2021 Discord Logins, Vercel Integration, Full text search, and OAuth guides. - Tue, 01 Jun 2021 03:03:00 + Tue, 01 Jun 2021 06:06:00 https://supabase.com/blog/supabase-beta-may-2021 Supabase Beta May 2021 https://supabase.com/blog/supabase-beta-may-2021 Apple & Twitter Logins, Supabase Grid, Go & Swift Libraries. - Tue, 01 Jun 2021 03:03:00 + Tue, 01 Jun 2021 06:06:00 https://supabase.com/blog/supabase-beta-april-2021 Supabase Beta April 2021 https://supabase.com/blog/supabase-beta-april-2021 Supabase "gardening" - stability, security, and community support. - Tue, 04 May 2021 03:03:00 + Tue, 04 May 2021 06:06:00 https://supabase.com/blog/supabase-beta-march-2021 Supabase Beta March 2021 https://supabase.com/blog/supabase-beta-march-2021 Launch week, Storage, Supabase CLI, Connection Pooling, Supabase UI, and Pricing. - Mon, 05 Apr 2021 03:03:00 + Mon, 05 Apr 2021 06:06:00 https://supabase.com/blog/supabase-workflows Workflows are coming to Supabase https://supabase.com/blog/supabase-workflows Functions are great, but you know what's better? - Thu, 01 Apr 2021 03:03:00 + Thu, 01 Apr 2021 06:06:00 https://supabase.com/blog/supabase-pgbouncer PgBouncer is now available in Supabase https://supabase.com/blog/supabase-pgbouncer Better support for Serverless and Postgres. - Thu, 01 Apr 2021 03:03:00 + Thu, 01 Apr 2021 06:06:00 https://supabase.com/blog/supabase-dot-com Supabase Dot Com https://supabase.com/blog/supabase-dot-com The Supabase Domain name is changing. - Thu, 01 Apr 2021 03:03:00 + Thu, 01 Apr 2021 06:06:00 https://supabase.com/blog/supabase-nft-marketplace Supabase Launches NFT Marketplace https://supabase.com/blog/supabase-nft-marketplace A fully encrypted NFT platform to protect and transact your digital assets - Thu, 01 Apr 2021 03:03:00 + Thu, 01 Apr 2021 06:06:00 https://supabase.com/blog/supabase-cli Supabase CLI https://supabase.com/blog/supabase-cli Local development, database migrations, and self-hosting. - Wed, 31 Mar 2021 03:03:00 + Wed, 31 Mar 2021 06:06:00 https://supabase.com/blog/supabase-storage Storage is now available in Supabase https://supabase.com/blog/supabase-storage Launching Supabase Storage and how you can use it in your apps - Tue, 30 Mar 2021 03:03:00 + Tue, 30 Mar 2021 06:06:00 https://supabase.com/blog/pricing Supabase Beta Pricing https://supabase.com/blog/pricing Supabase launches Beta pricing structure - Mon, 29 Mar 2021 03:03:00 + Mon, 29 Mar 2021 06:06:00 https://supabase.com/blog/launch-week Launch week https://supabase.com/blog/launch-week Five days of Supabase. - Wed, 24 Mar 2021 03:03:00 + Wed, 24 Mar 2021 06:06:00 https://supabase.com/blog/angels-of-supabase Angels of Supabase https://supabase.com/blog/angels-of-supabase Meet the investors of Supabase. - Wed, 24 Mar 2021 03:03:00 + Wed, 24 Mar 2021 06:06:00 https://supabase.com/blog/In-The-Loop Developers stay up to date with intheloop.dev https://supabase.com/blog/In-The-Loop Learn why Kevin is building intheloop.dev with Supabase - Mon, 22 Mar 2021 03:03:00 + Mon, 22 Mar 2021 06:06:00 https://supabase.com/blog/using-supabase-replit Using Supabase in Replit https://supabase.com/blog/using-supabase-replit Free hosted relational database from within your node.js repl - Thu, 11 Mar 2021 03:03:00 + Thu, 11 Mar 2021 07:07:00 https://supabase.com/blog/toad-a-link-shortener-with-simple-apis-for-low-coders Toad, a link shortener with simple APIs for low-coders https://supabase.com/blog/toad-a-link-shortener-with-simple-apis-for-low-coders An easy-to-use link shortening tool with simple APIs - Mon, 08 Mar 2021 03:03:00 + Mon, 08 Mar 2021 07:07:00 https://supabase.com/blog/postgres-as-a-cron-server Postgres as a CRON Server https://supabase.com/blog/postgres-as-a-cron-server Running repetitive tasks with your Postgres database. - Fri, 05 Mar 2021 03:03:00 + Fri, 05 Mar 2021 07:07:00 https://supabase.com/blog/supabase-beta-february-2021 Supabase Beta February 2021 https://supabase.com/blog/supabase-beta-february-2021 One year of building. - Tue, 02 Mar 2021 03:03:00 + Tue, 02 Mar 2021 07:07:00 https://supabase.com/blog/cracking-postgres-interview Cracking PostgreSQL Interview Questions https://supabase.com/blog/cracking-postgres-interview Understand the top PostgreSQL Interview Questions - Sat, 27 Feb 2021 03:03:00 + Sat, 27 Feb 2021 07:07:00 https://supabase.com/blog/case-study-roboflow Roboflow.com choose Supabase to power Paint.wtf leaderboard https://supabase.com/blog/case-study-roboflow Learn how Roboflow.com used Supabase to build their Paint.wtf leaderboard - Tue, 09 Feb 2021 03:03:00 + Tue, 09 Feb 2021 07:07:00 https://supabase.com/blog/supabase-beta-january-2021 Supabase Beta January 2021 https://supabase.com/blog/supabase-beta-january-2021 Eleven months of building. - Tue, 02 Feb 2021 03:03:00 + Tue, 02 Feb 2021 07:07:00 https://supabase.com/blog/supabase-beta-december-2020 Supabase Beta December 2020 https://supabase.com/blog/supabase-beta-december-2020 Ten months of building. - Sat, 02 Jan 2021 03:03:00 + Sat, 02 Jan 2021 07:07:00 https://supabase.com/blog/supabase-dashboard-performance Making the Supabase Dashboard Supa-fast https://supabase.com/blog/supabase-dashboard-performance Improving the performance of the Supabase dashboard - Sun, 13 Dec 2020 03:03:00 + Sun, 13 Dec 2020 07:07:00 https://supabase.com/blog/supabase-striveschool Supabase Partners With Strive School To Help Teach Open Source https://supabase.com/blog/supabase-striveschool Supabase Partners With Strive School To Help Teach Open Source To The Next Generation Of Developers - Wed, 02 Dec 2020 03:03:00 + Wed, 02 Dec 2020 07:07:00 https://supabase.com/blog/case-study-xendit Xendit Built a Counter-Fraud Watchlist for the Fintech Industry https://supabase.com/blog/case-study-xendit See how Xendit use Supabase to build a full-text search engine. - Wed, 02 Dec 2020 03:03:00 + Wed, 02 Dec 2020 07:07:00 https://supabase.com/blog/case-study-tayfa TAYFA Built a No-Code Website Builder in Seven Days https://supabase.com/blog/case-study-tayfa See how Tayfa went from idea to paying customer in less than 30 days. - Wed, 02 Dec 2020 03:03:00 + Wed, 02 Dec 2020 07:07:00 https://supabase.com/blog/case-study-monitoro Monitoro Built a Web Crawler Handling Millions of API Requests https://supabase.com/blog/case-study-monitoro See how Monitoro built an automated scraping platform using Supabase. - Wed, 02 Dec 2020 03:03:00 + Wed, 02 Dec 2020 07:07:00 https://supabase.com/blog/supabase-alpha-november-2020 Supabase Alpha November 2020 https://supabase.com/blog/supabase-alpha-november-2020 Nine months of building. - Tue, 01 Dec 2020 03:03:00 + Tue, 01 Dec 2020 07:07:00 https://supabase.com/blog/postgresql-views Postgres Views https://supabase.com/blog/postgresql-views Creating and using a view in PostgreSQL. - Wed, 18 Nov 2020 03:03:00 + Wed, 18 Nov 2020 07:07:00 https://supabase.com/blog/supabase-alpha-october-2020 Supabase Alpha October 2020 https://supabase.com/blog/supabase-alpha-october-2020 Eight months of building. - Mon, 02 Nov 2020 03:03:00 + Mon, 02 Nov 2020 07:07:00 https://supabase.com/blog/improved-dx Supabase.js 1.0 https://supabase.com/blog/improved-dx We're releasing a new version of our Supabase client with some awesome new improvements. - Fri, 30 Oct 2020 03:03:00 + Fri, 30 Oct 2020 06:06:00 https://supabase.com/blog/supabase-alpha-september-2020 Supabase Alpha September 2020 https://supabase.com/blog/supabase-alpha-september-2020 Seven months of building. - Sat, 03 Oct 2020 03:03:00 + Sat, 03 Oct 2020 06:06:00 https://supabase.com/blog/supabase-hacktoberfest-2020 Supabase Hacktoberfest 2020 https://supabase.com/blog/supabase-hacktoberfest-2020 Join us for a celebration of open source software and learn how to contribute to Supabase. - Fri, 11 Sep 2020 03:03:00 + Fri, 11 Sep 2020 06:06:00 https://supabase.com/blog/supabase-alpha-august-2020 Supabase Alpha August 2020 https://supabase.com/blog/supabase-alpha-august-2020 Six months of building - Thu, 03 Sep 2020 03:03:00 + Thu, 03 Sep 2020 06:06:00 https://supabase.com/blog/supabase-auth Supabase Auth https://supabase.com/blog/supabase-auth Authenticate and authorize your users with Supabase Auth - Wed, 05 Aug 2020 03:03:00 + Wed, 05 Aug 2020 06:06:00 https://supabase.com/blog/supabase-alpha-july-2020 Supabase Alpha July 2020 https://supabase.com/blog/supabase-alpha-july-2020 Five months of building - Sun, 02 Aug 2020 03:03:00 + Sun, 02 Aug 2020 06:06:00 https://supabase.com/blog/continuous-postgresql-backup-walg Continuous PostgreSQL Backups using WAL-G https://supabase.com/blog/continuous-postgresql-backup-walg Have you ever wanted to restore your database's state to a particular moment in time? This post explains how, using WAL-G. - Sun, 02 Aug 2020 03:03:00 + Sun, 02 Aug 2020 06:06:00 https://supabase.com/blog/alpha-launch-postmortem Alpha Launch Postmortem https://supabase.com/blog/alpha-launch-postmortem Everything that went wrong with Supabase's launch - Fri, 10 Jul 2020 03:03:00 + Fri, 10 Jul 2020 06:06:00 https://supabase.com/blog/postgresql-templates What are PostgreSQL Templates? https://supabase.com/blog/postgresql-templates What are PostgreSQL templates and what are they used for? - Thu, 09 Jul 2020 03:03:00 + Thu, 09 Jul 2020 06:06:00 https://supabase.com/blog/postgresql-physical-logical-backups Physical vs Logical Backups in PostgreSQL https://supabase.com/blog/postgresql-physical-logical-backups What are physical and logical backups in Postgres? - Tue, 07 Jul 2020 03:03:00 + Tue, 07 Jul 2020 06:06:00 https://supabase.com/blog/supabase-alpha-june-2020 Supabase Alpha June 2020 https://supabase.com/blog/supabase-alpha-june-2020 Four months of building - Wed, 01 Jul 2020 03:03:00 + Wed, 01 Jul 2020 06:06:00 https://supabase.com/blog/supabase-steve-chavez Steve Chavez has joined Supabase https://supabase.com/blog/supabase-steve-chavez Steve joins Supabase to help build Auth. - Mon, 15 Jun 2020 03:03:00 + Mon, 15 Jun 2020 06:06:00 https://supabase.com/blog/supabase-alpha-may-2020 Supabase Alpha May 2020 https://supabase.com/blog/supabase-alpha-may-2020 Three months of building - Mon, 01 Jun 2020 03:03:00 + Mon, 01 Jun 2020 06:06:00 https://supabase.com/blog/supabase-alpha-april-2020 Supabase Alpha April 2020 https://supabase.com/blog/supabase-alpha-april-2020 Two months of building - Mon, 01 Jun 2020 03:03:00 + Mon, 01 Jun 2020 06:06:00 diff --git a/studio/components/interfaces/Authentication/Users/InviteUserModal.tsx b/studio/components/interfaces/Authentication/Users/InviteUserModal.tsx index 71b6501fb07..401e60663a0 100644 --- a/studio/components/interfaces/Authentication/Users/InviteUserModal.tsx +++ b/studio/components/interfaces/Authentication/Users/InviteUserModal.tsx @@ -1,6 +1,6 @@ -import { useContext, useState, useRef } from 'react' +import { useContext, useState } from 'react' import { observer } from 'mobx-react-lite' -import { Button, Modal, Input, IconPlus, IconMail } from '@supabase/ui' +import { Button, Modal, Input, IconPlus, IconMail, Form } from '@supabase/ui' import { useStore } from 'hooks' import { post } from 'lib/common/fetch' @@ -8,44 +8,32 @@ import { API_URL } from 'lib/constants' import { PageContext } from 'pages/project/[ref]/auth/users' const InviteUserModal = () => { - const PageState: any = useContext(PageContext) - const inputRef = useRef(null) const { ui } = useStore() - + const PageState: any = useContext(PageContext) const [visible, setVisible] = useState(false) - const [loading, setLoading] = useState(false) - const [emailValue, setEmailValue] = useState('') - function handleToggle() { - // reset data before showing modal again - if (!visible) { - setEmailValue('') - } - setVisible(!visible) - } + const handleToggle = () => setVisible(!visible) - function onInputChange(e: any) { - setEmailValue(e.target.value) - } - - async function onInviteUser() { + const validate = (values: any) => { + const errors: any = {} const emailValidateRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/ - if (!emailValidateRegex.test(emailValue)) { - inputRef?.current?.focus() - const message = - emailValue.trim() === '' - ? 'Please enter a valid email' - : `${emailValue} is an invalid email` - ui.setNotification({ category: 'error', message: message }) - return + + if (values.email.length === 0) { + errors.email = 'Please enter a valid email' + } else if (!emailValidateRegex.test(values.email)) { + errors.email = `${values.email} is an invalid email` } - setLoading(true) - const response = await post(`${API_URL}/auth/${PageState.projectRef}/invite`, { - email: emailValue, - }) + return errors + } + const onInviteuser = async (values: any, { setSubmitting }: any) => { + setSubmitting(true) + + const response = await post(`${API_URL}/auth/${PageState.projectRef}/invite`, { + email: values.email, + }) if (response.error) { ui.setNotification({ category: 'error', @@ -55,12 +43,12 @@ const InviteUserModal = () => { PageState.fetchData(1) ui.setNotification({ category: 'success', - message: `Sent invite email to ${emailValue}`, + message: `Sent invite email to ${values.email}`, }) + setVisible(false) } - setLoading(false) - setVisible(false) + setSubmitting(false) } return ( @@ -69,38 +57,48 @@ const InviteUserModal = () => { Invite -
- - } - descriptionText="Type in the full email address" - autoFocus - // @ts-ignore - ref={inputRef} - value={emailValue} - onChange={onInputChange} - type="email" - name="email" - id="email" - placeholder="User email" - className="w-full" - /> - - - - -
+
+ {({ isSubmitting }: { isSubmitting: boolean }) => ( +
+ + } + type="email" + name="email" + placeholder="User email" + /> + + + + +
+ )} +
) diff --git a/studio/components/interfaces/Billing/AddNewPaymentMethodModal/AddPaymentMethodForm.tsx b/studio/components/interfaces/Billing/AddNewPaymentMethodModal/AddPaymentMethodForm.tsx index fa5c0ed9e9a..444eb12257e 100644 --- a/studio/components/interfaces/Billing/AddNewPaymentMethodModal/AddPaymentMethodForm.tsx +++ b/studio/components/interfaces/Billing/AddNewPaymentMethodModal/AddPaymentMethodForm.tsx @@ -29,6 +29,11 @@ const AddPaymentMethodForm: FC = ({ returnUrl, onCancel }) => { setIsSaving(true) + if (document !== undefined) { + // [Joshen] This is to ensure that any 3DS popup from Stripe remains clickable + document.body.classList.add('!pointer-events-auto') + } + const { error } = await stripe.confirmSetup({ elements, confirmParams: { return_url: returnUrl }, @@ -41,6 +46,10 @@ const AddPaymentMethodForm: FC = ({ returnUrl, onCancel }) => { message: error?.message ?? ' Failed to save card details', }) } + + if (document !== undefined) { + document.body.classList.remove('!pointer-events-auto') + } } return ( diff --git a/studio/components/interfaces/Billing/Subscription/Subscription.tsx b/studio/components/interfaces/Billing/Subscription/Subscription.tsx index 65fd5ae48fa..aaff5936893 100644 --- a/studio/components/interfaces/Billing/Subscription/Subscription.tsx +++ b/studio/components/interfaces/Billing/Subscription/Subscription.tsx @@ -3,6 +3,7 @@ import { FC } from 'react' import { sum } from 'lodash' import { useRouter } from 'next/router' import { Button, Loading } from '@supabase/ui' +import * as Tooltip from '@radix-ui/react-tooltip' import { PermissionAction } from '@supabase/shared-types/out/constants' import { checkPermissions, useStore, useFlag } from 'hooks' @@ -38,7 +39,6 @@ const Subscription: FC = ({ }) => { const { ui } = useStore() const router = useRouter() - const isOrgOwner = ui.selectedOrganization?.is_owner const enablePermissions = useFlag('enablePermissions') const projectUpdateDisabled = useFlag('disableProjectCreationAndUpdate') @@ -46,7 +46,7 @@ const Subscription: FC = ({ const canReadSubscription = checkPermissions(PermissionAction.READ, 'subscriptions') const canUpdateSubscription = enablePermissions ? checkPermissions(PermissionAction.BILLING_WRITE, 'stripe.subscriptions') - : isOrgOwner + : ui.selectedOrganization?.is_owner const isPayg = subscription?.tier.prod_id === STRIPE_PRODUCT_IDS.PAYG const isEnterprise = subscription.tier.supabase_prod_id === PRICING_TIER_PRODUCT_IDS.ENTERPRISE @@ -75,46 +75,51 @@ const Subscription: FC = ({

{subscription?.tier.name ?? '-'}

- {isEnterprise ? ( - - ) : ( - - )} - {!canUpdateSubscription ? ( - <> - {enablePermissions ? ( -

- You need additional permissions to amend subscriptions -

- ) : ( -

- Only the organization owner can amend subscriptions -

- )} - - ) : projectUpdateDisabled ? ( -

- Subscription changes are currently disabled -
- Our engineers are working on a fix -

- ) : ( -
- )} + + + + + {!canUpdateSubscription || projectUpdateDisabled ? ( + + +
+ + {projectUpdateDisabled ? ( + <> + Subscription changes are currently disabled. +
+ Our engineers are working on a fix. + + ) : !canUpdateSubscription && enablePermissions ? ( + 'You need additional permissions to amend subscriptions' + ) : !canUpdateSubscription && !enablePermissions ? ( + 'Only the organization owner can amend subscriptions' + ) : ( + '' + )} +
+
+
+ ) : ( + <> + )} +
{paid && ( diff --git a/studio/components/interfaces/Organization/TeamSettings/MemberActions.tsx b/studio/components/interfaces/Organization/TeamSettings/MemberActions.tsx index d39d2342bab..9e12672a072 100644 --- a/studio/components/interfaces/Organization/TeamSettings/MemberActions.tsx +++ b/studio/components/interfaces/Organization/TeamSettings/MemberActions.tsx @@ -36,11 +36,16 @@ const MemberActions: FC = ({ members, member, roles }) => { const isExpired = isInviteExpired(member?.invited_at ?? '') const isPendingInviteAcceptance = member.invited_id + const roleId = member.role_ids?.[0] ?? -1 const canRemoveMember = enablePermissions ? rolesRemovable.includes((member?.role_ids ?? [-1])[0]) : true - const canResendInvite = checkPermissions(PermissionAction.CREATE, 'user_invites') - const canRevokeInvite = checkPermissions(PermissionAction.DELETE, 'user_invites') + const canResendInvite = checkPermissions(PermissionAction.CREATE, 'user_invites', { + resource: { role_id: roleId }, + }) + const canRevokeInvite = checkPermissions(PermissionAction.DELETE, 'user_invites', { + resource: { role_id: roleId }, + }) const handleMemberDelete = async () => { confirmAlert({ diff --git a/studio/components/interfaces/Organization/TeamSettings/MembersView.tsx b/studio/components/interfaces/Organization/TeamSettings/MembersView.tsx index d1281e8033d..615e2ca16be 100644 --- a/studio/components/interfaces/Organization/TeamSettings/MembersView.tsx +++ b/studio/components/interfaces/Organization/TeamSettings/MembersView.tsx @@ -12,6 +12,7 @@ import { isInviteExpired, getUserDisplayName } from '../Organization.utils' import Table from 'components/to-be-cleaned/Table' import MemberActions from './MemberActions' +import RolesHelperModal from './RolesHelperModal/RolesHelperModal' import { PageContext } from 'pages/org/[slug]/settings' import { getRolesManagementPermissions } from './TeamSettings.utils' @@ -84,7 +85,10 @@ const MembersView = () => { head={[ User, , - Role, + + Role + {enablePermissions && } + , , ]} body={[ @@ -97,7 +101,7 @@ const MembersView = () => { const disableRoleEdit = !canRemoveRole || memberIsUser || memberIsPendingInvite const validateSelectedRoleToChange = (roleId: any) => { - if (!role) return + if (!role || role.id === roleId) return const selectedRole = (roles || []).find((role) => role.id === roleId) const canAddRole = rolesAddable.includes(selectedRole?.id ?? -1) @@ -167,14 +171,14 @@ const MembersView = () => { value={role.id} onChange={validateSelectedRoleToChange} > - {roles.map((role: any) => ( + {roles.map((r: any) => ( - {role.name} + {r.name} ))} @@ -194,7 +198,7 @@ const MembersView = () => { - ) : !canRemoveRole ? ( + ) : !memberIsUser && !canRemoveRole ? (
= ({}) => { + const [showModal, setShowModal] = useState(false) + return ( + <> + setShowModal(!showModal)} + /> + setShowModal(!showModal)} + > +
+ +

+ The following table shows the corresponding permissions for each available role in the + dashboard. +

+
+ +
+
+
Permissions
+
+ Owner +
+
+ Adminstrator +
+
+ Developer +
+
+ +
+ {PERMISSIONS_MAPPING.map((group) => ( + +
+
{group.title}
+
+ {group.actions.map((action, idx) => ( +
+
{action.description}
+
+ {action.permissions.owner && } +
+
+ {action.permissions.admin && } +
+
+ {action.permissions.developer && } +
+
+ ))} +
+ ))} +
+
+
+
+
+ + ) +} + +export default RolesHelperModal diff --git a/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectButton.tsx b/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectButton.tsx index 4d433bfccd4..45d2d1d9c87 100644 --- a/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectButton.tsx +++ b/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectButton.tsx @@ -3,7 +3,7 @@ import { useRouter } from 'next/router' import { Button } from '@supabase/ui' import * as Tooltip from '@radix-ui/react-tooltip' -import { useStore, checkPermissions } from 'hooks' +import { useStore, checkPermissions, useFlag } from 'hooks' import { API_URL } from 'lib/constants' import { delete_ } from 'lib/common/fetch' import TextConfirmModal from 'components/ui/Modals/TextConfirmModal' @@ -16,13 +16,17 @@ interface Props { const DeleteProjectButton: FC = ({ type = 'danger' }) => { const router = useRouter() const { app, ui } = useStore() + const enablePermissions = useFlag('enablePermissions') const project = ui.selectedProject + const isOwner = ui.selectedOrganization?.is_owner const [isOpen, setIsOpen] = useState(false) const [loading, setLoading] = useState(false) - const canDeleteProject = checkPermissions(PermissionAction.UPDATE, 'projects') + const canDeleteProject = enablePermissions + ? checkPermissions(PermissionAction.UPDATE, 'projects') + : isOwner const toggle = () => { if (loading) return @@ -52,11 +56,9 @@ const DeleteProjectButton: FC = ({ type = 'danger' }) => { <> -
- -
+
{!canDeleteProject && ( diff --git a/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectPanel.tsx b/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectPanel.tsx index b04b7785663..f6a75ee3aa6 100644 --- a/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectPanel.tsx +++ b/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectPanel.tsx @@ -23,7 +23,7 @@ const DeleteProjectPanel: FC = ({}) => { withIcon title="Deleting this project will also remove your database." > -
+

Make sure you have made a backup if you want to keep your data.

diff --git a/studio/components/interfaces/Settings/General/General.tsx b/studio/components/interfaces/Settings/General/General.tsx index 9bd14c4ee58..b14935f30b2 100644 --- a/studio/components/interfaces/Settings/General/General.tsx +++ b/studio/components/interfaces/Settings/General/General.tsx @@ -2,7 +2,7 @@ import { FC } from 'react' import { Form, Input } from '@supabase/ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { useStore, checkPermissions } from 'hooks' +import { useStore, checkPermissions, useFlag } from 'hooks' import { API_URL } from 'lib/constants' import { post } from 'lib/common/fetch' import { @@ -20,9 +20,14 @@ const General: FC = ({}) => { const { app, ui } = useStore() const project = ui.selectedProject + const enablePermissions = useFlag('enablePermissions') + const isOwner = ui.selectedOrganization?.is_owner + const formId = 'project-general-settings' const initialValues = { name: project?.name ?? '', ref: project?.ref ?? '' } - const canUpdateProject = checkPermissions(PermissionAction.UPDATE, 'projects') + const canUpdateProject = enablePermissions + ? checkPermissions(PermissionAction.UPDATE, 'projects') + : isOwner const onSubmit = async (values: any, { setSubmitting, resetForm }: any) => { const response = await post(`${API_URL}/projects/${project?.ref}/update`, { name: values.name }) diff --git a/studio/components/interfaces/Settings/General/Infrastructure/PauseProjectButton.tsx b/studio/components/interfaces/Settings/General/Infrastructure/PauseProjectButton.tsx index d625a046d3b..255ea80ae5a 100644 --- a/studio/components/interfaces/Settings/General/Infrastructure/PauseProjectButton.tsx +++ b/studio/components/interfaces/Settings/General/Infrastructure/PauseProjectButton.tsx @@ -5,7 +5,7 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { Button, IconPause } from '@supabase/ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useStore } from 'hooks' +import { checkPermissions, useStore, useFlag } from 'hooks' import { post } from 'lib/common/fetch' import { API_URL, PROJECT_STATUS } from 'lib/constants' import ConfirmModal from 'components/ui/Dialogs/ConfirmDialog' @@ -21,13 +21,15 @@ const PauseProjectButton: FC = observer(({ projectRef, projectId }) => { const [loading, setLoading] = useState(false) const [isModalOpen, setIsModalOpen] = useState(false) + const enablePermissions = useFlag('enablePermissions') + const isOwner = ui.selectedOrganization?.is_owner + const openModal = () => setIsModalOpen(true) const closeModal = () => setIsModalOpen(false) - const canPauseProject = checkPermissions( - PermissionAction.INFRA_EXECUTE, - 'queue_jobs.projects.pause' - ) + const canPauseProject = enablePermissions + ? checkPermissions(PermissionAction.INFRA_EXECUTE, 'queue_jobs.projects.pause') + : isOwner const requestPauseProject = async () => { if (!canPauseProject) { diff --git a/studio/components/interfaces/Settings/Logs/LogTable.tsx b/studio/components/interfaces/Settings/Logs/LogTable.tsx index 59b83fb6c87..c3a6b14a94a 100644 --- a/studio/components/interfaces/Settings/Logs/LogTable.tsx +++ b/studio/components/interfaces/Settings/Logs/LogTable.tsx @@ -12,13 +12,16 @@ import DatabaseApiColumnRender from './LogColumnRenderers/DatabaseApiColumnRende import DatabasePostgresColumnRender from './LogColumnRenderers/DatabasePostgresColumnRender' import CSVButton from 'components/ui/CSVButton' import DefaultPreviewColumnRenderer from './LogColumnRenderers/DefaultPreviewColumnRenderer' +import { LogQueryError } from '.' +import ResourcesExceededErrorRenderer from './LogsErrorRenderers/ResourcesExceededErrorRenderer' +import DefaultErrorRenderer from './LogsErrorRenderers/DefaultErrorRenderer' interface Props { data?: Array onHistogramToggle?: () => void isHistogramShowing?: boolean isLoading?: boolean - error?: any + error?: LogQueryError | null showDownload?: boolean // TODO: move all common params to a context to avoid prop drilling queryType?: QueryType @@ -227,6 +230,34 @@ const LogTable = ({ } }, [stringData]) + const renderErrorAlert = () => { + if (!error) return null + const childProps = { + isCustomQuery: queryType ? false : true, + error: error!, + } + let Renderer = DefaultErrorRenderer + if ( + typeof error === 'object' && + error.error?.errors.find((err) => err.reason === 'resourcesExceeded') + ) { + Renderer = ResourcesExceededErrorRenderer + } + + return ( +
+ + + +
+ ) + } + return ( <>
)} - {error && ( -
- - - -
- )} + {error && renderErrorAlert()}
) : null diff --git a/studio/components/interfaces/Settings/Logs/Logs.types.ts b/studio/components/interfaces/Settings/Logs/Logs.types.ts index 8c2565d16e0..7e5280a45a8 100644 --- a/studio/components/interfaces/Settings/Logs/Logs.types.ts +++ b/studio/components/interfaces/Settings/Logs/Logs.types.ts @@ -51,9 +51,19 @@ export interface CountData { type LFResponse = { result: T[] error?: { + code: number + errors: { + domain: string + message: string + reason: string | 'resourcesExceeded' + }[] message: string + status: string } } +type ApiError = string + +export type LogQueryError = Omit, "result"> | ApiError export type Count = LFResponse diff --git a/studio/components/interfaces/Settings/Logs/LogsErrorRenderers/DefaultErrorRenderer.tsx b/studio/components/interfaces/Settings/Logs/LogsErrorRenderers/DefaultErrorRenderer.tsx new file mode 100644 index 00000000000..4d3a92c6713 --- /dev/null +++ b/studio/components/interfaces/Settings/Logs/LogsErrorRenderers/DefaultErrorRenderer.tsx @@ -0,0 +1,19 @@ +import { Input } from '@supabase/ui' +import { LogQueryError } from '..' + +export interface ErrorRendererProps { + error: LogQueryError + isCustomQuery: boolean +} + +const DefaultErrorRenderer: React.FC = ({ error }) => ( + +) +export default DefaultErrorRenderer diff --git a/studio/components/interfaces/Settings/Logs/LogsErrorRenderers/LogsErrorRenderers.stories.tsx b/studio/components/interfaces/Settings/Logs/LogsErrorRenderers/LogsErrorRenderers.stories.tsx new file mode 100644 index 00000000000..c5c8332e2d0 --- /dev/null +++ b/studio/components/interfaces/Settings/Logs/LogsErrorRenderers/LogsErrorRenderers.stories.tsx @@ -0,0 +1,65 @@ +import React, { useState } from 'react' + +import DefaultErrorRenderer from './DefaultErrorRenderer' +import ResourcesExceededErrorRenderer from './ResourcesExceededErrorRenderer' +import { Alert } from '@supabase/ui' + +export default { + title: 'Logs', +} + +export const ErrorRenderers = () => ( +
+ {[ + , + , + , + + , + ].map((child) => ( + + {child} + + ))} +
+) diff --git a/studio/components/interfaces/Settings/Logs/LogsErrorRenderers/ResourcesExceededErrorRenderer.tsx b/studio/components/interfaces/Settings/Logs/LogsErrorRenderers/ResourcesExceededErrorRenderer.tsx new file mode 100644 index 00000000000..2d41f559137 --- /dev/null +++ b/studio/components/interfaces/Settings/Logs/LogsErrorRenderers/ResourcesExceededErrorRenderer.tsx @@ -0,0 +1,39 @@ +import { Accordion, Input } from '@supabase/ui' +import { ErrorRendererProps } from './DefaultErrorRenderer' + +const ResourcesExceededErrorRenderer: React.FC = ({ error, isCustomQuery }) => ( +
+
+

This query requires too much memory to be executed.

+

+ {isCustomQuery + ? 'Avoid selecting entire objects and instead select specific keys using dot notation.' + : 'Avoid querying across a large datetime range.'} +

+ {!isCustomQuery &&

Please contact support if this error persists.

} +
+ + + + + +
+) + +export default ResourcesExceededErrorRenderer diff --git a/studio/components/layouts/AuthLayout/AuthLayout.utils.ts b/studio/components/layouts/AuthLayout/AuthLayout.utils.ts index b080ea87ec2..465c8b89df0 100644 --- a/studio/components/layouts/AuthLayout/AuthLayout.utils.ts +++ b/studio/components/layouts/AuthLayout/AuthLayout.utils.ts @@ -36,7 +36,7 @@ export const generateAuthMenu = (ref: string): ProductMenuGroup[] => { ] : []), { - name: 'Templates', + name: 'Email Templates', key: 'templates', url: `/project/${ref}/auth/templates`, items: [], diff --git a/studio/components/layouts/ProjectLayout/LayoutHeader/HelpPopover.tsx b/studio/components/layouts/ProjectLayout/LayoutHeader/HelpPopover.tsx index fc06202088f..cc1ad3302a5 100644 --- a/studio/components/layouts/ProjectLayout/LayoutHeader/HelpPopover.tsx +++ b/studio/components/layouts/ProjectLayout/LayoutHeader/HelpPopover.tsx @@ -5,6 +5,7 @@ import { IconMessageCircle, Popover, IconBookOpen, + IconActivity, } from '@supabase/ui' import { useRouter } from 'next/router' import { FC } from 'react' @@ -34,20 +35,21 @@ const HelpPopover: FC = () => { For issues with your project hosted on supabase.com, or other inquiries about our hosted services.

-
- - - - +
+ + - - - - + + + + +

diff --git a/studio/components/layouts/ProjectLayout/ProjectPausedState.tsx b/studio/components/layouts/ProjectLayout/ProjectPausedState.tsx index b74ab4593d4..a3b11e308dc 100644 --- a/studio/components/layouts/ProjectLayout/ProjectPausedState.tsx +++ b/studio/components/layouts/ProjectLayout/ProjectPausedState.tsx @@ -4,7 +4,7 @@ import { Alert, Button, IconPauseCircle } from '@supabase/ui' import { PermissionAction } from '@supabase/shared-types/out/constants' import { Project } from 'types' -import { checkPermissions, useStore, useSubscriptionStats } from 'hooks' +import { checkPermissions, useStore, useSubscriptionStats, useFlag } from 'hooks' import { post } from 'lib/common/fetch' import { API_URL, PROJECT_STATUS, DEFAULT_FREE_PROJECTS_LIMIT } from 'lib/constants' import { DeleteProjectButton } from 'components/interfaces/Settings/General' @@ -20,13 +20,15 @@ const ProjectPausedState: FC = ({ project }) => { const { total_active_free_projects: totalActiveFreeProjects } = subscriptionStats const freeProjectsLimit = ui.profile?.free_project_limit ?? DEFAULT_FREE_PROJECTS_LIMIT + const enablePermissions = useFlag('enablePermissions') + const isOwner = ui.selectedOrganization?.is_owner + const [showConfirmRestore, setShowConfirmRestore] = useState(false) const hasExceedActiveFreeProjectsLimit = totalActiveFreeProjects >= freeProjectsLimit - const canResumeProject = checkPermissions( - PermissionAction.INFRA_EXECUTE, - 'queue_jobs.projects.initialize_or_resume' - ) + const canResumeProject = enablePermissions + ? checkPermissions(PermissionAction.INFRA_EXECUTE, 'queue_jobs.projects.initialize_or_resume') + : isOwner const onSelectRestore = () => { if (!canResumeProject) { diff --git a/studio/components/to-be-cleaned/Table.tsx b/studio/components/to-be-cleaned/Table.tsx index f5c33fbb7a7..6e1c4c4d81a 100644 --- a/studio/components/to-be-cleaned/Table.tsx +++ b/studio/components/to-be-cleaned/Table.tsx @@ -48,7 +48,7 @@ const Th: React.FC = ({ children, className, style }) => { if (className) classes.push(className) return ( - {children} + {children} ) } diff --git a/studio/styles/ui.scss b/studio/styles/ui.scss index edd4643abf4..131380b4316 100644 --- a/studio/styles/ui.scss +++ b/studio/styles/ui.scss @@ -118,7 +118,7 @@ } .table-container thead th { - @apply text-scale-900 font-normal text-sm; + @apply text-scale-1100 font-normal text-sm; @apply bg-table-header-light dark:bg-table-header-dark; @apply border-t border-b border-table-border-light dark:border-table-border-dark; } diff --git a/studio/tests/pages/projects/LogTable.test.js b/studio/tests/pages/projects/LogTable.test.js index 1e0b5eaffc4..12446159483 100644 --- a/studio/tests/pages/projects/LogTable.test.js +++ b/studio/tests/pages/projects/LogTable.test.js @@ -90,3 +90,37 @@ test('error message handling', async () => { await screen.findByText(/string/) await screen.findByText(/my_error/) }) + +test('custom error message: Resources exceeded during query execution', async () => { + const errorFromLogflare = { + error: { + code: 400, + errors: [ + { + domain: 'global', + message: + 'Resources exceeded during query execution: The query could not be executed in the allotted memory. Peak usage: 122% of limit.\nTop memory consumer(s):\n ORDER BY operations: 99%\n other/unattributed: 1%\n', + reason: 'resourcesExceeded', + }, + ], + message: + 'Resources exceeded during query execution: The query could not be executed in the allotted memory. Peak usage: 122% of limit.\nTop memory consumer(s):\n ORDER BY operations: 99%\n other/unattributed: 1%\n', + status: 'INVALID_ARGUMENT', + }, + } + + // logs explorer, custom query + const { rerender } = render() + + // prompt user to reduce selected tables + await screen.findByText(/This query requires too much memory to be executed/) + await screen.findByText( + /Avoid selecting entire objects and instead select specific keys using dot notation/ + ) + + // previewer, prompt to reduce time range + rerender() + await screen.findByText(/This query requires too much memory to be executed/) + await screen.findByText(/Avoid querying across a large datetime range/) + await screen.findByText(/Please contact support if this error persists/) +}) diff --git a/web/docs/guides/api.mdx b/web/docs/guides/api.mdx index 8883bb38142..3d9c80e88f1 100644 --- a/web/docs/guides/api.mdx +++ b/web/docs/guides/api.mdx @@ -2,6 +2,7 @@ id: api title: APIs description: Auto-generating and Realtime APIs. +sidebar_label: Overview --- import Tabs from '@theme/Tabs'; @@ -24,7 +25,7 @@ The APIs are: - **Scalable.**
The API can serve thousands of simultaneous requests, and works well for Serverless workloads. -### REST API +### REST API {#rest-api-overview} Supabase provides a RESTful API using [PostgREST](https://postgrest.org/). This is a very thin API layer on top of Postgres. It provides everything you need from a CRUD API: @@ -45,7 +46,7 @@ It provides everything you need from a CRUD API: allowFullScreen > -### GraphQL API +### GraphQL API {#graphql-api-overview} :::note @@ -55,7 +56,7 @@ GraphQL is in Beta, and may have breaking changes. It is only available on self- GraphQL in Supabase works through [pg_graphql](https://supabase.com/blog/2021/12/03/pg-graphql), an open source PostgreSQL extension for GraphQL. -### Realtime API +### Realtime API {#realtime-api-overview} Supabase provides a Realtime API using [Realtime](https://github.com/supabase/realtime). You can use this to listen to database changes over websockets. Realtime leverages PostgreSQL's built-in logical replication. You can manage your Realtime API simply by managing Postgres publications. @@ -69,33 +70,31 @@ All APIs are auto-created from Database tables. After you have added tables or f API routes are automatically created when you create Postgres Tables, Views, or Functions. Let's create our first -API route by creating a table called `todos` (which will store some public user information). -This will create a corresponding route `todos` which can accept `GET`, `POST`, `PATCH`, & `DELETE` requests. +API route by creating a table called `todos` to store tasks. +This creates a corresponding route `todos` which can accept `GET`, `POST`, `PATCH`, & `DELETE` requests. - + groupId="dashboard-or-sql" + defaultValue="dashboard" + values={[ + {label: 'Dashboard', value: 'dashboard'}, + {label: 'SQL', value: 'sql'}, + ]}> -```sh -1. Go to the "Table editor" section. -2. Click "New Table". -3. Enter the table name "todos". -4. Click "Save". -5. Click "New Column". -6. Enter the column name "task" and make the type "text". -7. Click "Save". -``` + + +1. Go to the [Table editor](https://app.supabase.com/project/_/editor) page in the Dashboard. +1. Click **New Table** and create a table with the name `todos`. +1. Click **Save**. +1. Click **New Column** and create a column with the name `task` and type `text`. +1. Click **Save**. - + ```sql -- Create a table called "todos" with a column to store tasks. @@ -113,13 +112,9 @@ create table todos ( Every Supabase project has a unique API URL. Your API is secured behind an API gateway which requires an API Key for every request. - -```sh -1. Go to the "Settings" section. -2. Click "API" in the sidebar. -3. Find your API URL in this page. -4. Find your "anon" and "service_role" keys on this page. -``` +1. Go to the [Settings](https://app.supabase.com/project/_/settings/general) page in the Dashboard. +2. Click **API** in the sidebar. +3. Find your API `URL`, `anon`, and `service_role` keys on this page.