<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Danilo à Tellinghusen ▪️ ☕ &amp; 🍕</title>
    <description>The latest articles on Forem by Danilo à Tellinghusen ▪️ ☕ &amp; 🍕 (@sleeplessfox).</description>
    <link>https://forem.com/sleeplessfox</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F984446%2F021e7327-91b8-4b3c-a99c-ce02cb090d03.jpg</url>
      <title>Forem: Danilo à Tellinghusen ▪️ ☕ &amp; 🍕</title>
      <link>https://forem.com/sleeplessfox</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/sleeplessfox"/>
    <language>en</language>
    <item>
      <title>Simple Analytics Integration in Ionic Mobile Apps</title>
      <dc:creator>Danilo à Tellinghusen ▪️ ☕ &amp; 🍕</dc:creator>
      <pubDate>Mon, 29 Jan 2024 07:30:13 +0000</pubDate>
      <link>https://forem.com/sleeplessfox/simple-analytics-integration-in-ionic-mobile-apps-3210</link>
      <guid>https://forem.com/sleeplessfox/simple-analytics-integration-in-ionic-mobile-apps-3210</guid>
      <description>&lt;p&gt;While creating my app &lt;a href="https://rdzn.de"&gt;[RDZN] - German Football&lt;/a&gt;, I was in search of an analytics solution that is compliant with German law, user-friendly, and easy to integrate. Nothing easier than that 😅. &lt;br&gt;
The goal is to track essential data, enabling me to consistently improve the app and offer users an enhanced and more enjoyable experience.&lt;/p&gt;


&lt;h2&gt;
  
  
  1. What is [RDZN] - German Football?
&lt;/h2&gt;

&lt;p&gt;[RDZN] - German Football is a mobile app about American Football in Germany, focusing on the first German Football League (GFL) and the second German Football League (GFL2).&lt;br&gt;
The app is built using Ionic, Angular, Capacitor and with an AWS Serverless Backend in the background. You can download it on Apple App Store and Google Play Store.&lt;/p&gt;

&lt;p&gt;After approximately 4 years in the app stores at the beginning of 2023, RDZN achieved official partner status with the GFL and GFL2, marking a profound personal achievement. The acknowledgment as an "official partner" prompted the integration of a new analytics service within the app. This decision aimed to enhance compliance with German regulations and mitigate potential legal issues, reflecting a commitment to aligning with local laws.&lt;/p&gt;


&lt;h2&gt;
  
  
  2. Challenges with Traditional Analytics in Germany
&lt;/h2&gt;

&lt;p&gt;Understanding how analytics works in Germany has its own set of challenges, especially when dealing with the rules about how data can be used and keeping everything in line with the law. Even though regular analytics tools are quite effective, they face certain difficulties specific to Germany.&lt;/p&gt;

&lt;p&gt;The General Data Protection Regulation (GDPR) casts a substantial shadow over analytics practices. With the focus on protecting user privacy, German data protection laws are stringent. Following this law can be tricky for traditional analytics tools because they might struggle to get clear permission from users before collecting and using their data.&lt;/p&gt;

&lt;p&gt;Even popular tools like Google Analytics face challenges in Germany. The data collection practices of such tools may not always align with the strict standards set by German privacy laws. This misalignment raises concerns about the legality and ethicality of data handling, leading to a search for different solutions.&lt;/p&gt;

&lt;p&gt;Given these challenges, there's a growing need for analytics solutions that focus on keeping user data private, following GDPR rules, and fitting seamlessly with German data protection laws. So I started looking for a better suitable solution for [RDZN].&lt;/p&gt;


&lt;h2&gt;
  
  
  3. Simple Analytics: A Great Choice
&lt;/h2&gt;

&lt;p&gt;For my app, I needed a tool that complied with the rules of strict German data protection laws and had a solid commitment to user privacy and transparency. During my research, I came across several similar services that met my requirements. However, one particular product captured my attention due to its simplicity, design, and impressive set of features.&lt;/p&gt;

&lt;p&gt;Let's delve into the features and benefits that make &lt;a href="https://www.simpleanalytics.com/?referral=danilo-tellinghusen"&gt;Simple Analytics&lt;/a&gt; a superior and more compliant choice, especially when compared to the widely used Google Analytics.&lt;/p&gt;
&lt;h3&gt;
  
  
  Features and Benefits
&lt;/h3&gt;

&lt;p&gt;Simple Analytics is like a protective fortress for your data and will never store any personal data about your visitors, unlike some tools that might engage in shady practices.&lt;br&gt;
Transparency is a core value for Simple Analytics. It is an Open Startup and operates openly, giving users a clear view of how their data is treated and how their business is going. This ethical approach perfectly aligns with RDZN's commitment to trustworthy analytics.&lt;/p&gt;

&lt;p&gt;Designed for user-friendliness, Simple Analytics presents easy-to-understand AI-driven insights, simplifying the navigation through complex reports. This ensures RDZN gains meaningful insights without drowning in data complexity.&lt;/p&gt;

&lt;p&gt;Security is a top-tier concern for Simple Analytics, employing encrypted data storage and strict measures to keep RDZN's analytics data confidential and secure.&lt;/p&gt;

&lt;p&gt;As an EU-based entity, Simple Analytics embraces the privacy standards set by the European Union. Beyond being a feature, privacy protection is the business model of Simple Analytics. It aligns with various privacy policies, including GDPR, PECR, CCPA, and more.&lt;/p&gt;

&lt;p&gt;Unlike Google Analytics, Simple Analytics works without invasive cookies. This cookie-free approach respects user privacy and saves users from annoying cookie banners, creating a smoother experience.&lt;/p&gt;

&lt;p&gt;With Simple Analytics, I get real-time analytics insights without messing with user privacy. It allows immediate responses to user behavior while keeping privacy a top priority&lt;/p&gt;

&lt;p&gt;**Here's a summary of all key features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Aligning with GDPR, PECR, CCPA, and more.&lt;/li&gt;
&lt;li&gt;Embracing simplicity, the dashboard offers insights in a straightforward and user-friendly manner.&lt;/li&gt;
&lt;li&gt;Just chat with AI to make analytics more intuitive.&lt;/li&gt;
&lt;li&gt;Zero Personal Data Storage, No Cookie Banners: They don't store personal information, eliminating the need for annoying cookie banners.&lt;/li&gt;
&lt;li&gt;Goals-Tracker and Events Explorer: Keep a close eye on crucial events and conversion funnels&lt;/li&gt;
&lt;li&gt;Lightweight Script for Increased Website Speed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In a nutshell, Simple Analytics is the perfect fit for RDZN, offering features and benefits that not only amp up analytics capabilities but also resonate with the principles of privacy, transparency, and user trust.&lt;/p&gt;


&lt;h2&gt;
  
  
  4. Integration Guide: Ionic Mobile App
&lt;/h2&gt;

&lt;p&gt;In the first place, Simple Analytics is designed for websites and not directly for mobile apps. However, why not use it in web-based mobile apps like Ionic apps?&lt;/p&gt;

&lt;p&gt;The [RDZN] - German Football App is an Ionic/Angular app and for that, I will show you how easily you can integrate Simple Analytics into your Ionic app.&lt;/p&gt;
&lt;h3&gt;
  
  
  4.1 Integration via Javascript
&lt;/h3&gt;

&lt;p&gt;Simple Analytics provides a script that you can embed within the&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;body&amp;gt; tag of your website or your index.html of your Ionic Angular/React app.
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;...&amp;lt;/head&amp;gt;

&amp;lt;body&amp;gt;  

  &amp;lt;app-root&amp;gt;&amp;lt;/app-root&amp;gt;

&amp;lt;!-- Simple Analytics --&amp;gt;
  &amp;lt;!-- Default Script --&amp;gt; 
  &amp;lt;script data-collect-dnt="true" async defer data-hostname="your-domain.com"
    src="https://scripts.simpleanalyticscdn.com/latest.js"&amp;gt;&amp;lt;/script&amp;gt;

  &amp;lt;!-- Use Pixel for visitors with disabled JavaScript --&amp;gt; 
  &amp;lt;noscript&amp;gt;
      &amp;lt;img src="https://queue.simpleanalyticscdn.com/noscript.gif" alt=""
      referrerpolicy="no-referrer-when-downgrade" /&amp;gt;
  &amp;lt;/noscript&amp;gt;

&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple Analytics gives you several settings parameters that allow you to customize the tracking script. For example, you can replace the default SA CDN domain with your own subdomain. This has the advantage of bypassing ad blockers that generally block analytical scripts.&lt;br&gt;
Here you can find more information about the various script settings:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.simpleanalytics.com/?source=post_page-----9371d545d1e7--------------------------------"&gt;Simple Analytics documentation&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  4.2 How to Collect App Events
&lt;/h3&gt;

&lt;p&gt;With the Simple Analytics script, you can now send and gather your custom events. To simplify this process, they've developed a dedicated automated events script. Installing this script once will enable tracking for standard events such as outbound links, clicks on email addresses, and the number of downloads for commonly used file types (pdf, csv, docx, xlsx).&lt;br&gt;
You can add the script to your &lt;strong&gt;&lt;/strong&gt; tag too.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;body&amp;gt;
  ...

  &amp;lt;!-- Auto Event Tracking --&amp;gt; 
  &amp;lt;script async src="https://scripts.simpleanalyticscdn.com/auto-events.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But now, let's dive into how to collect custom events and get our hands dirty! 😁&lt;/p&gt;

&lt;p&gt;Within your application or website, you can use the JavaScript sa_event - function to create events.&lt;/p&gt;

&lt;p&gt;To track an event you can do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sa_event("click_signup", {some metadata});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we want to employ this event function in our Ionic/Angular application. To do this, we generate a *.js file in our ./assets/js folder and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//sa-event-service.js
function trackSaEvent(eventName, eventData) {
  sa_event(eventName, eventData)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want you can use this function directly in your Angular Components to track custom events:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//app.component.ts

//Some imports here
import {...}

//Add Event service for SimpleAnalytics
declare const trackSaEvent: (...args: any[]) =&amp;gt; void;

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss'],
})
export class AppComponent {

  constructor() {}

  ...

  //Track custom event
  trackSaEvent('click_signup', {
      platform: 'android',
  });

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or use the function directly in HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!-- signin-form.component.html --&amp;gt; 

&amp;lt;button
    type="submit"
    onclick="sa_event('auth_sign_in_btn_click')"
    class="..."&amp;gt;
&amp;lt;/button&amp;gt;```



Because this solution is not yet optimal, let's construct a suitable Angular service.



```//analytics.service.ts 

import { Injectable } from '@angular/core';
import { environment } from 'src/environments/environment';

//Event service for SimpleAnalytics
declare const trackSaEvent: (...args: any[]) =&amp;gt; void;

@Injectable({
  providedIn: 'root',
})
export class AnalyticsService {
  constructor() {}

  trackEvent(event: string, data: any) {
    //Only send event data to Simple Analytics in prod mode
    if (environment.production) {
      trackSaEvent(event, data);
    } else {
      console.log('Analytics Event', event, data);
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//app.component.ts

//Some imports here
import {...}

//Add Event service for SimpleAnalytics
declare const trackSaEvent: (...args: any[]) =&amp;gt; void;

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss'],
})
export class AppComponent {

 constructor(
    private analyticsService: AnalyticsService,
  ) {
    ...
  }

  ...

  //Track custom event
   this.analyticsService.trackEvent('click_signup', {
        platform: 'android',
   });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's all 🤙!&lt;br&gt;
You can now collect events for all kinds of custom events. Like form submits, button clicks, open pages or views and many more.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Simple Analytics Dashboard
&lt;/h2&gt;

&lt;p&gt;By default, Simple Analytics captures all visits and page views on your website or app, along with their sources. You can then analyze this data within the straightforward and neat dashboard.&lt;br&gt;
In addition to information about visits and visitors, you can also view the default and custom events sent by the app 👍.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Conclusion
&lt;/h2&gt;

&lt;p&gt;Creating a mobile app comes with its challenges. Understanding how people use the app while respecting privacy laws, is crucial. &lt;a href="https://rdzn.de"&gt;RDZN&lt;/a&gt;faced this challenge and found a reliable ally in &lt;a href="https://www.simpleanalytics.com/?referral=danilo-tellinghusen"&gt;Simple Analytics&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Traditional analytics tools posed problems with privacy and German laws, so I needed a solution that fit the bill. Simple Analytics, with its privacy-focused approach and user-friendly features, turned out to be the perfect fit for me.&lt;/p&gt;

&lt;p&gt;By teaming up with Simple Analytics, RDZN not only got a tool for understanding user behavior but also a trustworthy partner in respecting user privacy. The process of bringing Simple Analytics into the app was smooth, and the ability to customize tracking scripts and use automated event tracking made it even better.&lt;br&gt;
In a nutshell, Simple Analytics became the go-to solution for my Ionic/Angular app, paving the way for a more secure and user-focused future for mobile apps and websites. I am so satisfied with the solution that I now also use Simple Analytics in my new project &lt;a href="https://makersdiary.com"&gt;MakersDiary&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The lesson here is clear: making apps better doesn't have to come at the cost of user privacy, and services like Simple Analytics are leading the way.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>ionic</category>
      <category>analytics</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Why I Switched From AWS Cognito To Supabase The Week Before My Startup Launched</title>
      <dc:creator>Danilo à Tellinghusen ▪️ ☕ &amp; 🍕</dc:creator>
      <pubDate>Mon, 05 Dec 2022 23:10:44 +0000</pubDate>
      <link>https://forem.com/sleeplessfox/why-i-switched-from-aws-cognito-to-supabase-the-week-before-my-startup-launched-269c</link>
      <guid>https://forem.com/sleeplessfox/why-i-switched-from-aws-cognito-to-supabase-the-week-before-my-startup-launched-269c</guid>
      <description>&lt;p&gt;Authentication is a very important part of any website. It's the thing that protects your users' data, and it's also the thing that, if implemented incorrectly, will kill your startup before it even begins. 😶&lt;br&gt;
However, there are many well-known authentication solutions that can be used for your startup because they will save you time and prevent risks to the success of your business - provided you choose the right one 😅&lt;/p&gt;
&lt;h2&gt;
  
  
  Backstory
&lt;/h2&gt;

&lt;p&gt;When I started my startup &lt;a href="https://makersdiary.com" rel="noopener noreferrer"&gt;MakersDiary&lt;/a&gt;, I decided from the outset that it made more sense for me to use an established solution - even if it costs money.&lt;/p&gt;

&lt;p&gt;MakersDiary is the first platform designed specifically to help indie makers and developers to share their journey in public. Track and manage their side hustles and startup projects to share all relevant information, successes, and struggles with the build-in-public community.&lt;/p&gt;

&lt;p&gt;For authentication, MakersDiary started with &lt;a href="https://aws.amazon.com/de/cognito/" rel="noopener noreferrer"&gt;AWS Cognito&lt;/a&gt; via Amplify, a great choice for a small startup that will be a serverless web application. I was using the Cognito User Pools, an authentication provider that allows MakersDiary to use a user pool with the AWS credentials of each user. When users sign into their account, they are redirected to my serverless web application that can handle all necessary needs.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Cognito Problem
&lt;/h2&gt;

&lt;p&gt;In the beginning, Cognito was really easy to set up but as &lt;a href="https://makersdiary.com" rel="noopener noreferrer"&gt;MakersDiary&lt;/a&gt; got more complex I started to struggle with this solution. AWS is awesome but also very complex and extensive with a very steep learning curve.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem 1 -&lt;/strong&gt; ❌&lt;/p&gt;

&lt;p&gt;It can happen that you lose yourself very quickly in the configuration and implementation so that everything works as desired. While I really love doing heavy implementation and learning more to be able to code what I want, it didn't help when I want to release my product quickly.&lt;/p&gt;

&lt;p&gt;So you have to develop and maintain your own backend service running on AWS Lambda that will handle the user auth process including pre- and post-auth functionalities like sending nice looking welcome or signup-confirmation emails. This is quite a big effort especially if you don't have such experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem 2 -&lt;/strong&gt; ❌&lt;/p&gt;

&lt;p&gt;The next problem arose when I started to implement third-party authentication like Twitter. With MakersDiary users can share their project information, monthly revenue &amp;amp; user updates, and much more directly on Twitter.&lt;/p&gt;

&lt;p&gt;While Cognito is a great solution for setting up your own authentication, it has almost no support for third-party authentication (except for Amazon, Apple &amp;amp; Google). So I had to implement the Twitter OAuth process by myself for MakersDiary.&lt;br&gt;
Even if there are great libraries like passport.js or twitter-api-v2, the manual implementation is still very time-consuming and gives me quite a headache.&lt;/p&gt;

&lt;p&gt;For example, after a user authenticates with Twitter all necessary information has to be written into the AWS Cognito User Pool so that you have all such information within your JWT token on your client to show e.g. the Twitter handle, name and profile image. It is all absolutely possible but a bit tricky and complex. 😪&lt;/p&gt;

&lt;p&gt;Later I realized that MakersDiary should support other social media providers e.g. LinkedIn beyond the MVP, so I'll have to implement this functionality again by myself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem 3 -&lt;/strong&gt; ❌&lt;/p&gt;

&lt;p&gt;MakersDiary users can upload their profile images, project logos and screenshots to add them to the projects they create. For this case, I used an AWS S3 bucket storage. If you just need a public bucket without any restrictions S3 is very easy to use. But if you want to restrict access to certain AWS accounts, S3 becomes very complex. In my case, I needed to restrict access to some specific JWT token holders with my AWS Cognito users, IAM roles and policies. And here the pain begins 😅…&lt;/p&gt;
&lt;h2&gt;
  
  
  The Decision
&lt;/h2&gt;

&lt;p&gt;After I while I saw more and more problems here which will block or at least slow me down sometimes. I was thinking about AWS Cognito is may not that easy and suitable solution for a small one-man startup.&lt;/p&gt;

&lt;p&gt;At this point, MakersDiary was not yet released, and no users had signed up. This made it easier for me to migrate away from AWS Cognito to another auth service than if I did so later with active users.&lt;/p&gt;

&lt;p&gt;So I decided to search for another auth service.&lt;/p&gt;

&lt;p&gt;My first idea was to move to &lt;a href="https://auth0.com/" rel="noopener noreferrer"&gt;Auth0&lt;/a&gt; one of the biggest auth services out there. But the Auth0 pricing model is very expensive at a later stage of your Startup and after reading &lt;a href="https://kevcodez.medium.com/migrating-125-000-users-from-auth0-to-supabase-81c0568de307" rel="noopener noreferrer"&gt;Kevin Grüneberg's article&lt;/a&gt; about how &lt;a href="//parqet.com"&gt;Parqet &lt;/a&gt; had to migrate from Auth0 to Supabase for that reason, I investigated further.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Supabase?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://supabase.com/" rel="noopener noreferrer"&gt;Supabase&lt;/a&gt; is an open-source alternative to Firebase. They use the slogan "Build in a weekend. Scale to millions" and I can say that is not a lie 😃.&lt;/p&gt;

&lt;p&gt;It allows you to set up the top 3 main parts of your app in almost no time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;Database&lt;/li&gt;
&lt;li&gt;Storage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can start with Supabase with a free plan which is absolutely suitable for a young startup. If your startup grows you can upgrade to a fair-priced pro plan without any problems.&lt;br&gt;
What I really like about Supabase is its simplicity. You can set up the whole app in one day with just a few lines of code. This means that you don't need to spend a lot of time on backend development and can focus on building your app. It's also open source so you have full control over your data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem 1 - ✅ Solved&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I planned to release &lt;a href="https://makersdiary.com" rel="noopener noreferrer"&gt;MakersDiary&lt;/a&gt; in around 7 days so the decision to move from Cognito to another auth service could put my whole release at risk. Luckily Supabase has quite nice documentation and initial database scripts so setting up my first project was no problem.&lt;/p&gt;

&lt;p&gt;Once you become familiar with the dashboard's initially confusing navigation, setting up everything becomes very easy. 😁&lt;/p&gt;

&lt;p&gt;In my case, I just needed the auth service and some databases to store the user and the user's profile information. All my other databases will stay on AWS DynamoDb.&lt;/p&gt;

&lt;p&gt;So I added an email/PSW auth flow for MakersDiary with a post auth confirmation email. In the Supabase free plan, you can have up to 50.000 active users - a number that should be sufficient for most small startups. I would be thrilled to have such a large amount of active users for MakersDiary 😎.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//User sign up
async signUp(signUpObject: any) {
  return await this.supabase.auth.signUp({
    email: signUpObject.email,
    password: signUpObject.password,
    options: {
      data: {
       //Some meta data e.g.
       //first_login: true
      },
    },
  });

  return { data: data, error: error };
}

//User sign in
async signIn(email: string, password: string) {
    return await this.supabase.auth.signInWithPassword({
      email: email,
      password: password,
    });
}

//User sign out
async signOut() {
  const { error } = await this.supabase.auth.signOut();

  if (!error) {
    this._session = null;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Supabase supports Trigger functions for any database row manipulation. So you can trigger a DB script in &lt;a href="https://www.postgresql.org/docs/current/plpgsql.html" rel="noopener noreferrer"&gt;PostgreSQL Structured Query Language&lt;/a&gt; (PL/pgSQL) when e.g., a new user has been added or the profile of an existing user was updated.&lt;/p&gt;

&lt;p&gt;BTW: Supabase provides an easy way to create and customize HTML email templates for all types of emails. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9brihq6lua5wmfkneas4.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9brihq6lua5wmfkneas4.PNG" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem 2 - ✅ Almost solved&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Unlike AWS Cognito, Supabase supports all major social providers so that you can offer your users to sign in with any of them - with only a few minutes of setting up and a few lines of code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fui6k5287w0ihgawcj2p5.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fui6k5287w0ihgawcj2p5.PNG" alt="Image description" width="800" height="881"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async signInWithSocial(provider: string) {
    return await this.supabase.auth.signInWithOAuth({
      provider: 'twitter',
      options: {
        scopes:
          'tweet.read users.read offline.access tweet.write follows.read like.read like.write list.read list.write tweet.moderate.write',
        redirectTo: 'https://example.com/welcome',
      },
    });
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The little fly in the ointment was that Supabase hasn't supported Twitter Apiv2 for that long, so the use of it doesn't seem to be well documented or I just didn't find it in a short time.&lt;/p&gt;

&lt;p&gt;So the Twitter sign-in was working well, but I had problems getting all the information - Twitter Apiv2 accessToken, accessSecret and refreshToken - that were needed for my server to use later for making calls against that service.&lt;br&gt;
But I didn't mind that because my own implementation of the Twitter OAuth sign-in process was working well so I used that again. 😅&lt;/p&gt;

&lt;p&gt;But now I'm prepared for a future where MakersDiary can be accessed through several other social media providers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem 3 - ✅ Solved&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My third pain point was finding a storage solution where authenticated users can upload and access files and if necessary generate signed URLs to share them in public.&lt;/p&gt;

&lt;p&gt;Supabase allows you to store 1 GB of files for free, which should be enough space for the first profile images and project logos.&lt;br&gt;
I love how easy it is to store and update files, as well as generate public URLs from your client application with a few lines of code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//Upload avatar image
private async uploadAvatar(file, filepath) {
  return await this.supabase.storage
    .from('avatars')
    .upload(filepath, file, {
      cacheControl: '3600',
      // upsert is set to true, the file is overwritten if it exists
      upsert: true,
    });
}

//Download avatar image
private async downloadAvatar(filepath) {
  return await this.supabase.storage
    .from('avatars')
    .download(filepath);
}

//Creates public url
private async getPublicFileUrl(storage, path) {
  const { data } = this.supabase.storage.from(storage).getPublicUrl(path);
  return data.publicUrl;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I didn't go too deep into technical detail here because it would be beyond the scope of this article.&lt;/p&gt;

&lt;p&gt;I'm really happy with my decision to move from Cognito to &lt;a href="https://supabase.com/" rel="noopener noreferrer"&gt;Supabase&lt;/a&gt;. The new &lt;a href="https://makersdiary.com" rel="noopener noreferrer"&gt;MakersDiary&lt;/a&gt; auth process is easier for users and allows me to expand without putting more stress on myself - something I couldn't handle if the site's growth with Cognito and S3.&lt;/p&gt;

&lt;p&gt;Even if supabase is still at the very beginning of a great journey, it is already a very big help for small startups and side hustles. Next week the new &lt;a href="https://supabase.com/launch-week" rel="noopener noreferrer"&gt;release of Supabase will launch&lt;/a&gt; and I'm looking forward to which new great features will be added. 🙂&lt;/p&gt;

&lt;p&gt;I hope that this post helped you understand how I solved the three main pain points of my project and made it better for everyone.&lt;br&gt;
If you have any feedback or questions, please let me know in the comments!&lt;/p&gt;

&lt;p&gt;Special thanks to Kevin Grüneberg for his help in troubleshooting my first attempts at creating PL/pgSQL scripts. 😁💜&lt;/p&gt;

</description>
      <category>ai</category>
      <category>learning</category>
    </item>
  </channel>
</rss>
