<?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>DEV Community: Leonidas Costas</title>
    <description>The latest articles on DEV Community by Leonidas Costas (@leonidascostas).</description>
    <link>https://dev.to/leonidascostas</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%2F597969%2F85ff3fee-8a97-42e5-b2a3-537d85baebac.png</url>
      <title>DEV Community: Leonidas Costas</title>
      <link>https://dev.to/leonidascostas</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/leonidascostas"/>
    <language>en</language>
    <item>
      <title>Delayed and scheduled payments with Stripe</title>
      <dc:creator>Leonidas Costas</dc:creator>
      <pubDate>Fri, 03 Sep 2021 14:24:56 +0000</pubDate>
      <link>https://dev.to/leonidascostas/delayed-and-scheduled-payments-in-your-web-app-1mm8</link>
      <guid>https://dev.to/leonidascostas/delayed-and-scheduled-payments-in-your-web-app-1mm8</guid>
      <description>&lt;p&gt;Hi Sparta!&lt;/p&gt;

&lt;p&gt;In this article I will share with you &lt;strong&gt;how to execute delayed or scheduled payments&lt;/strong&gt; in your React and NestJS app 💳&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The full source code and the documentation is available &lt;a href="https://github.com/arthurPrvst/credit-card-saving-stripe"&gt;on GitHub&lt;/a&gt; or &lt;a href="https://fast-modular-project.com/modules/reactjs-nestjs-stripe-card-saving"&gt;on FMP&lt;/a&gt;&lt;/strong&gt; 🙂&lt;/p&gt;

&lt;p&gt;This payment module will be added top of the React/Node/MySQL starter. This starter has already been presented to you in &lt;a href="https://dev.to/fastmodularproject/web-starter-react-nestjs-mysql-3o9i"&gt;this article&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  How does it work ?
&lt;/h1&gt;

&lt;p&gt;We'll use Stripe API in order to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1. Save customer's payment credentials&lt;/li&gt;
&lt;li&gt;2. Execute an offline payment when we want (by triggering the backend from a UI in the front, by adding a cron in the backend...).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the first step, we'll use Stripe's &lt;code&gt;SetupIntent&lt;/code&gt; that are meant to save credit card info that can be later used as we wish.&lt;/p&gt;

&lt;p&gt;For the second step, we'll use Stripe's &lt;code&gt;PaymentIntent&lt;/code&gt; that are meant to execute a payment instantly.&lt;/p&gt;

&lt;h1&gt;
  
  
  High picture of the workflow
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;1. User loads the page where he can save it's card.&lt;/li&gt;
&lt;li&gt;2. Frontend asks backend to create a Stripe &lt;code&gt;SetupIntent&lt;/code&gt; in order to let the user save it's payment credentials.&lt;/li&gt;
&lt;li&gt;3. Backend creates the &lt;code&gt;SetupIntent&lt;/code&gt; and returns the corresponding &lt;code&gt;one time secret&lt;/code&gt; to the frontend.&lt;/li&gt;
&lt;li&gt;4. User fills all info about it's card (number, CVV...) and does the 3DS authentication if needed. He press the "save my card" buttton.&lt;/li&gt;
&lt;li&gt;5. Backend is receiving several notifications about the &lt;code&gt;SetupIntent&lt;/code&gt; status thanks to a &lt;code&gt;Webhook&lt;/code&gt;. It saves all payment status in database as logs records.&lt;/li&gt;
&lt;li&gt;6. If the &lt;code&gt;SetupIntent&lt;/code&gt; has a correct status (received from the webhook), the &lt;code&gt;stripeCustomer&lt;/code&gt; is saved in database in the &lt;code&gt;User&lt;/code&gt; table (so we can retrieve all it's card info later).&lt;/li&gt;
&lt;li&gt;7. When you then want to trigger an offline payment for this user, backend only needs to ask stripe all card infos for this particular &lt;code&gt;stripeCustomer&lt;/code&gt;. It then triggers a &lt;code&gt;PaymentIntent&lt;/code&gt; with all infos previously retrieved, and... TADA ! The delayed payment is done 🎉&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Step by step guide
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Step 1 - Backend
&lt;/h3&gt;

&lt;p&gt;Add folder &lt;code&gt;backend/stripe&lt;/code&gt; in your &lt;code&gt;backend/src/api&lt;/code&gt;.&lt;br&gt;
Don't forget to add &lt;code&gt;StripeModule&lt;/code&gt; in the imports of the &lt;code&gt;app.module&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Add folder &lt;code&gt;backend/payment&lt;/code&gt; in your &lt;code&gt;backend/src/api&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Don't forget to add &lt;code&gt;PaymentModule&lt;/code&gt; in the imports of the &lt;code&gt;app.module&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the backend folder, install following dependency:&lt;br&gt;
&lt;code&gt;npm install stripe@8.132.0&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 2 - Frontend
&lt;/h3&gt;

&lt;p&gt;Add folder &lt;code&gt;frontend/screenExample&lt;/code&gt; in your &lt;code&gt;frontend/src/pages&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Add following code in pages.navigation.tsx :&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;Route exact path="/example" component={PaymentSiScreen}/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add folder &lt;code&gt;frontend/services/stripe.service.ts&lt;/code&gt; in your &lt;code&gt;frontend/services&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the frontend folder, install following dependency:&lt;br&gt;
&lt;code&gt;npm install @stripe/stripe-js@1.11.0&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 3 - Stripe credentials
&lt;/h3&gt;

&lt;p&gt;Backend:&lt;br&gt;
Update &lt;code&gt;stripeSecretKey&lt;/code&gt; in &lt;code&gt;StripeController&lt;/code&gt; and &lt;code&gt;StripeService&lt;/code&gt;  with the secretKey from your stripe account.&lt;/p&gt;

&lt;p&gt;Frontend:&lt;br&gt;
Add stripe public key in &lt;code&gt;PaymentSiScreen&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    stripeSecretKey: "pk_test_XxxXXXXxXXXXXXXxXXxxxxxXxxXXXXxXXXXXXXxXXxxxxxXxxXXXXxXXXXXXXxXXxxxxxXxxXXXXxXXXXXXXxXXxxxxx"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4 - Stripe webhook
&lt;/h3&gt;

&lt;p&gt;In your Stripe account, create a webhook and publish it to production. Your webhook setup will need following events:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;setup_intent.created&lt;/li&gt;
&lt;li&gt;setup_intent.requires_action&lt;/li&gt;
&lt;li&gt;setup_intent.canceled&lt;/li&gt;
&lt;li&gt;setup_intent.setup_failed&lt;/li&gt;
&lt;li&gt;setup_intent.succeeded&lt;/li&gt;
&lt;li&gt;payment_intent.created&lt;/li&gt;
&lt;li&gt;payment_intent.requires_action&lt;/li&gt;
&lt;li&gt;payment_intent.requires_capture&lt;/li&gt;
&lt;li&gt;payment_intent.canceled&lt;/li&gt;
&lt;li&gt;payment_intent.payment_failed&lt;/li&gt;
&lt;li&gt;payment_intent.succeeded&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once published, you'll have a &lt;code&gt;webhookSecret&lt;/code&gt; available.&lt;br&gt;
You can now update &lt;code&gt;stripeWebhookSecretKey&lt;/code&gt; in &lt;code&gt;StripeService&lt;/code&gt; with this webhookSecret.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bonus
&lt;/h3&gt;

&lt;p&gt;If you want to contact your users when they correctly saved their card or when a delayed payment failed, you can use a mailer module and send mail in the webhook function in &lt;code&gt;stripe/stripe.service.ts&lt;/code&gt;. This other module is available &lt;a href="https://fast-modular-project.com/modules"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;I hope this module will help you ! Do not hesitate to &lt;strong&gt;pin and star on GitHub&lt;/strong&gt; if you appreciated the article ❤️&lt;/p&gt;

&lt;p&gt;Links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The platform sharing the starter and it's modules: &lt;a href="https://fast-modular-project.com"&gt;Fast Modular Project&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Module "Delayed and scheduled payments" on &lt;a href="https://github.com/arthurPrvst/credit-card-saving-stripe"&gt;GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>payment</category>
      <category>stripe</category>
      <category>nestjs</category>
      <category>react</category>
    </item>
    <item>
      <title>Automatic Mail Campaign Creation with Mailjet</title>
      <dc:creator>Leonidas Costas</dc:creator>
      <pubDate>Thu, 02 Sep 2021 14:37:57 +0000</pubDate>
      <link>https://dev.to/leonidascostas/automatic-mailjet-campaign-creation-1d6k</link>
      <guid>https://dev.to/leonidascostas/automatic-mailjet-campaign-creation-1d6k</guid>
      <description>&lt;p&gt;Hi Sparta!&lt;/p&gt;

&lt;p&gt;In this article I will share with you &lt;strong&gt;how to create marketing campaigns, newsletters... automatically&lt;/strong&gt; in your NestJS backend 💌&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The full source code and the documentation is available &lt;a href="https://github.com/arthurPrvst/automatic-campaign-mailjet"&gt;on GitHub&lt;/a&gt; or &lt;a href="https://fast-modular-project.com/modules/automatic-campaign-creation-mailjet"&gt;on FMP&lt;/a&gt;&lt;/strong&gt; 🙂&lt;/p&gt;

&lt;p&gt;This newsletter / marketing campaign module will be added top of the React/Node/MySQL starter. This starter has already been presented to you in &lt;a href="https://dev.to/fastmodularproject/web-starter-react-nestjs-mysql-3o9i"&gt;this article&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  How does it work ?
&lt;/h1&gt;

&lt;p&gt;We'll use Mailjet's API in order to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a "Contact" for every user of your app&lt;/li&gt;
&lt;li&gt;Add them to an already existing ContactList created on Mailjet side&lt;/li&gt;
&lt;li&gt;Update their metadatas (whether or not their profil are verified)&lt;/li&gt;
&lt;li&gt;Create campaign draft&lt;/li&gt;
&lt;li&gt;Send a test mail to a dev adress in order to preview the futur campaign that will be sent&lt;/li&gt;
&lt;li&gt;Schedule the campaign for all user's missing the verification of their profil&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  High picture of the workflow
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;A user sign up to your web app.&lt;/li&gt;
&lt;li&gt;A user is created in databse and on Mailjet side as a "Contact" (name, email, hasVerifiedProfil)&lt;/li&gt;
&lt;li&gt;Every day a 6pm05 we generate automatically a campaign draft to ask for the verification of their account (for user's who haven't done it before).&lt;/li&gt;
&lt;li&gt;The campaign is scheduled for 6pm35.&lt;/li&gt;
&lt;li&gt;The draft is sent to you, in order to verify their is no issue in content that will be sent to your user. If an issue occurs, you can delete the scheduled campaign in your Mailjet account. You could then retrigger the campaign generation with Postman once the content is corrected.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Step by step guide
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;1 - Account creation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create a MailJet account &lt;a href="https://fr.mailjet.com"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Step 2 - Install mailjet dependency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Install the &lt;code&gt;node-mailjet&lt;/code&gt; dependency in the &lt;code&gt;backend&lt;/code&gt; directory of your project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install node-mailjet@3.3.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Step 3 - Mailjet credentials&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add your mailjet API credentials in your environments files (DEV, STAGING &amp;amp; PROD) found in the &lt;code&gt;backend/src/environments&lt;/code&gt; directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const environment = {
  ...,
  mailjet: {
    apiKey: '%YOUR_API_KEY%',
    secretKey: '%YOUR_SECRET_KEY%',
    contactListID: TODO_LATER,
  },
  ...
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your credentials can be found using &lt;a href="https://app.mailjet.com/account/api_keys"&gt;this link&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Step 4 - Contact lists config
Create two contact lists in your Mailjet account. One will be used in dev env &lt;code&gt;mylist_dev&lt;/code&gt; and the other one will be used for production &lt;code&gt;mylist_prod&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To do so, in your Mailjet account : "Contact" &amp;gt; "Contact List" &amp;gt; "Create a contact a list".&lt;/p&gt;

&lt;p&gt;Properties of your user should contains at least "email" (string), "name" (string) and hasVerified (boolean).&lt;/p&gt;

&lt;p&gt;Once created, the the contactListID in &lt;code&gt;backend/src/environments&lt;/code&gt; in the mailjet config.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Step 5 - Segment config&lt;br&gt;
A segment is a subset of contacts from a contact list that matchs your condition on the metadatas of the contact.&lt;br&gt;
In our case, we'll create a segment "verification_not_done" that will contains all contact from &lt;code&gt;mylist_prod&lt;/code&gt; having &lt;code&gt;hasVerified&lt;/code&gt; properties equal to &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Step 6 - Mail template config&lt;br&gt;
Create your campaign template with your Mailjet account : "Models" &amp;gt; "My Marketing Models" &amp;gt; "Create a new model". &lt;br&gt;
Once created, copy the ID of the template and set it as value of &lt;code&gt;ACCOUNT_VERIFICATION_TEMPLATE&lt;/code&gt; in &lt;code&gt;campaign-templates.enum.ts&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 7 - Back
&lt;/h3&gt;

&lt;p&gt;Add folder &lt;code&gt;backend/campaign&lt;/code&gt; in your &lt;code&gt;backend/src/api&lt;/code&gt;. &lt;br&gt;
Don't forget to add &lt;code&gt;CampaignModule&lt;/code&gt; in the imports of the &lt;code&gt;app.module&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Add folder &lt;code&gt;backend/mailer&lt;/code&gt; in your &lt;code&gt;backend/src/shared&lt;/code&gt;. &lt;br&gt;
Don't forget to add &lt;code&gt;MailerModule&lt;/code&gt; in the imports of the &lt;code&gt;app.module&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 8 - Contact creation on sign up
&lt;/h3&gt;

&lt;p&gt;When your user sign up, you should create a contact on mailjet side.&lt;/p&gt;

&lt;p&gt;To do so, in file &lt;code&gt;backend/src/api/auth.controller.ts&lt;/code&gt; add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { MailerService } from '../../shared/mailer/mailer.service';

...

    @Post('signup')
    async signUp(@Body() createUserDto: CreateUserDto): Promise&amp;lt;{ success: boolean, token?: string, id?: number }&amp;gt; {

        ...

        const mailjetContact = await this.mailService.createContact(user);

        if (mailjetContact.body.Data[0].ID) {
            console.log("Mailjet contactID", mailjetContact.body.Data[0].ID);
            await this.mailService.addContactToContactList(mailjetContact.body.Data[0].ID);

            await this.usersService.update(user, { contactId: mailjetContact.body.Data[0].ID });
            await this.mailService.updateDefaultContactMetadatas(mailjetContact.body.Data[0].ID, createUserDto.firstname);
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can then verify in your contactList on your mailjet acccount the new user created on sign up.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 9 - Automatic campaign creation
&lt;/h3&gt;

&lt;p&gt;Every friday at 6pm05, your campaign will be created, and scheduled at 6pm35 on all users that did not verify their account.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    // Every friday at 6pm05
    @Cron('0 5 18 * * 5', {
        name: 'sendMarketingCampaignVerifyAccount',
        timeZone: 'Europe/Paris',
    })
    async sendMarketingCampaignVerifyAccount() {
        ...
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To make the &lt;a href="https://docs.nestjs.com/techniques/task-scheduling"&gt;NestJS cron&lt;/a&gt; work, please install following dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    npm install --save @nestjs/schedule
    npm install --save-dev @types/cron
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Bonus
&lt;/h3&gt;

&lt;p&gt;To avoid any issue being categorized as "SPAM" you should configure the SPF and DKIM configuration for your sending mail address and your domain : Mailjet profil &amp;gt; "Preferences" &amp;gt; "Domains" &amp;gt; "DKIM/SPF authentication".&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;I hope this module will help you ! Do not hesitate to &lt;strong&gt;pin and star on GitHub&lt;/strong&gt; if you appreciated the article ❤️&lt;/p&gt;

&lt;p&gt;Links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The platform sharing the starter and it's modules: &lt;a href="https://fast-modular-project.com"&gt;Fast Modular Project&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Module "Automatic campaign Mailjet" on &lt;a href="https://github.com/arthurPrvst/automatic-campaign-mailjet"&gt;GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>newsletter</category>
      <category>mailjet</category>
      <category>campaign</category>
      <category>nestjs</category>
    </item>
    <item>
      <title>User's location by browser's permission or IP address</title>
      <dc:creator>Leonidas Costas</dc:creator>
      <pubDate>Fri, 28 May 2021 16:14:43 +0000</pubDate>
      <link>https://dev.to/leonidascostas/get-user-s-location-in-your-app-486a</link>
      <guid>https://dev.to/leonidascostas/get-user-s-location-in-your-app-486a</guid>
      <description>&lt;p&gt;This module allows you to locate your user either by navigator permission, either by IP address.&lt;/p&gt;

&lt;h1&gt;
  
  
  What does it bring?
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;(For the browser solution) Navigator permission ask&lt;/li&gt;
&lt;li&gt;(For the browser solution) Navigator coordinate ask&lt;/li&gt;
&lt;li&gt;(For the IP solution) Retrieving of IP address in the backend&lt;/li&gt;
&lt;li&gt;(For the IP solution) Calls to ip-api.com service in order to get the location of a specific IP&lt;/li&gt;
&lt;li&gt;3 hours of work saved &lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Prerequisites
&lt;/h1&gt;

&lt;p&gt;To make this module work, a 13€/month subscription to &lt;code&gt;ip-api&lt;/code&gt; service is needed.&lt;/p&gt;

&lt;h1&gt;
  
  
  Retrieving user’s location with it’s IP address and IP-API
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Step 1
&lt;/h3&gt;

&lt;p&gt;We’ll store user’s IP address present in the « x-forwarded-for » field from the HTTP header of its request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;request.ipAddress = request?.headers['x-forwarded-for']?.split(',')[0] || request.connection.remoteAddress
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ip address is now accessible through request.ipAddress, but we’ll create a custom decorator to ease the retrieve of it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2
&lt;/h3&gt;

&lt;p&gt;Create a custom decorator to get the ipAdress using a decorator instead of accessing directly &lt;code&gt;request.ipAddress&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { createParamDecorator, ExecutionContext } from '@nestjs/common';

export const IpAddress = createParamDecorator(
    (data: unknown, ctx: ExecutionContext) =&amp;gt; {
        const request = ctx.switchToHttp().getRequest();
        return request.ipAddress;
    },
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3
&lt;/h3&gt;

&lt;p&gt;Create a Controller that uses this custom decorator&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4
&lt;/h3&gt;

&lt;p&gt;In your controller, use your service that gets users latitude and longitude from it’s IP (using ip-api service).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        const headers = {
            Accept: "application/json",
            "Content-Type": "application/json"
        };
        const res = await fetch(`https://pro.ip-api.com/json/${ip}?key=[ENTER YOUR KEY HERE]`, {
            method: "get",
            headers
        });
        const json = await res.json();
        return {
            latitude: json.lat,
            longitude: json.lon
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Retrieving user’s location with navigator permissions
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Step 1
&lt;/h3&gt;

&lt;p&gt;You can use the &lt;a href="https://developer.mozilla.org/fr/docs/Web/API/Navigator"&gt;navigator web api standards&lt;/a&gt; to tell the browser to ask for the user to authorize thee usage of it’s location.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const getGeolocationPermission = async () =&amp;gt; {
    const permission = await navigator.permissions.query({
        name: "geolocation"
    });
    return permission.state;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2
&lt;/h3&gt;

&lt;p&gt;If the user accepted the prompt, you’ll be able to ask the navigator for its latitude and longitude with the &lt;code&gt;navigator.geolocation.getCurrentPosition()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The entire source code and a distance computation between two locations are available &lt;a href="https://fast-modular-project.com/modules/location-by-ip-and-navigator"&gt;here&lt;/a&gt;&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;You are now free to use those two methods as a way to retrieve user’s location:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;either thanks to it’s IP address&lt;/li&gt;
&lt;li&gt;either through it’s browser&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;I hope this module will help you saving some time while trying to implement a system to retrieve the location of your users.&lt;br&gt;
If you have any question, I'll be present as usual in the comment section !&lt;/p&gt;

&lt;p&gt;Links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The platform sharing the starter and it's modules : &lt;a href="https://fast-modular-project.com"&gt;Fast Modular Project&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;User's location module open source code &lt;a href="https://fast-modular-project.com/modules/location-by-ip-and-navigator"&gt;here.&lt;/a&gt;
Do not hesitate to pin and like if you appreciated the article ❤️&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>react</category>
      <category>node</category>
      <category>opensource</category>
    </item>
    <item>
      <title>SEO and multilingual web app with distinct URLs</title>
      <dc:creator>Leonidas Costas</dc:creator>
      <pubDate>Sun, 16 May 2021 09:03:19 +0000</pubDate>
      <link>https://dev.to/leonidascostas/seo-and-multilingual-web-app-3mjb</link>
      <guid>https://dev.to/leonidascostas/seo-and-multilingual-web-app-3mjb</guid>
      <description>&lt;p&gt;I’ll present you in this article how to have a SEO friendly multilingual web app.&lt;/p&gt;

&lt;p&gt;If you want to have worldwide users using your web application, you are at the right place.&lt;/p&gt;

&lt;p&gt;As you may know, Google won’t display your website in France if it is written in Russian. Obviously, you’ll need to translate all the pages of your web application for each country targeted. But this is not enough, and here is why I decided to write this article 😃&lt;/p&gt;

&lt;p&gt;Even if you have multiple languages available on your website, you must notify Google that you have them. &lt;/p&gt;

&lt;p&gt;How ? We’ll see how to use &lt;strong&gt;distinct URLs&lt;/strong&gt; and &lt;strong&gt;Hreflang tags&lt;/strong&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Prerequisites
&lt;/h1&gt;

&lt;p&gt;You can use this module to learn how SEO works for multilingual website, or just to copy past it in your project to improve your SEO direclty.&lt;/p&gt;

&lt;h1&gt;
  
  
  Stay SEO friendly
&lt;/h1&gt;

&lt;p&gt;The common solution to translate a web app is to store user’s language in a local storage or a cookie in the browser/device. &lt;/p&gt;

&lt;p&gt;This is correct but not SEO friendly at all as Google can't know that you have multiple languages 😢&lt;br&gt;
Indeed, the Google bot gets your pages through a &lt;code&gt;curl&lt;/code&gt; command, and does not have any local storage or cookies.&lt;/p&gt;

&lt;h2&gt;
  
  
  use distincts URLs!
&lt;/h2&gt;

&lt;p&gt;And… distincts URLs comes to the rescue!&lt;/p&gt;

&lt;p&gt;You can use them to distinguish your translated pages by: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;domain&lt;/li&gt;
&lt;li&gt;subdomain&lt;/li&gt;
&lt;li&gt;extension&lt;/li&gt;
&lt;li&gt;repertory&lt;/li&gt;
&lt;li&gt;query&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As examples, Twitter uses queries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;https://www.twitter.com?lang=en&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;https://www.twitter.com?lang=fr&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and Wikipedia uses subdomains: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;https://en.wikipedia.org/wiki/LinkedIn&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;https://fr.wikipedia.org/wiki/LinkedIn&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Choose the one you prefer, the important point here is to have different URLs 😃&lt;/p&gt;

&lt;h1&gt;
  
  
  use hreflang!
&lt;/h1&gt;

&lt;p&gt;Hreflang tags are used to specify all the translations available for a page.&lt;br&gt;
It helps Google to understand that your apps has several languages, in addition to the distinct URLs you set up.&lt;/p&gt;

&lt;p&gt;The theoretical part is now over, we can move on to the funny part, the implementation 😊&lt;br&gt;
For this part, as it’s more code oriented, everything is available &lt;strong&gt;&lt;a href="https://fast-modular-project.com/modules/multilingual-seo-optimisation-hreflang"&gt;here&lt;/a&gt; and on GitHub&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It gives: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the setup of the React router according to your distinct URLs&lt;/li&gt;
&lt;li&gt;utils functions&lt;/li&gt;
&lt;li&gt;the setup of &lt;code&gt;hreflang&lt;/code&gt; tags with &lt;code&gt;react-helmet&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Hope you enjoyed the article, do not hesitate to ask if you have any question on the theoretical part or on the implemation steps. I’ll be in the comment section as usual.&lt;/p&gt;

&lt;p&gt;Pin &amp;amp; like if you enjoyed this article ! ❤️&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>opensource</category>
      <category>seo</category>
    </item>
    <item>
      <title>Scalable Websockets with AWS API Gateway and AWS Lambda</title>
      <dc:creator>Leonidas Costas</dc:creator>
      <pubDate>Fri, 30 Apr 2021 15:52:22 +0000</pubDate>
      <link>https://dev.to/leonidascostas/scalable-websockets-with-aws-api-gateway-and-aws-lambda-3gke</link>
      <guid>https://dev.to/leonidascostas/scalable-websockets-with-aws-api-gateway-and-aws-lambda-3gke</guid>
      <description>&lt;p&gt;Hi Sparta!&lt;/p&gt;

&lt;p&gt;In this article I will share with you how to add scalable websockets system in your app with AWS API Gateway and AWS Lambda. Websockets are used to implement any real time system in like a chat or a notification system.&lt;/p&gt;

&lt;p&gt;Please note that AWS is not mandatory to implement simple websockets, but it gives us the scalability we are looking for if we are dealing with an app with thousands of users.&lt;/p&gt;

&lt;p&gt;On my side, I used this module on top of the React/Node/MySQL starter. This starter has already been presented to you in &lt;a href="https://dev.to/fastmodularproject/web-starter-react-nestjs-mysql-3o9i"&gt;this article&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  What does it bring?
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Open source code&lt;/li&gt;
&lt;li&gt;Documentation and "Quick Start"&lt;/li&gt;
&lt;li&gt;Complete integration of websockets in your React / NestJS / MySQL starter (it can be easily adapted to a node backend)&lt;/li&gt;
&lt;li&gt;AWS Lambda functions source code&lt;/li&gt;
&lt;li&gt;20 hours of work saved :D&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Prerequisite
&lt;/h1&gt;

&lt;p&gt;By getting the code &lt;a href="https://fast-modular-project.com/modules/websocket-apigateway-aws-lambda"&gt;here&lt;/a&gt;, you'll have the websockets already integrated in the web starter. You'll get a functional project with an authentication and a websocket system in less than 20 minutes :D&lt;/p&gt;

&lt;p&gt;Note that using the starter is not mandatory, you can also use the module as standalone. The integration won't be as easy as with the starter, but it should still be simple to integrate it in your already created project :)&lt;/p&gt;

&lt;h1&gt;
  
  
  Websockets in 3 words
&lt;/h1&gt;

&lt;p&gt;With a standard (REST/SOAP) API, frontend sends information to the server and get a proper answer. This is enough most of the time but it means that the frontend/user need to perform an action to get up to date datas.&lt;/p&gt;

&lt;p&gt;Let's imagine a chat where users would have to press a "refresh button" to get new messages displayed... this would be quite annoying. Websockets come to the rescue ! &lt;/p&gt;

&lt;p&gt;Websocket is a bidirectional connection that you initiate between a server and a client. This connection allows the frontend to speak to the server and vice-versa without any call to an API. If we take back the example of the chat, websockets allow the server to say to the user that he has a new message (without any action from him).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The entire open source code and a step by step integration on the starter is available&lt;/strong&gt; &lt;a href="https://fast-modular-project.com/modules/websocket-apigateway-aws-lambda"&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  High level picture of the workflow
&lt;/h1&gt;

&lt;p&gt;The websocket connection will be setup between the client (browser or mobile app) and API Gateway (for sockets). We could have established a websocket connection directly with the backend but this could lead to a shutdown of your API if your server can't scale and if there is too many connections to be maintained. Thanks to API Gateway, the sockets will be handle in a separated server that can scale, independently from your back server.&lt;/p&gt;

&lt;p&gt;1) &lt;strong&gt;User logs in&lt;/strong&gt;. He initializes a websocket connection with the API Gateway. The API generates a unique identifier of this connection: &lt;code&gt;connectionId&lt;/code&gt;. Once the connection is established, frontend send to the API Gateway (with the socket created) a "connected event". The AWS Lambda that handle the "websocket connection flow" calls our backend endpoint to link this user with this &lt;code&gt;connectionId&lt;/code&gt; in our database. The backend saves this infos. For every users connected on our app, we now have one or several &lt;code&gt;connectionId&lt;/code&gt; associated.&lt;/p&gt;

&lt;p&gt;2) &lt;strong&gt;The backend want to send an event to users&lt;/strong&gt;. For all users, it get their connectionId and ask the API Gateway to send a message to the websocket identified by this &lt;code&gt;connectionId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;3) &lt;strong&gt;Users receive the event&lt;/strong&gt; (without any call to the backend) and adapt their frontend accordingly.&lt;/p&gt;

&lt;p&gt;4) &lt;strong&gt;A user logs out&lt;/strong&gt;. This closes the websocket, and notify the API Gateway with a "disconnected event". The AWS Lambda that handle the "websocket disconnection flow" calls our backend endpoint to delete the link between this user and the &lt;code&gt;connectionId&lt;/code&gt; in our database. The backend saves this infos.&lt;/p&gt;

&lt;h1&gt;
  
  
  Configure your AWS API Gateway
&lt;/h1&gt;

&lt;p&gt;1) Create an &lt;a href="https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-overview-developer-experience.html#api-gateway-overview-websocket"&gt;API Gateway (for sockets)&lt;/a&gt; with all default parameters &lt;br&gt;
Add 2 routes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;auth&lt;/code&gt;: will be called from the frontend when we receive a new connection&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$disconnect&lt;/code&gt;: will be called from the frontend when we receive connection closing event&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2) Set your API Gateway credentials in the environments variables of your backend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    ...
    apiGateway: {
      endpoint:
        'https://xxxxxxx.execute-api.eu-west-3.amazonaws.com/env',
      accessKeyId: 'XXXXXXXXXXXXXXXXXX',
      secretAccessKey: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
      region: 'eu-west-3',
    },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3) Set your API Gateway endpoint in the environments variables of your frontend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;socketUrl: "wss://XXXXXXXX.execute-api.eu-west-3.amazonaws.com/env"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Configure your AWS Lambdas
&lt;/h1&gt;

&lt;p&gt;1) Setup the "Connection flow" with AWS Lambda.&lt;br&gt;
Create an AWS Lambda anted &lt;code&gt;websocket-connection&lt;/code&gt; and plug it to the &lt;code&gt;auth route&lt;/code&gt; of the API Gateway. &lt;/p&gt;

&lt;p&gt;In the code of this lambda you should call a backend endpoint we'll create soon. This endpoint will be in charge of saving in database the connectionId of the websocket the user just connected too. Please check &lt;a href="https://fast-modular-project.com/modules/websocket-apigateway-aws-lambda"&gt;here&lt;/a&gt; to copy paste the code for this lambda :)&lt;/p&gt;

&lt;p&gt;2) Setup the "Disconnection" flow with AWS Lambda.&lt;br&gt;
Create an AWS Lambda anted &lt;code&gt;websocket-disconnection&lt;/code&gt; and plug it to the &lt;code&gt;$disconnect route&lt;/code&gt; of the API Gateway. &lt;/p&gt;

&lt;p&gt;In the code of this lambda you should call a backend endpoint we'll create soon. This endpoint will be in charge of deleting the association between a user and a connectionId in our database. Please check &lt;a href="https://fast-modular-project.com/modules/websocket-apigateway-aws-lambda"&gt;here&lt;/a&gt; to copy paste the code for this lambda :)&lt;/p&gt;
&lt;h1&gt;
  
  
  Setup the websockets in your React frontend
&lt;/h1&gt;

&lt;p&gt;1) Install following package&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm i reconnecting-websocket@4.4.0&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;2) Init your websocket connection with the API Gateway Socket when the user is connected.&lt;/p&gt;

&lt;p&gt;You should establish the connection with the API Gateway thanks to the endpoint stored in your environment variable previously:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        let ws = new ReconnectingWebSocket(
            environment.socketUrl, [], {
            minReconnectionDelay: 500,
            maxReconnectionDelay: 500,
            reconnectionDelayGrowFactor: 1
        });
        ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should of course implement:&lt;br&gt;
&lt;code&gt;ws.onopen&lt;/code&gt; method: to define &lt;a href="https://fast-modular-project.com/modules/websocket-apigateway-aws-lambda"&gt;what to do when a connection is created&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ws.onmessage&lt;/code&gt; method: to define &lt;a href="https://fast-modular-project.com/modules/websocket-apigateway-aws-lambda"&gt;what to do when receiving a new message&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ws.onclose&lt;/code&gt; method: to define &lt;a href="https://fast-modular-project.com/modules/websocket-apigateway-aws-lambda"&gt;what to do when a connection is closed&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;3) Close the connection when he is loging out: &lt;code&gt;ws.close();&lt;/code&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Prepare our NestJS backend for websockets
&lt;/h1&gt;

&lt;p&gt;1) Create a new NestJS module &lt;code&gt;SocketConnectionsModule&lt;/code&gt; to manage websockets connections. Do not forget to add it to the import section of your &lt;code&gt;app.module&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Our &lt;code&gt;SocketConnectionEntity&lt;/code&gt; will associate a &lt;code&gt;connectionId&lt;/code&gt; to a &lt;code&gt;User&lt;/code&gt;. A user can have several websockets connections as he may be connected to your app through several browsers or with a mobile application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Entity('users')
export class UserEntity implements User {
    ...
    @OneToMany(type =&amp;gt; SocketConnectionEntity, socketConnection =&amp;gt; socketConnection.user)
    socketConnections: SocketConnectionEntity[];
    ...
}
&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;@Entity('socket_connection')
export class SocketConnectionEntity implements SocketConnection {
    @PrimaryGeneratedColumn()
    id: number;

    @Column({ name: "connection_id" })
    connectionId: string;

    @ManyToOne(() =&amp;gt; UserEntity, user =&amp;gt; user.socketConnections, { onDelete: 'CASCADE' })
    @JoinColumn({ name: "user_id" })
    user: User;

    @Column({ type: "datetime", default: () =&amp;gt; "CURRENT_TIMESTAMP" })
    timestamp: Date;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The controller and the service will let us create, get or delete user's connection in database (the &lt;code&gt;SocketConnectionEntity&lt;/code&gt; we just created). Those two endpoints are used by the AWS Lambdas we created previously.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Controller('socket-connections')
export class SocketConnectionsController {

    constructor(private socketConnectionService: SocketConnectionsService) { }

    @Post()
    @Roles('user', 'premium', 'admin')
    async create(@Body() body, @AuthUser() user) {
        return await this.socketConnectionService.create(user, body.connectionId);
    }

    @Delete(':connectionId')
    async delete(@Param() param) {
        return await this.socketConnectionService.deleteConnection(param.connectionId);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2) Create a &lt;code&gt;SocketService&lt;/code&gt; to ask the API Gateway to send a message to a specific &lt;code&gt;connectionId&lt;/code&gt;. Do not forget to import the was sdk &lt;code&gt;import { ApiGatewayManagementApi } from 'aws-sdk';&lt;/code&gt; and create your &lt;code&gt;awsGW&lt;/code&gt; object with your API Gateway credentials stored previously in your environment variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    async sendMessage(userId, data) {
        const connections = await this.socketConnectionService.getUserConnections(userId);

        for (const connection of connections) {
            console.log("Socket post to : ", connection.connectionId);
            this.awsGW.postToConnection({
                ConnectionId: connection.connectionId,
                Data: JSON.stringify(data)
            }, async (err, success) =&amp;gt; {
                if (err) {
                    if (!err.retryable) {
                        // Socket id is disabled
                        await this.socketConnectionService.deleteConnection(connection.connectionId);
                    }
                }
            });
        }
    };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;I hope this module will help you saving some time while trying to implement websockets in your project. If you have any question, I'll be present as usual in the comment section !&lt;/p&gt;

&lt;p&gt;Links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The platform sharing the starter and it's modules : &lt;a href="https://fast-modular-project.com"&gt;Fast Modular Project&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Module "Websocket with API Gateway and AWS Lambda" repository &lt;a href="https://fast-modular-project.com/modules/websocket-apigateway-aws-lambda"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not hesitate to pin and like if you appreciated the article ❤️&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>node</category>
      <category>aws</category>
    </item>
    <item>
      <title>Add a Redis cache to your NestJS backend</title>
      <dc:creator>Leonidas Costas</dc:creator>
      <pubDate>Wed, 28 Apr 2021 14:53:19 +0000</pubDate>
      <link>https://dev.to/leonidascostas/add-a-redis-cache-to-your-nestjs-backend-aog</link>
      <guid>https://dev.to/leonidascostas/add-a-redis-cache-to-your-nestjs-backend-aog</guid>
      <description>&lt;p&gt;Hi Sparta!&lt;/p&gt;

&lt;p&gt;In this article I will share with you how to use Redis as scalable cache system in your NestJS backend. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The full source code and the documentation is available &lt;a href="https://fast-modular-project.com/modules/redis-cache-nest-js"&gt;here&lt;/a&gt;&lt;/strong&gt; 🙂&lt;/p&gt;

&lt;p&gt;This cache system module will be added top of the React/Node/MySQL starter. This starter has already been presented to you in &lt;a href="https://dev.to/fastmodularproject/web-starter-react-nestjs-mysql-3o9i"&gt;this article&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Redis in 3 words
&lt;/h1&gt;

&lt;p&gt;Redis is an open source in-memory data structure store, that can be used either as a &lt;strong&gt;cache&lt;/strong&gt;, either as a &lt;strong&gt;database&lt;/strong&gt;, or a &lt;strong&gt;message broker&lt;/strong&gt; (like JMS or RabbitMQ). Even in critical applications, Redis is used in production as it provides a high availability via the Redis Sentinels and a automatic partitioning thanks to the Redis Cluster.&lt;/p&gt;

&lt;h1&gt;
  
  
  Configure your NestJS backend to use Redis
&lt;/h1&gt;

&lt;p&gt;This section is an overhead on top for the &lt;a href="https://docs.nestjs.com/techniques/caching"&gt;official documentation&lt;/a&gt; from NestJS, to adapt it to the web starter.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You should install following packages:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install cache-manager
npm install cache-manager-redis-store
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;You should specify your backend environments variables:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    export const environment = {
        ...,
        redis: {
            host: process.env.LOCAL_IP,
            port: process.env.REDIS_PORT,
            defaultTtl: 86400
        }
    };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;You should now create a NestJS module &lt;code&gt;MyRedisCacheModule&lt;/code&gt; with it's service &lt;code&gt;MyRedisCacheService&lt;/code&gt; to interact with your cache through the &lt;code&gt;cache-manager&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;set&lt;/code&gt;: allows you to set a cached value.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;get&lt;/code&gt;: allows to retrieve the value (will be undefined when TTL expired).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;del&lt;/code&gt;: allows you to deleted a stored key.&lt;/p&gt;

&lt;p&gt;The controller and the service:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;gets a cached value in Redis&lt;/li&gt;
&lt;li&gt;stores a value in Redis&lt;/li&gt;
&lt;li&gt;deletes a stored key &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The controller and service are available &lt;a href="https://fast-modular-project.com/modules/redis-cache-nest-js"&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt; 🙂&lt;/p&gt;

&lt;h1&gt;
  
  
  Setup Redis for dev environment
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;The initial starter's &lt;code&gt;docker-compose&lt;/code&gt; file launches our local databases (with a volume attached), our backend and our frontend. We'll modify it to also launch a redis server locally when starting our web app with &lt;code&gt;docker-compose up&lt;/code&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services:
  db:
    ...

  back:
    ...

  cache:
    image: "redis:alpine"
    ports:
      - ${REDIS_PORT}:${REDIS_PORT}
    env_file: ./.env

  front:
    ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(optional) to specify a password for this service you can add &lt;code&gt;command: redis-server --requirepass yourpassword&lt;/code&gt; in the &lt;code&gt;docker-compose.yaml&lt;/code&gt; and add also the password in your backend &lt;code&gt;redisStore&lt;/code&gt;: &lt;code&gt;auth_pass: 'password'&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The environments variables in &lt;code&gt;.env&lt;/code&gt; are loaded by docker when launching your app with &lt;code&gt;docker-compose up&lt;/code&gt;. You'll to add to this file the redis port you wanna use:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
REDIS_PORT = 6379
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your redis cache system is now alive locally 🙂&lt;br&gt;
You can test the test endpoints created in last section with Postman!&lt;/p&gt;

&lt;p&gt;You want to use a cache system in production ? Let's jump to the next section.&lt;/p&gt;

&lt;h1&gt;
  
  
  Setup Redis for prod environment
&lt;/h1&gt;

&lt;p&gt;From your code point of view, you'll only need to adapt your environment variables to route to a production AWS ElastiCache. For your Redis instance, the non clustered mode should be enough if not dealing with a large volume of datas. The best documentation to be read for this step is the great one provided by &lt;a href="https://aws.amazon.com/fr/blogs/database/latency-reduction-of-hybrid-architectures-with-amazon-elasticache/"&gt;AWS for ElastiCache&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;I hope this module will help you saving some time while trying to optimize your backend performance with a Redis cache. If you have any question, I'll be present as usual in the comment section!&lt;/p&gt;

&lt;p&gt;Links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The platform sharing the starter and it's modules: &lt;a href="https://fast-modular-project.com"&gt;Fast Modular Project&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Module "Scalable caching system with Redis and NestJS" is available &lt;a href="https://fast-modular-project.com/modules/redis-cache-nest-js"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not hesitate to pin and like if you appreciated the article ❤️&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>node</category>
      <category>redis</category>
      <category>docker</category>
    </item>
    <item>
      <title>Upload files in your web app to an AWS S3 bucket</title>
      <dc:creator>Leonidas Costas</dc:creator>
      <pubDate>Thu, 22 Apr 2021 14:54:09 +0000</pubDate>
      <link>https://dev.to/leonidascostas/upload-files-to-amazon-s3-bucket-nf</link>
      <guid>https://dev.to/leonidascostas/upload-files-to-amazon-s3-bucket-nf</guid>
      <description>&lt;p&gt;Hi Sparta!&lt;/p&gt;

&lt;p&gt;In this article I will share with you a file storage module that can help you store your user's files (profil's pictures, PDF documents...) in your app with a scalable architecture. &lt;/p&gt;

&lt;p&gt;We could have stored all those data to a custom server, but AWS S3 buckets are giving us the scalability and I'll show you here how to use them.&lt;/p&gt;

&lt;p&gt;On my side, I used this module on top of the React/Node/MySQL starter. This starter has already been presented to you in &lt;a href="https://dev.to/fastmodularproject/web-starter-react-nestjs-mysql-3o9i"&gt;this article&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  What does it bring?
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Open source code&lt;/li&gt;
&lt;li&gt;Documentation and "Quick Start"&lt;/li&gt;
&lt;li&gt;Complete integration of the process in your React / NestJS (it can be easily adapted to a node backend)&lt;/li&gt;
&lt;li&gt;AWS S3 configurations&lt;/li&gt;
&lt;li&gt;5 hours of work saved :D&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Prerequisite
&lt;/h1&gt;

&lt;p&gt;By getting the web starter I was mentioning above, you'll be able to plug this file upload module directly on top of it and have a functional project with an authentication and a file storage in less than 20 minutes.&lt;/p&gt;

&lt;p&gt;Note that using the starter is not mandatory, you can also use the module as standalone. The integration won't be as easy as with the starter, but it should still be simple to integrate it in your already created project :)&lt;/p&gt;

&lt;p&gt;The starter is available &lt;a href="https://fast-modular-project.com/starters/starter-reacjs-nestjs-mysql"&gt;here&lt;/a&gt;.&lt;br&gt;
The module is available &lt;a href="https://fast-modular-project.com/modules/upload-to-S3-bucket"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  How does it work?
&lt;/h1&gt;

&lt;p&gt;The S3 buckets is a public cloud storage resource available in Amazon Web Services' (AWS). You can manually upload files into the bucket and you can, of course, do it programmatically. Here is the high picture workflow of the process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Frontend asks the backend for an URL where it can saves a given file.&lt;/li&gt;
&lt;li&gt;Backend ask with it's credentials AWS to get signed URL that can be used to upload a file, and returns its to the frontend.&lt;/li&gt;
&lt;li&gt;Frontend uses the URL to save the file to the bucket.&lt;/li&gt;
&lt;li&gt;(optional) Your frontend can ask your backend to save in database the URL where your image/file has been uploaded in order to display it in your app :) &lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Setup the file storage process
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Create your S3 bucket &lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/create-bucket-overview.html"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Get your credentials. Go to &lt;code&gt;IAM console&lt;/code&gt;, from the navigation menu click on &lt;code&gt;Users&lt;/code&gt;, select your user or create a new user, create an access key, get the &lt;code&gt;Key ID&lt;/code&gt; and the &lt;code&gt;Key secret&lt;/code&gt; and keep them in save place, we'll see them soon ;)&lt;/li&gt;
&lt;li&gt;Grant the permissions for your users to modify your bucket (grant right &lt;code&gt;AmazonS3FullAccess&lt;/code&gt;). &lt;code&gt;IAM&lt;/code&gt; &amp;gt; &lt;code&gt;Create autorisation&lt;/code&gt; &amp;gt; &lt;code&gt;S3&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add the CORS policy in &lt;code&gt;S3&lt;/code&gt; &amp;gt; &lt;code&gt;autorisations&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "PUT"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": [],
        "MaxAgeSeconds": 3000
    }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Authorize public access to your S3 bucket&lt;/li&gt;
&lt;li&gt;Add your environment variables in the backend using the credentials your get during the second step:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;s3: {
        url: "https://[bucket].s3.eu-west-3.amazonaws.com/userUploads",
        bucket: "[bucket]",
        region: "[region]",
        host: "s3.eu-west-3.amazonaws.com",
        accessKeyId: "XXXXXXXXXXXXXXXXXX",
        secretAccessKey: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Your backend can now ask AWS for a signed URL (and give it back to the frontend):
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install aws-sdk@2.799.0
&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;    async getS3Url(fileExtension: string): Promise&amp;lt;string&amp;gt; {
        let signedUrl = await this.s3.getSignedUrlPromise('putObject', {
            Bucket: this.configService.environment.s3.bucket,
            Key: `pictures/${uuid.v4()}.${fileExtension}`,
            ContentType: 'application/octet-stream',
            ACL: 'public-read',
            Expires: 604800
        });
        return signedUrl;
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Finally, the frontend can use the signedUrl to store a file:
&lt;/li&gt;
&lt;/ul&gt;

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

    const headersContent = {
        "Content-Type": file.type,
        Accept: "application/json"
    };
    const headers = new Headers(headersContent);
    const response = await fetch(
        new Request(signedUrl, {
            method: "PUT",
            body: file,
            headers
        })
    );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The entire tutorial and a step by step integration on the starter with an example screen is available &lt;a href="https://fast-modular-project.com/modules/upload-to-S3-bucket"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;I hope this module will help you saving your some time while trying save user's files in your project.&lt;br&gt;
If you have any question, I'll be present as usual in the comment section !&lt;/p&gt;

&lt;p&gt;Links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The platform sharing the starter and it's modules : &lt;a href="https://fast-modular-project.com"&gt;Fast Modular Project&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Module "File uploads to AWS S3" repository &lt;a href="https://fast-modular-project.com/modules/upload-to-S3-bucket"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not hesitate to pin and like if you appreciated the article ❤️&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>aws</category>
      <category>node</category>
    </item>
    <item>
      <title>Send mails with Mailjet from your React NestJS app in 10 min</title>
      <dc:creator>Leonidas Costas</dc:creator>
      <pubDate>Mon, 29 Mar 2021 14:05:38 +0000</pubDate>
      <link>https://dev.to/leonidascostas/send-mails-with-mailjet-from-your-nestjs-backend-in-10-min-2p6c</link>
      <guid>https://dev.to/leonidascostas/send-mails-with-mailjet-from-your-nestjs-backend-in-10-min-2p6c</guid>
      <description>&lt;p&gt;In this article I will share with you a module that sends mail to customers using MailJet. On my side, I used this module on top of the React/Node/MySQL starter. This starter has been presented to you last week in &lt;a href="https://dev.to/fastmodularproject/web-starter-react-nestjs-mysql-3o9i"&gt;this article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Maybe you are wondering... why using Mailjet ? Because it's free until 6000 mails/months and no credit card is required :D&lt;/p&gt;

&lt;h1&gt;
  
  
  Prerequisite
&lt;/h1&gt;

&lt;p&gt;By getting the web starter I was mentioning above, you'll be able to plug this mail system module directly on top of it and have a functional project with an authentication and a mail system in less than 10 minutes.&lt;/p&gt;

&lt;p&gt;Note that using the starter is not mandatory, you can also use the module as standalone. The integration won't be as easy as with the starter, but it should still be simple to integrate it in your already created project :)&lt;/p&gt;

&lt;p&gt;The starter is available &lt;a href="https://fast-modular-project.com"&gt;here&lt;/a&gt;.&lt;br&gt;
The module is available &lt;a href="https://fast-modular-project.com/modules/mailjet-mailing"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  How does it work?
&lt;/h1&gt;

&lt;p&gt;In this module, we'll use Mailjet service. We can configure mail templates on their website which will be identified by a unique &lt;code&gt;ID&lt;/code&gt;. Those templates can be filled with static content and dynamic content that will change for every mails (pretty usefull to set usernames or callback url on a button). &lt;/p&gt;

&lt;p&gt;The backend will call Mailjet API to sends mails giving :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;receiver&lt;/li&gt;
&lt;li&gt;template ID&lt;/li&gt;
&lt;li&gt;variables (dynamic data)&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Setup the mailing system
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Mailjet configuration&lt;br&gt;
Create a MailJet account. &lt;br&gt;
Create your mail transactional template and publish it. &lt;br&gt;
Keep the &lt;code&gt;ID&lt;/code&gt; of your template in a safe place, we'll need it after.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mailjet dependency&lt;br&gt;
Install the &lt;code&gt;node-mailjet&lt;/code&gt; dependency in your backend : &lt;code&gt;npm install node-mailjet@3.3.1&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mailjet API credentials&lt;br&gt;
Set your mailjet API credentials you get from first step into your environments files located here : &lt;code&gt;./backend/src/environments&lt;/code&gt;. If you already forgot your API credentials, you can find them back using &lt;a href="https://app.mailjet.com/account/api_keys"&gt;this link&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Backend service&lt;br&gt;
Copy the &lt;code&gt;mailer&lt;/code&gt; folder of this module in your backend. You can know setup the template &lt;code&gt;ID&lt;/code&gt; from your published template into &lt;code&gt;templates.enum.ts&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it ! You are now enable to send mail to a specific user, using your pre-defined template a the &lt;code&gt;MailerService&lt;/code&gt; available in your backend :)&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;I hope this module will help you saving some time while trying to implement a mailing system in your project.&lt;/p&gt;

&lt;p&gt;Note that all modules currently available on the React/NestJS/MySQL web starter are listed &lt;a href="https://fast-modular-project.com/modules"&gt;here&lt;/a&gt;. Do not hesitate to ask for a tutorial on another module on this starter in the comment section !&lt;/p&gt;

&lt;p&gt;Links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The platform sharing the starter and it's modules : &lt;a href="https://fast-modular-project.com"&gt;Fast Modular Project&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;"Send mails with MailJet" module open source code available &lt;a href="https://fast-modular-project.com/modules/mailjet-mailing"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not hesitate to pin and like if you appreciated the article ❤️&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>node</category>
      <category>typescript</category>
      <category>saas</category>
    </item>
    <item>
      <title>Add a subscription payment system with Stripe in less than 20 min</title>
      <dc:creator>Leonidas Costas</dc:creator>
      <pubDate>Thu, 25 Mar 2021 15:00:10 +0000</pubDate>
      <link>https://dev.to/leonidascostas/add-a-subscription-payment-system-with-stripe-in-less-than-20-min-12a4</link>
      <guid>https://dev.to/leonidascostas/add-a-subscription-payment-system-with-stripe-in-less-than-20-min-12a4</guid>
      <description>&lt;p&gt;In this article I will share with you a payment module that could be really useful for those you want to implement a SaaS.&lt;/p&gt;

&lt;p&gt;On my side, I used this module on top of the React/Node/MySQL starter. This starter has been presented to you last week in &lt;a href="https://dev.to/fastmodularproject/web-starter-react-nestjs-mysql-3o9i"&gt;this article&lt;/a&gt;. &lt;/p&gt;

&lt;h1&gt;
  
  
  What does it bring?
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;subscription creation&lt;/li&gt;
&lt;li&gt;subscription cancelation&lt;/li&gt;
&lt;li&gt;subscription re-activation before d-day cancelation&lt;/li&gt;
&lt;li&gt;last but not least, almost 14 hours of work saved :D&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Prerequisite
&lt;/h1&gt;

&lt;p&gt;By getting the web starter I was mentioning above, you'll be able to plug this payment module directly on top of it and have a functional project with an authentication and a payment system in less than 20 minutes.&lt;/p&gt;

&lt;p&gt;Note that using the starter is not mandatory, you can also use the module as standalone. The integration won't be as easy as with the starter, but it should still be simple to integrate it in your already created project :)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The starter is available &lt;a href="https://fast-modular-project.com/starters"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The module is available &lt;a href="https://fast-modular-project.com/modules/reactjs-nestjs-stripe-subscription"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  How does it work?
&lt;/h1&gt;

&lt;p&gt;In this module, we'll use Stripe's checkout session. They are meant to create a payment session on Stripe's side for a given user and given product. We will redirect our user to this session when he clicks (hopefully) on "BUY NOW".&lt;/p&gt;

&lt;p&gt;High picture of the workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User clicks on your "buy button".&lt;/li&gt;
&lt;li&gt;Frontend asks backend to create a Stripe &lt;code&gt;checkout session&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Backend creates the &lt;code&gt;checkout session&lt;/code&gt; and returns the corresponding &lt;code&gt;sessionId&lt;/code&gt; to the frontend.&lt;/li&gt;
&lt;li&gt;Frontend redirects the user to the created session using the &lt;code&gt;sessionId&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;User pays on Stripe website and get redirect to your website (thanks to the &lt;code&gt;successUrl&lt;/code&gt; you'll provide) once the payment is successfully done.&lt;/li&gt;
&lt;li&gt;Backend is receiving notifications about the payment status thanks to a &lt;code&gt;Webhook&lt;/code&gt; and save the payment status in database.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Setup the payment system
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;Create a Stripe account&lt;/li&gt;
&lt;li&gt;Create a API key pair in "Developers" section. Once created keep your public (&lt;code&gt;pk_test...&lt;/code&gt;) and secret (&lt;code&gt;sk_test...&lt;/code&gt;) keys safe, we'll use them later :)&lt;/li&gt;
&lt;li&gt;Create your subscription product: set a description, a price, and the cancel settings. The product will be created in "test mode" by default. Once created, Stripe will display you a &lt;code&gt;priceId&lt;/code&gt; corresponding to the product, as usual keep it safe because we'll use it later :)&lt;/li&gt;
&lt;li&gt;Create a &lt;code&gt;Webhook&lt;/code&gt; between Stripe and your backend in "Developers" section, this will give you a secret &lt;code&gt;whsec_&lt;/code&gt;that should be kept safe.&lt;/li&gt;
&lt;li&gt;Add following event types to your Webhook: [&lt;code&gt;customer.subscription.updated&lt;/code&gt;, &lt;code&gt;customer.subscription.deleted&lt;/code&gt;, &lt;code&gt;invoice.payment_failed&lt;/code&gt;, &lt;code&gt;invoice.paid&lt;/code&gt;, &lt;code&gt;checkout.session.completed&lt;/code&gt;]&lt;/li&gt;
&lt;li&gt;Fill environment files with all info kept above as explained &lt;a href="https://fast-modular-project.com/modules/reactjs-nestjs-stripe-subscription"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;You can now push your frontend and backend to production and test your payment system! In test mode, you can fill the payment form with Stripe's test credit card &lt;code&gt;4242-4242-4242-4242&lt;/code&gt; and fill other fields with whatever you want.&lt;/li&gt;
&lt;li&gt;If your test passed, you can switch your Webhooks and your subscription product to production by clicking on "Send to production". Do not forget to update your environments files accordingly :)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The entire tutorial and a step by step integration on the starter is available &lt;a href="https://fast-modular-project.com/modules/reactjs-nestjs-stripe-subscription"&gt;here&lt;/a&gt;&lt;/strong&gt;. &lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;I hope this module will help you saving your some time while trying to implement a payment system in your project.&lt;br&gt;
If you have any question, I'll be present as usual in the comment section !&lt;/p&gt;

&lt;p&gt;Links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The platform sharing the starter and it's modules : &lt;a href="https://fast-modular-project.com"&gt;Fast Modular Project&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Stripe module open source code &lt;a href="https://fast-modular-project.com/modules/reactjs-nestjs-stripe-subscription"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not hesitate to pin and like if you appreciated the article ❤️&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>node</category>
      <category>saas</category>
    </item>
    <item>
      <title>Web starter with CI and AWS deployment (React NestJS Docker)</title>
      <dc:creator>Leonidas Costas</dc:creator>
      <pubDate>Wed, 17 Mar 2021 11:28:06 +0000</pubDate>
      <link>https://dev.to/leonidascostas/web-starter-react-nestjs-mysql-3o9i</link>
      <guid>https://dev.to/leonidascostas/web-starter-react-nestjs-mysql-3o9i</guid>
      <description>&lt;p&gt;In this article I will share with you a starter that has been pretty useful for some of my web projects :)&lt;/p&gt;

&lt;h1&gt;
  
  
  What does it bring ?
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;an isolated docker environment with a local frontend / backend / database launchable in one command&lt;/li&gt;
&lt;li&gt;a project structure with an authentication&lt;/li&gt;
&lt;li&gt;a foundation on which features can be added&lt;/li&gt;
&lt;li&gt;a deployment guide to AWS infrastructure&lt;/li&gt;
&lt;li&gt;continuous integration with Github Actions&lt;/li&gt;
&lt;li&gt;last but not least, almost 30 hours work saved :')&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  How does it work ?
&lt;/h1&gt;

&lt;p&gt;The frontend, backend, and database are wrapped in docker to avoid any issue with OS or local configurations. You can fire up everything with one command : &lt;code&gt;docker-compose up&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Frontend and backend are defining an architecture and a naming conventions to ease the comprehension of the starter and the share of feature around it.&lt;/p&gt;

&lt;h1&gt;
  
  
  Add features on it ?
&lt;/h1&gt;

&lt;p&gt;Some modules are also available to be added on top of it. You can use them and plug it, they are fully adapted to the starter structure :)&lt;/p&gt;

&lt;p&gt;Here is some available modules for this starter :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;multilingual with Phrase&lt;/li&gt;
&lt;li&gt;Payment system with Stripe&lt;/li&gt;
&lt;li&gt;Webcam with React&lt;/li&gt;
&lt;li&gt;Websocket with AWS API Gateway&lt;/li&gt;
&lt;li&gt;Location by ip&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All module are listed and available for download &lt;a href="https://fast-modular-project.com/modules"&gt;here&lt;/a&gt;. There is much more module to be created, so feel free to create your own and share it with the community :D&lt;/p&gt;

&lt;h1&gt;
  
  
  Deployment and continuous integration ?
&lt;/h1&gt;

&lt;p&gt;For the deployment steps, you'll have to create a RDS database, an Elastic Beanstalks, a S3 bucket and a CloudFront instance.&lt;/p&gt;

&lt;p&gt;For the continuous integration, you'll have to edit &lt;br&gt;
&lt;a href="https://fast-modular-project.com/starters/starter-reacjs-nestjs-mysql"&gt;&lt;code&gt;.github/workflows/main.yml&lt;/code&gt;&lt;/a&gt; to set up :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;branch name on which you want to trigger continuous integration (generally &lt;code&gt;master&lt;/code&gt; or &lt;code&gt;main&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;name of your &lt;code&gt;S3 bucket&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;name of your &lt;code&gt;Elastic Beanstalk&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Add your AWS credentials as secrets to your GitHub repository (&lt;code&gt;AWS_ACCESS_KEY_ID&lt;/code&gt;, &lt;code&gt;AWS_SECRET_ACCESS_KEY&lt;/code&gt;) .&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;I hope this starter will help you starting your future project! &lt;br&gt;
If you have any question I'll be present in the comment section !&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The platform sharing the starter and it's modules :&lt;br&gt;
&lt;a href="https://fast-modular-project.com"&gt;Fast Modular Project&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Do not hesitate to pin and like if you appreciated the article ❤️&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>node</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
