<?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: sven Gaubert</title>
    <description>The latest articles on Forem by sven Gaubert (@svengau).</description>
    <link>https://forem.com/svengau</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%2F332141%2F808b39b6-2e4c-4358-a18c-78a9e4c460f3.jpeg</url>
      <title>Forem: sven Gaubert</title>
      <link>https://forem.com/svengau</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/svengau"/>
    <language>en</language>
    <item>
      <title>Guide to nextjs + turbopack ⚡️🏎️</title>
      <dc:creator>sven Gaubert</dc:creator>
      <pubDate>Mon, 03 Mar 2025 07:58:35 +0000</pubDate>
      <link>https://forem.com/svengau/guide-to-nextjs-turbopack-48kl</link>
      <guid>https://forem.com/svengau/guide-to-nextjs-turbopack-48kl</guid>
      <description>&lt;p&gt;I really like Next.js, but it's commonly known to become really slow when your project grows.&lt;br&gt;
On my side, I could wait sometimes 40 seconds 🤯 to have one page compiled and displayed when developing &lt;a href="https://www.smartrole.ai" rel="noopener noreferrer"&gt;smartrole.ai&lt;/a&gt;, a big monorepo with turborepo, nextjs, pnpm, tailwind and prisma amongst others. &lt;br&gt;
I've tried to play with NextJS settings, like webpack, serverExternalPackages, or modularizeImports, but nothing really works.&lt;/p&gt;

&lt;p&gt;TBH, I was even considering switching to another framework.😢 Then comes Rust in the game, with &lt;a href="https://nextjs.org/docs/app/api-reference/turbopack" rel="noopener noreferrer"&gt;Turbopack&lt;/a&gt;...&lt;br&gt;
Enabling Turbopack is not straightforward at all, but it’s worth it: now it's just a matter of 1 or 2 seconds to compile ! 🤩&lt;/p&gt;

&lt;p&gt;So here's a guide on how I achieved this leap in performance and tackled some common issues along the way.&lt;/p&gt;
&lt;h1&gt;
  
  
  Installation
&lt;/h1&gt;

&lt;p&gt;The easy part. In package.json, simply add &lt;code&gt;--turbo&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"next dev --turbo"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: you also have &lt;code&gt;--turbopack&lt;/code&gt; options, which does the same, except you can't configure it using the &lt;a href="https://nextjs.org/docs/app/api-reference/config/next-config-js/turbo" rel="noopener noreferrer"&gt;experimental.turbo&lt;/a&gt; option.&lt;/p&gt;

&lt;p&gt;Remove the &lt;code&gt;webpack&lt;/code&gt;section from your &lt;code&gt;next.config.ts&lt;/code&gt;, as Turbopack comes as a replacement of webpack.&lt;/p&gt;

&lt;h1&gt;
  
  
  Troubleshooting Common Issues
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Package resolves to a different version
&lt;/h2&gt;

&lt;p&gt;When working with Turbopack, you might encounter an error like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The request prettier/standalone matches serverExternalPackages (or the default list).
The package resolves to a different version when requested from the project directory (3.5.1) compared to the package requested from the importing module (3.4.2).
Make sure to install the same version of the package in both locations.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Solution: To resolve version mismatches, add &lt;code&gt;pnpm.overrides&lt;/code&gt; to &lt;code&gt;package.json&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;"pnpm": {
    "overrides": {
      "prettier": "3.5.2"
    }
  },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Package can't be external
&lt;/h2&gt;

&lt;p&gt;If you encounter an error stating that a package cannot be external, you might see something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Package @libsql/client (serverExternalPackages or default list) can't be external
The request @libsql/client matches serverExternalPackages (or the default list), but it can't be external:
The request could not be resolved by Node.js from the project directory.
Packages that should be external need to be installed in the project directory, so they can be resolved from the output files.
Try to install the package into the project directory.
Next.js package not found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Create a &lt;code&gt;.npmrc&lt;/code&gt; file at the root of your monorepo with the following content to ensure all dependencies are installed correctly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;legacy-peer-deps=true
public-hoist-pattern[]=*import-in-the-middle*
public-hoist-pattern[]=*require-in-the-middle*
public-hoist-pattern[]=*motion/react*
public-hoist-pattern[]=*motion*
public-hoist-pattern[]=*keyv*
public-hoist-pattern[]=*chart.js*
public-hoist-pattern[]=*@prisma/client*
public-hoist-pattern[]=*@aws-sdk/client-s3*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;For further context, refer to the &lt;a href="https://github.com/vercel/next.js/issues/68805" rel="noopener noreferrer"&gt;GitHub issue&lt;/a&gt; related to this problem.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Next.js package not found
&lt;/h2&gt;

&lt;p&gt;Sometimes, Turbopack may fail to locate the Next.js package, resulting in an error like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Execution of get_entrypoints_with_issues failed
- Execution of Project::entrypoints failed
- Execution of AppProject::routes failed
- Execution of directory_tree_to_entrypoints_internal failed
- Execution of directory_tree_to_entrypoints_internal failed
- Execution of directory_tree_to_loader_tree failed
- Execution of *FileSystemPath::join failed
- Execution of get_next_package failed
- Next.js package not found]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; To fix this, delete the &lt;code&gt;pnpm-lock.yaml&lt;/code&gt; file. This can help resolve dependency resolution issues.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;See the &lt;a href="https://github.com/vercel/next.js/discussions/55987" rel="noopener noreferrer"&gt;GitHub discussion&lt;/a&gt; for more details.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The "path" argument must be of type string. Received undefined
&lt;/h2&gt;

&lt;p&gt;It appears with next 15.2.0&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Downgrade to a more stable version by setting your Next.js version in &lt;code&gt;package.json&lt;/code&gt; to &lt;code&gt;15.1.7&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Refer to this &lt;a href="https://github.com/vercel/next.js/issues/76497" rel="noopener noreferrer"&gt;GitHub issue&lt;/a&gt; for more insights.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>turbopack</category>
      <category>webdev</category>
      <category>webpack</category>
    </item>
    <item>
      <title>Seed your project in the freemium jungle🌴🌴</title>
      <dc:creator>sven Gaubert</dc:creator>
      <pubDate>Tue, 28 Apr 2020 12:52:07 +0000</pubDate>
      <link>https://forem.com/svengau/seed-your-project-in-the-freemium-jungle-bpj</link>
      <guid>https://forem.com/svengau/seed-your-project-in-the-freemium-jungle-bpj</guid>
      <description>&lt;p&gt;So many freemium services to help you launch your side project or startup!&lt;/p&gt;

&lt;p&gt;Here is a step-by-step guide to setting up a complete project, from &lt;strong&gt;logo design&lt;/strong&gt; to &lt;strong&gt;marketing&lt;/strong&gt; and of course &lt;strong&gt;hosting&lt;/strong&gt;. &lt;strong&gt;WITH ONLY FREE(MIUM) services !!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TLDR;
&lt;/h2&gt;

&lt;p&gt;For those who are in a hurry, we will present the following products in this article:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Development&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Logo branding&lt;/strong&gt; with &lt;a href="http://tailorbrands.go2cloud.org/aff_c?offer_id=3&amp;amp;aff_id=1219" rel="noopener noreferrer"&gt;Tailor Brands&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Code versioning&lt;/strong&gt; on a private repo, with &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;Github&lt;/a&gt; or &lt;a href="https://about.gitlab.com/" rel="noopener noreferrer"&gt;Gitlab&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Authentication&lt;/strong&gt; with Google or Facebook account&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Double Authentication&lt;/strong&gt; with &lt;a href="http://google-authenticator.com/" rel="noopener noreferrer"&gt;Google Authenticator&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Database&lt;/strong&gt; with &lt;a href="https://www.mongodb.com/cloud/atlas" rel="noopener noreferrer"&gt;MongoDB Atlas&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Storage&lt;/strong&gt; with &lt;a href="https://cloudinary.com/" rel="noopener noreferrer"&gt;Cloudinary&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Hosting&lt;/strong&gt; &lt;strong&gt;&amp;amp; API&lt;/strong&gt; with &lt;a href="https://netlify.com/" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt; or &lt;a href="https://vercel.com/" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Emailing&lt;/strong&gt; with &lt;a href="https://www.mailgun.com/" rel="noopener noreferrer"&gt;Mailgun&lt;/a&gt; or &lt;a href="https://www.mailjet.com/" rel="noopener noreferrer"&gt;Mailjet&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Payment&lt;/strong&gt; with &lt;a href="https://stripe.com/" rel="noopener noreferrer"&gt;Stripe&lt;/a&gt; or &lt;a href="https://www.paypal.com/" rel="noopener noreferrer"&gt;Paypal&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Performance Check&lt;/strong&gt; with &lt;a href="https://developers.google.com/web/tools/lighthouse" rel="noopener noreferrer"&gt;Lighthouse&lt;/a&gt; &amp;amp; &lt;a href="https://www.webpagetest.org/" rel="noopener noreferrer"&gt;WebPageTest&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Marketing&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Newsletter&lt;/strong&gt; with &lt;a href="https://mailchimp.com/" rel="noopener noreferrer"&gt;Mailchimp&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Seo&lt;/strong&gt; with &lt;a href="https://neilpatel.com/ubersuggest/" rel="noopener noreferrer"&gt;UberSuggest&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Analytics&lt;/strong&gt; with the aptly named &lt;a href="https://analytics.google.com/analytics/web/" rel="noopener noreferrer"&gt;Google Analytics&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Live chat&lt;/strong&gt; with &lt;a href="http://hubs.to/TPRVc" rel="noopener noreferrer"&gt;Hubspot&lt;/a&gt; or &lt;a href="https://freshchat.grsm.io/fsr" rel="noopener noreferrer"&gt;Freshchat&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Quick Notice&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This choice is purely subjective, and there are many great services created every day, with a freemium offer. We tried to choose well-known services with an interesting free offer and no trial period.&lt;/p&gt;

&lt;p&gt;Also, some of the provided links are sponsored 💸. No worries, we didn't choose those services because of their affiliation program, but because they are simply the best.&lt;/p&gt;

&lt;p&gt;If you feel a must-have is missing, please feel free to &lt;a href="https://www.fullstackrocket.com/contact-us" rel="noopener noreferrer"&gt;contact us&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Logo Branding
&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://tailorbrands.go2cloud.org/aff_c?offer_id=3&amp;amp;aff_id=1219" rel="noopener noreferrer"&gt;Tailor Brands&lt;/a&gt; is a team of experts who are dedicated to streamlining the branding procedure for startups and small businesses. It makes it branding accessible for all regardless of their background in design, skill level, and budget size. &lt;a href="http://tailorbrands.go2cloud.org/aff_c?offer_id=3&amp;amp;aff_id=1219" rel="noopener noreferrer"&gt;Tailor Brands&lt;/a&gt; has created a platform where branding and logo design has been made so much easier and fun with its huge amount of designing and branding tools. For this reason, it has 14 million users who have created about 500 million unique designs on this platform.&lt;/p&gt;

&lt;p&gt;You can design a logo for your company for free in a matter of minutes! There are six steps you need to follow for the design of your logo and by the end, you will be able to download the logo in the form of an EPS file or SVG.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Versioning on a private repo
&lt;/h2&gt;

&lt;p&gt;It's a long time since you had to set up your own SVN server. ;-)&lt;/p&gt;

&lt;p&gt;Now, simple choose a free service between &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;Github&lt;/a&gt; (acquired by Microsoft in 2018) or &lt;a href="https://about.gitlab.com/" rel="noopener noreferrer"&gt;Gitlab&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Unlimited private and public projects&lt;/li&gt;
&lt;li&gt;  Unlimited collaborators&lt;/li&gt;
&lt;li&gt;  Free minutes for Continuous Integration (CI) and Delivery (CD)&lt;/li&gt;
&lt;li&gt;  Project Issue Board&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also &lt;a href="https://bitbucket.org/" rel="noopener noreferrer"&gt;Bitbucket&lt;/a&gt; is a good alternative, but only 5 collaborators per repo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authentication with Google or Facebook account
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/OAuth" rel="noopener noreferrer"&gt;OAuth protocol&lt;/a&gt; is used for authentication using Google or Facebook. Just register your client on &lt;a href="https://developers.facebook.com/apps/" rel="noopener noreferrer"&gt;Facebook Developpers&lt;/a&gt; or &lt;a href="https://console.developers.google.com/apis/credentials" rel="noopener noreferrer"&gt;Google Console&lt;/a&gt;, then your client can call those services with the requested information (user profile, email, ...), the user will be redirected to the authentication service login page, and finally your server will receive the access token, with the requested information. And all this at no cost!&lt;/p&gt;

&lt;h2&gt;
  
  
  Double Authentication with Google Authenticator
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Multi-factor_authentication" rel="noopener noreferrer"&gt;Two-Factor Authentication&lt;/a&gt; (2FA) It's a must-have if your service uses sensitive data and you want to add an extra layer of protection. 2 classical options: send an SMS to the user to double authenticate him/her, but you'll have to pay the SMS, or use &lt;a href="http://google-authenticator.com/" rel="noopener noreferrer"&gt;Google Authenticator&lt;/a&gt; for free! There are plenty of tutorial available on internet to setup Google Authenticator, for example &lt;a href="https://medium.com/@richb_/easy-two-factor-authentication-2fa-with-google-authenticator-php-108388a1ea23" rel="noopener noreferrer"&gt;this one for PHP&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Database with MongoDB Atlas
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.mongodb.com/cloud/atlas" rel="noopener noreferrer"&gt;MongoDB Atlas&lt;/a&gt; provides the easiest way to manage and host data in the cloud. Optimization and monitoring of database pain can be reduced by using extended set tools and features that are included in MongoDB Atlas.&lt;/p&gt;

&lt;p&gt;Choose your favorite cloud providers (AWS, Google Cloud or Azure), then your region (be careful to choose the same region as the server hosting your site), and that's it! You have a mongodb database entirely on the Cloud, with a good 500MB of storage.&lt;/p&gt;

&lt;p&gt;Another interesting alternative is &lt;a href="https://fauna.com/" rel="noopener noreferrer"&gt;FaunaDB&lt;/a&gt;, with a generous 5Gb of storage, (yes, 5Gb for free!) but the Fauna Query Language (FQL) can be a little confusing at first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Storage with Cloudinary
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://cloudinary.com/" rel="noopener noreferrer"&gt;Cloudinary&lt;/a&gt; is a media management platform that provides an end-to-end solution for all your video and image needs. Its key features are file storage and upload, cloud asset management, video, and image manipulation (thumbnails, resizing, etc...), fast deliver, optimization and presentation. There is a secure cloud system for the storage of videos and images.&lt;/p&gt;

&lt;p&gt;Images and videos can be directly uploaded from the browser, or using Cloudinary's SDKs &amp;amp; upload API.&lt;/p&gt;

&lt;p&gt;Also, you can upload some private assets, only accessible with a signed Urls.&lt;/p&gt;

&lt;p&gt;And every month, you'll have 25 credits for free! For an example usage, 2GB of image storage (2 credits), 4GB of bandwidth (4 credits) and 4000 monthly transformations (4 credits) will need 10 credits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Web Hosting &amp;amp; API with Netlify or Vercel
&lt;/h2&gt;

&lt;p&gt;Forget about hosting your own servers, setting up kubernetes (arghh), and receiving the invoice at the end of the month! At least, at the beginning when launching your project (and even further).&lt;/p&gt;

&lt;p&gt;Just choose between &lt;a href="https://www.netlify.com/" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt; or &lt;a href="https://vercel.com/" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt; (ex Zeit.co, ex Now.sh), to host your website, your API (using serverless), and even with a micro service approach!&lt;/p&gt;

&lt;p&gt;On both services, you can deploy your site manually from your local (and save minutes of build time), or deploy automatically from your Git repository when commits are added.&lt;/p&gt;

&lt;p&gt;Once deployed, your service will benefit from a global CDN for your website, and your api from an auto-scalable serverless environment.&lt;/p&gt;

&lt;p&gt;An interesting freemium alternative is &lt;a href="https://www.heroku.com/" rel="noopener noreferrer"&gt;Heroku&lt;/a&gt;, but it suffers a couple of convenient. First, the service is less handy to use than Netlify or Vercel. And once you've got traffic, the cost will increase significantly.&lt;/p&gt;

&lt;p&gt;Also &lt;a href="https://firebase.google.com/" rel="noopener noreferrer"&gt;Firebase&lt;/a&gt; is a great option, but the interface is a bit complicated, and I found this technology a bit invasive (you have to install the Javascript SDK into your app), so it will be difficult to move your service to another provider if you are not satisfied.&lt;/p&gt;

&lt;h2&gt;
  
  
  Payment with Stripe or Paypal
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://stripe.com/" rel="noopener noreferrer"&gt;Stripe&lt;/a&gt; is a payment gateway platform, which handles many countries, currencies and payment methods (Visa, mastercard, Alipay, Apple Pay, Giropay, iDEAL, SEPA, Wechat and many more).&lt;/p&gt;

&lt;p&gt;No setup fees or monthly subscription, only a % on each transaction (e.g USA=2.9%+30¢, France 1.4%+€0.25, Singapore 3.4%+$0.50).&lt;/p&gt;

&lt;p&gt;Stripe supports one-time payments or subscriptions, using direct API or checkout (a payment page hosted by Stripe). And it supports &lt;a href="https://stripe.com/docs/strong-customer-authentication" rel="noopener noreferrer"&gt;Strong Customer Authentication&lt;/a&gt; (SCA), aka 3D Secure.&lt;/p&gt;

&lt;p&gt;⚠️Stripe also manage products, skus &amp;amp; inventory, but some apis have been deprecated (orders API), so I would strongly recommend to use the service as a payment gateway only.&lt;/p&gt;

&lt;p&gt;Another good option is &lt;a href="https://www.paypal.com" rel="noopener noreferrer"&gt;Paypal&lt;/a&gt; of course, a bit older so you can easily be lost in the documentation, but it works well.&lt;/p&gt;

&lt;p&gt;Same same than Stripe, Paypal only takes a % on each transaction (e.g USA=2.9%+30¢, France 2.9%+€0.35, Singapore 4.4%+$0.30).&lt;/p&gt;

&lt;h2&gt;
  
  
  Emailing with Mailgun or Mailjet
&lt;/h2&gt;

&lt;p&gt;I've used Mailgun for years, and this service is doing one thing really well: sending and receiving emails.&lt;/p&gt;

&lt;p&gt;It provides a complete track record of your received and sent emails through applications and websites. SMPT or API are the two methods that can be used to interact with the service. You can also define some emails templates to use, which is great, but no visual editor year. And with the flex plan, you can send &lt;strong&gt;up to 5,000 emails / month&lt;/strong&gt; for free.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.mailjet.com/" rel="noopener noreferrer"&gt;Mailjet&lt;/a&gt; (&lt;a href="https://www.mailjet.com/mailgun-acquires-mailjet/" rel="noopener noreferrer"&gt;acquired by... Mailgun&lt;/a&gt; (!) in 2019) is also a great service to send and receive emails, &lt;strong&gt;6,000 emails per month&lt;/strong&gt;, save unlimited contacts, with an API, SMTP Relay, &amp;amp; Webhooks, send newsletters, etc...&lt;/p&gt;

&lt;p&gt;Also a key feature in Mailjet is the &lt;strong&gt;Visual Email template editor&lt;/strong&gt;. So easy to update emails content, in Html or &lt;a href="https://mjml.io/" rel="noopener noreferrer"&gt;MJML&lt;/a&gt; to design responsive emails.&lt;/p&gt;

&lt;h2&gt;
  
  
  Newsletter with Mailchimp
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://mailchimp.com/" rel="noopener noreferrer"&gt;Mailchimp&lt;/a&gt; is an amazing tool to send newsletter or automated emails (welcome email, order notifications, etc...), with multiple features.&lt;/p&gt;

&lt;p&gt;The free plan comes with 10,000 emails per month, and 2000 contacts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.mailjet.com/" rel="noopener noreferrer"&gt;Mailjet&lt;/a&gt; is also a good option to send newsletter, but no automation in the free tiers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Search Engine Optimization (SEO)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://neilpatel.com/ubersuggest/" rel="noopener noreferrer"&gt;Ubersuggest&lt;/a&gt; is a really complete tool provided by Neil Patel, a famous SEO expert. This tool allows you to dig into searches and keywords to help you increase your page rank.&lt;/p&gt;

&lt;p&gt;Neil's newsletter also provides high quality content to train you in SEO.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance Check
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developers.google.com/web/tools/lighthouse" rel="noopener noreferrer"&gt;Google Lighthouse&lt;/a&gt; is an easy going tool to audit your website and measure performance, accessibility and SEO best practices.&lt;/p&gt;

&lt;p&gt;You can launch Lighthouse directly from your chrome dev tools, or from the command line, or online from the &lt;a href="https://developers.google.com/speed/pagespeed/insights" rel="noopener noreferrer"&gt;Google PageSpeed Insights&lt;/a&gt; website.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.webpagetest.org/" rel="noopener noreferrer"&gt;WebpageTest&lt;/a&gt; is also an handy tool to measure the performance of your website, even if the design is soooo 80's 😝. The project is &lt;a href="https://github.com/WPO-Foundation/webpagetest" rel="noopener noreferrer"&gt;open-sourced&lt;/a&gt; by the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Analytics with Google Analytics&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://analytics.google.com/analytics/web/" rel="noopener noreferrer"&gt;Google analytics&lt;/a&gt; is one of the most popular service to analyze the visitors on your website in detail, for free.&lt;/p&gt;

&lt;p&gt;This service can provide you with valuable insights such as track your video, mobile applications and social networking sites.&lt;/p&gt;

&lt;h2&gt;
  
  
  Live chat with Hubspot or Freshchat
&lt;/h2&gt;

&lt;p&gt;Finally, once your website is up and running, &lt;a href="http://hubs.to/TPRVc" rel="noopener noreferrer"&gt;Hubspot&lt;/a&gt; and &lt;a href="https://www.freshworks.com/live-chat-software/" rel="noopener noreferrer"&gt;Freshchat&lt;/a&gt; will help you interacting with your customers with a live chat. You're not online ? Those services will notify you by email or on Slack, so you can&lt;/p&gt;

&lt;h2&gt;
  
  
  Too much services to integrate ? Don't worry 😉
&lt;/h2&gt;

&lt;p&gt;At &lt;a href="https://www.fullstackrocket.com/" rel="noopener noreferrer"&gt;Fullstack Rocket&lt;/a&gt;, we want to help entrepreneurs get their idea off the ground. We have integrated most of these free services into easy-to-deploy solutions.&lt;/p&gt;

&lt;p&gt;Our service is quite new, but we have already a few solutions that handle common features, like user registration and login, email template creation, asset storage, and much more.&lt;/p&gt;

&lt;p&gt;We are also looking for talented developers who want to offer and sell their own solution. If you are interested in monetizing your project, contact us!&lt;/p&gt;

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

&lt;p&gt;There are so many high quality freemium services, this article has presented some of them, and I'm sure you will have many in mind, so please &lt;a href="https://www.fullstackrocket.com/contact-us" rel="noopener noreferrer"&gt;share with us&lt;/a&gt;, and I will update this article accordingly.&lt;/p&gt;

&lt;p&gt;Also, a couple of advices to conclude:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  before developing a feature, check if it doesn't already exist in the cloud.&lt;/li&gt;
&lt;li&gt;  Keep in mind that conditions of use can change overnight,&lt;/li&gt;
&lt;li&gt;  Prefer well-known services to services that are too new.&lt;/li&gt;
&lt;li&gt;  Check carefully the different plans offered to avoid surprises if your service generates traffic.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;And happy coding ! 🤓&lt;/strong&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Authentication using Netlify, lambda… and PassportJS 👮‍♀️</title>
      <dc:creator>sven Gaubert</dc:creator>
      <pubDate>Tue, 11 Feb 2020 23:07:56 +0000</pubDate>
      <link>https://forem.com/svengau/authentication-using-netlify-lambda-and-passportjs-57e8</link>
      <guid>https://forem.com/svengau/authentication-using-netlify-lambda-and-passportjs-57e8</guid>
      <description>&lt;p&gt;&lt;em&gt;This article was originally written on &lt;a href="https://medium.com/@svengau/authentication-using-netlify-lambda-and-passportjs-%EF%B8%8F-51bfd80c6c11" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can easily use ExpressJS and PassportJS to do authentication on Netlify with lambda functions.&lt;/p&gt;

&lt;h1&gt;
  
  
  TLDR;
&lt;/h1&gt;

&lt;p&gt;For those in a hurry, an &lt;a href="https://netlify-authentification-sample.netlify.com" rel="noopener noreferrer"&gt;online demo&lt;/a&gt; is available, and source code of the sample project is available here:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/svengau" rel="noopener noreferrer"&gt;
        svengau
      &lt;/a&gt; / &lt;a href="https://github.com/svengau/netlify-authentification-sample" rel="noopener noreferrer"&gt;
        netlify-authentification-sample
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Authentication with netlify lambda functions, PassportJS and Express
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Example of netlify authentication with Passportjs&lt;/h1&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://app.netlify.com/sites/netlify-authentification-sample/deploys" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/1071fe04198ec50d24d54f28d4c83daeef0ee4edaf1ebe8c750ea06a4eb9de70/68747470733a2f2f6170692e6e65746c6966792e636f6d2f6170692f76312f6261646765732f39643161643730392d326463632d346336662d616661352d3861346236356463326564312f6465706c6f792d737461747573" alt="Netlify Status"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This project shows how to use the very popular &lt;a href="http://www.passportjs.org" rel="nofollow noopener noreferrer"&gt;PassportJS&lt;/a&gt; library (normally available under expressjs) with the &lt;a href="https://www.netlify.com/" rel="nofollow noopener noreferrer"&gt;Netlify&lt;/a&gt; platform running under AWS Lambda.&lt;/p&gt;
&lt;p&gt;We took the example of &lt;a href="http://www.passportjs.org/packages/passport-google-oauth/" rel="nofollow noopener noreferrer"&gt;Google OAuth&lt;/a&gt;, but you can use any &lt;a href="http://www.passportjs.org/packages/" rel="nofollow noopener noreferrer"&gt;PassportJS strategy&lt;/a&gt; (Twitter, Facebook, Local, JWT, Github, ...).&lt;/p&gt;
&lt;p&gt;You can clone on you local with:&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;git@github.com:svengau/netlify-authentification-sample.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Alternatively you can deploy straight to Netlify with this one-click Deploy:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://app.netlify.com/start/deploy?repository=https://github.com/svengau/netlify-authentification-sample&amp;amp;utm_source=github" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/7997e9832575db385b4538afa47f1a83ef821924b17653244c1d32e749b3f2f8/68747470733a2f2f7777772e6e65746c6966792e636f6d2f696d672f6465706c6f792f627574746f6e2e7376673f75746d5f736f757263653d676974687562" alt="Deploy to Netlify"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Once deployed, don't forget to configure the 3 following env variables:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GOOGLE_AUTH_CLIENT_ID: your google client id&lt;/li&gt;
&lt;li&gt;GOOGLE_AUTH_CLIENT_SECRET: your google client secret key&lt;/li&gt;
&lt;li&gt;SESSION_SECRET: a random session secret&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Live Demo&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;You may test out a deployed version of this project here: &lt;a href="https://netlify-authentification-sample.netlify.com/" rel="nofollow noopener noreferrer"&gt;https://netlify-authentification-sample.netlify.com/&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/svengau/netlify-authentification-sample" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h1&gt;
  
  
  Netlify &amp;amp; the identity module
&lt;/h1&gt;

&lt;p&gt;Netlify is a great product to deploy static apps or even with API (using lambda functions). The service also manages authentication with the &lt;a href="https://docs.netlify.com/visitor-access/identity/" rel="noopener noreferrer"&gt;identity module&lt;/a&gt;: this module may match your requirement, but the free offer has some limitations, and the first &lt;strong&gt;paid offer costs $99/month/site&lt;/strong&gt;! If you have several sites, it can quickly become very expensive.&lt;/p&gt;

&lt;p&gt;In the following example, I will show you how to use the very popular &lt;a href="http://www.passportjs.org" rel="noopener noreferrer"&gt;PassportJS&lt;/a&gt; library to authenticate with Google Auth. With PassportJS, you have more than &lt;a href="http://www.passportjs.org/packages/" rel="noopener noreferrer"&gt;500 authentication strategies&lt;/a&gt; (Twitter, Facebook, Local, JWT, Github,…) to choose from, &lt;strong&gt;for free!&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Configuration from scratch
&lt;/h1&gt;

&lt;p&gt;Netlify provides a &lt;a href="https://github.com/netlify/create-react-app-lambda" rel="noopener noreferrer"&gt;create-react-app-lambda&lt;/a&gt; boilerplate to start an application with create-react-app and lamdba, but we will start from scratch with &lt;a href="https://github.com/facebook/create-react-app" rel="noopener noreferrer"&gt;create-react-app&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So, let’s go! we’ll create a React app, with lambda functions, that will load an express application to be able to use passportJS and Google strategy. No need for a database, we will store everything in cookies thanks to the client-session library.&lt;/p&gt;

&lt;p&gt;1. Install the netlify CLI in global mode:&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 netlify-cli -g
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2. Create the React application, with the following dependencies:&lt;/p&gt;

&lt;p&gt;npx create-react-app netlify-authentification-sampleyarn add serverless-http passport passport-google-oauth20 lodash client-sessions cookie-parseryarn add -D netlify-lambda npm-run-all http-proxy-middleware env-cmd&lt;/p&gt;

&lt;p&gt;3. Add a proxy as described in the &lt;a href="https://create-react-app.dev/docs/proxying-api-requests-in-development/#configuring-the-proxy-manually" rel="noopener noreferrer"&gt;facebook doc&lt;/a&gt;, to point the url /netlify/functions to our API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const proxy = require("http-proxy-middleware");module.exports = function setupProxy(app) {  
  app.use(  
    proxy("/.netlify/functions/", {  
     target: "http://localhost:8888/"  
    })   
  );  
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4. Create the file netlify.toml, to configure the build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[build]  
command = “yarn build”   
functions = “build-lambda”   
publish = “build”
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;5. The src/lambda directory (but not the subdirectories) contains all the lambda functions. Create an &lt;code&gt;src/lambda/auth.js&lt;/code&gt; function that will support authentication:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import serverless from "serverless-http";  
import app from "./lib/express";  
exports.handler = serverless(app);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function will be accessible from &lt;code&gt;/.netlify/functions/auth&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;6. And configure the express application, with the cookie parser, client session and passport:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.use(cookieParser());  
app.use(  
  sessions({  
    cookieName: "session",  
    secret: process.env.SESSION_SECRET,  
    cookie: {  
      ephemeral: false,  
      secure: false  
    }  
  })  
);  
app.use(passport.initialize());  
app.use(passport.session());  
passport.serializeUser(  
  (user, cb) =&amp;gt; cb(user ? null : "null user", user)  
);  
passport.deserializeUser(  
  (user, cb) =&amp;gt; cb(user ? null : "null user", user)  
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;7. Add the PassportJS strategy for Google:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;router.use((req, _res, next) =&amp;gt; {  
  const {  
    query: { host }  
  } = req;if (!passport._strategy(Strategy.name) &amp;amp;&amp;amp; host) {  
    console.info(`Init Google Auth strategy on host ${host}`);  
    passport.use(  
      new Strategy(  
        {  
          clientID: process.env.GOOGLE_AUTH_CLIENT_ID,  
          clientSecret: process.env.GOOGLE_AUTH_CLIENT_SECRET,  
          callbackURL: `${host}/.netlify/functions/auth/google/callback`,  
          passReqToCallback: true  
        },  
        async function(req, _token, _tokenSecret, profile, done) {  
          console.info("load user profile", profile);  
          const user = {  
            id: profile.id,  
            image: get("photos[0].value")(profile),  
            userName: profile.displayName  
          };  
          req.user = user;  
          return done(null, user);  
        }  
      )  
    );  
  }  
  next();  
});  
router.get(  
  "/google",  
  passport.authenticate("google", {  
    scope: [  
      "[https://www.googleapis.com/auth/userinfo.profile](https://www.googleapis.com/auth/userinfo.profile)",  
      "[https://www.googleapis.com/auth/userinfo.email](https://www.googleapis.com/auth/userinfo.email)"  
    ]  
  })  
);  
router.get(  
  "/google/callback",  
  passport.authenticate("google", { failureRedirect: "/" }),  
  function callback(req, res) {  
    console.info(`login user ${req.user &amp;amp;&amp;amp; req.user.id} and redirect`);  
    return req.login(req.user, async function callbackLogin(loginErr) {  
      if (loginErr) {  
        throw loginErr;  
      }  
      return res.redirect("/");  
    });  
Note: these settings are sensitive and private, and should not be commuted in git. You will also have to declare them in the netlify interface in the “Build &amp;amp; Deploy &amp;gt; Environment” section.  
  }  
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the &lt;code&gt;host&lt;/code&gt; parameter is sent by the client, because within a lambda function, you can access the host or requested url.&lt;/p&gt;

&lt;p&gt;8. Store the private keys in .env file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GOOGLE_AUTH_CLIENT_ID=&amp;lt;youclientID&amp;gt;.apps.googleusercontent.com  
GOOGLE_AUTH_CLIENT_SECRET=&amp;lt;youClientSecretKey&amp;gt;  
SESSION_SECRET=&amp;lt;ARandomString&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note 1&lt;/strong&gt;: these settings are sensitive and private, and should not be commited in git. You will also have to declare them in the netlify interface in the “Build &amp;amp; Deploy &amp;gt; Environment” section.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note 2&lt;/strong&gt;: If you have public settings in your application, you can also declare them only once in &lt;code&gt;netlify.toml&lt;/code&gt;, in the “build.environment” section&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And voila ! 🎉&lt;/p&gt;

&lt;p&gt;Now, you just have to start your app locally with &lt;code&gt;yarn dev&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Deployment on Netlify
&lt;/h1&gt;

&lt;p&gt;Really simple, 2 methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  deployment directly from the git repository. For more details, see the &lt;a href="https://docs.netlify.com/site-deploys/create-deploys/#deploy-with-git" rel="noopener noreferrer"&gt;netlify documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  command line deployment, with: &lt;code&gt;netlify deploy&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;once deployed, configure the environment variables in the netlify interface, the same way you’ve done it in &lt;code&gt;.env&lt;/code&gt; file:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  GOOGLE_AUTH_CLIENT_ID&lt;/li&gt;
&lt;li&gt;  GOOGLE_AUTH_CLIENT_SECRET&lt;/li&gt;
&lt;li&gt;  SECRET_SESSION&lt;/li&gt;
&lt;/ul&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%2Fyhnrv9yp1rzb65si9aix.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%2Fyhnrv9yp1rzb65si9aix.png" width="800" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;You can easily use express and PassportJS with Netlify, and it’s a bless 👼. It’s interesting for the following reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ExpressJS has a very rich ecosystem
&lt;/li&gt;
&lt;li&gt;you have an existing project under express and want to make a smooth migration
&lt;/li&gt;
&lt;li&gt;you know express well&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, there are some limitations to be taken into account. According to the documentation, all serverless functions are deployed with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  us-east-1 AWS Lambda region&lt;/li&gt;
&lt;li&gt;  1024MB of memory&lt;/li&gt;
&lt;li&gt;  10 second execution limit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So if you start using express, try to keep your &lt;strong&gt;application small&lt;/strong&gt; (if necessary, you can split it over several endpoints), use a &lt;strong&gt;database in the same region&lt;/strong&gt; as your Netlify application (us-east-1), and &lt;strong&gt;no heavy operations&lt;/strong&gt; that last long.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finally…
&lt;/h2&gt;

&lt;p&gt;A little self-promotion 😇 does not hurt: At &lt;strong&gt;&lt;a href="https://www.fullstackrocket.com" rel="noopener noreferrer"&gt;FullStack Rocket&lt;/a&gt;&lt;/strong&gt;, we have developed pre-packaged offers that can be deployed directly on Netlify, for a free hosting cost if you don’t have traffic. Ideal for startups who want to test their concept quickly ! You will earn time and money !&lt;/p&gt;

&lt;p&gt;And Happy coding ! 😎&lt;/p&gt;

</description>
      <category>node</category>
      <category>serverless</category>
      <category>aws</category>
      <category>netlify</category>
    </item>
    <item>
      <title>When GraphQL meets gRPC… 😍</title>
      <dc:creator>sven Gaubert</dc:creator>
      <pubDate>Tue, 11 Feb 2020 11:16:39 +0000</pubDate>
      <link>https://forem.com/svengau/when-graphql-meets-grpc-5aah</link>
      <guid>https://forem.com/svengau/when-graphql-meets-grpc-5aah</guid>
      <description>&lt;p&gt;&lt;em&gt;This article was originally written on &lt;a href="https://medium.com/@svengau/when-graphql-meets-grpc-3e9729d32e05" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Context
&lt;/h1&gt;

&lt;p&gt;At &lt;a href="http://www.aiptrade.com" rel="noopener noreferrer"&gt;Aiptrade&lt;/a&gt;, we have a micro-service architecture, deployed on Kubernetes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;backend services discuss with each others via pub-sub,&lt;/li&gt;
&lt;li&gt;and ONLY one frontend service to manage the API. Argh.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This frontend service has grown and is now fat, so it’s time to truncate it, and move to a &lt;strong&gt;Backend for Frontend&lt;/strong&gt; (BFF) architecture.&lt;br&gt;&lt;br&gt;
At first, we tried &lt;a href="https://www.apollographql.com/docs/graphql-tools/schema-stitching.html" rel="noopener noreferrer"&gt;&lt;strong&gt;GraphQL schema stitching&lt;/strong&gt;&lt;/a&gt;, which sounds really awesome, but it comes with some problems: conflict management between types of the same name, heterogeneous error handling, and we were also worried about performance, since a graphQL request is parsed twice.&lt;br&gt;&lt;br&gt;
So we turned to gRPC. Very promising on paper, library available in several languages, with a typed contract similar to GraphQL, used for several years by Google internally, in short the Holy Grail! 🤩&lt;/p&gt;

&lt;p&gt;I won’t explain GraphQL &lt;a href="https://grpc.io" rel="noopener noreferrer"&gt;gRPC&lt;/a&gt; nor &lt;a href="https://developers.google.com/protocol-buffers/" rel="noopener noreferrer"&gt;protobuffer&lt;/a&gt;, there are plenty of articles and the official documentation is good. So let’s dig into the project.&lt;/p&gt;
&lt;h1&gt;
  
  
  The sample project
&lt;/h1&gt;

&lt;p&gt;Our PoC will allow us to create… well… blog posts as usual 😄, and is composed with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a &lt;strong&gt;graphQL server&lt;/strong&gt;, in front of the client as our unique BFF entry point. Its role is mainly to validate input data (required / optional fields, type, …) and filter output data. The validation here is important since required &amp;amp; optional fields have been dropped from proto3. It also acts as a client to the gRPC micro-service.&lt;/li&gt;
&lt;li&gt;a &lt;strong&gt;gRPC server&lt;/strong&gt;, to perform all functional operations. Here to create and list some blog posts.&lt;/li&gt;
&lt;li&gt;those 2 micro-services will be hosted on k8, so we will also implement a &lt;strong&gt;Health check&lt;/strong&gt; mechanism, in gRPC please!&lt;/li&gt;
&lt;/ul&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%2Fukm6cnati10i4ca1zsbr.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%2Fukm6cnati10i4ca1zsbr.png" alt="Sample Architecture diagram with GraphQL &amp;amp; gRPC" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sample Architecture diagram with GraphQL &amp;amp; gRPC (cc cloudcraft.co)&lt;/p&gt;
&lt;h1&gt;
  
  
  Setup
&lt;/h1&gt;

&lt;p&gt;For the GraphQL Server, &lt;a href="https://www.npmjs.com/package/apollo-server" rel="noopener noreferrer"&gt;apollo-server&lt;/a&gt; does the job perfectly. And it offers a very convenient graphQL playground to run our queries.&lt;/p&gt;

&lt;p&gt;For gRPC, We will use &lt;strong&gt;NodeJS&lt;/strong&gt; for the server and client side, because gRPC libraries on NodeJS &lt;strong&gt;can dynamically generate the code at runtime&lt;/strong&gt;, which is awesome to quickly do a PoC, unlike other libraries available on other platforms (Go, PHP, Java, Python,…), that require the &lt;a href="https://github.com/protocolbuffers/protobuf" rel="noopener noreferrer"&gt;protoc&lt;/a&gt; compiler to generate a stub at build time. If you prefer working with static generated code, &lt;a href="https://dev.to/attest-engineering/fully-typed-typescript-api-consuming-grpc-and-graphql-5d5ae6b33bf1"&gt;here&lt;/a&gt; a really interesting article.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On the &lt;strong&gt;client side&lt;/strong&gt;, the official &lt;a href="https://www.npmjs.com/package/grpc" rel="noopener noreferrer"&gt;gRPC&lt;/a&gt; client works like a charm. It can handle interceptors, but doesn’t support Promises. If you prefer working with async / await, &lt;a href="https://www.npmjs.com/package/grpc-caller" rel="noopener noreferrer"&gt;grpc-caller&lt;/a&gt; is a good alternative.&lt;/li&gt;
&lt;li&gt;On the &lt;strong&gt;server side&lt;/strong&gt;, The official &lt;a href="https://github.com/grpc/grpc-node" rel="noopener noreferrer"&gt;gRPC-node&lt;/a&gt; library doesn’t support interceptors, so we have chosen &lt;a href="https://github.com/malijs/mali" rel="noopener noreferrer"&gt;mali&lt;/a&gt;, a really simple and easy to use library for gRPC, which supports metadata and middlewares (aka interceptors).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To run the PoC:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone [git@github.com](mailto:git@github.com):svengau/grpc-graphql-sample.gitcd post-api &amp;amp;&amp;amp; npm i &amp;amp;&amp;amp; npm start  
cd graphql-api &amp;amp;&amp;amp; npm i &amp;amp;&amp;amp; npm start🚀 Server ready at [http://localhost:4000/graphql](http://localhost:4000/graphql)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;and run the following query:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mutation {  
 addPost(data: { title: “helloooo” }) {  
   message  
   result { \_id title body }  
 }  
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  The wedding contract
&lt;/h1&gt;

&lt;p&gt;The gRPC server exposes 2 proto3 contracts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Post.proto&lt;/strong&gt;, a sample contract to create and list blog posts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Health.proto&lt;/strong&gt;, a &lt;a href="https://github.com/grpc/grpc/blob/master/doc/health-checking.md" rel="noopener noreferrer"&gt;contract proposed&lt;/a&gt; by gRPC to check service Health from Kubernetes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The proto3 contract, in the &lt;code&gt;post.proto&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;message Post {  
  string \_id = 1;  
  string title = 2;  
  string body = 3;  
}message Posts {  
  int32 page = 1;  
  int32 limit = 2;  
  int32 count = 3;  
  repeated Post nodes = 4;  
}message addPostRequest {  
  reserved 1; // \_id  
  required string title = 2;  
  string body = 3;  
}message listPostRequest {  
  optional string page = 1 \[default = 1\];  
  optional string limit = 2;  
  optional string \_id = 3;  
}service PostService {  
  rpc addPost (addPostRequest) returns (Post) {}  
  rpc listPosts (listPostRequest) returns (Posts) {}  
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And to serve the proto file, as simple as:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Mali from "mali";this.server = new Mali();this.server.addService("\[...\]/Post.proto", "PostService");  
this.server.use({ PostService: { addPost, listPost } })this.server.start("0.0.0.0:50051");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Security
&lt;/h1&gt;

&lt;p&gt;gRPC supports natively &lt;a href="https://grpc.io/docs/guides/auth.html" rel="noopener noreferrer"&gt;2 mechanisms&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SSL/TLS&lt;/strong&gt;: this will encrypt all the data exchanged between the client and the server, and works at the channel level.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token-based authentication with Google&lt;/strong&gt;: aka OAuth2 tokens, and must be used on an encrypted channel.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SSL/TLS is a must have since Google doesn’t allow any unencrypted connections with its services. We won’t use token-based authentication, but a simple mechanism based on an API key to illustrate how work interceptors. By the way, &lt;a href="https://cloud.google.com/endpoints/docs/grpc/about-grpc" rel="noopener noreferrer"&gt;Google Cloud Endpoints&lt;/a&gt; uses also a similar mechanism to restrict access to their API.&lt;/p&gt;
&lt;h2&gt;
  
  
  SSL
&lt;/h2&gt;

&lt;p&gt;To generate SSL certificates for CA, client and server, just launch in post-api:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/cert/generate\_using\_openssl.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I’ve also put another sample script which uses &lt;a href="https://github.com/square/certstrap" rel="noopener noreferrer"&gt;certrap&lt;/a&gt;, a convenient tool provided by Foursquare.&lt;/p&gt;

&lt;p&gt;Once generated, the certificates use is &lt;a href="https://grpc.io/docs/guides/auth.html#nodejs" rel="noopener noreferrer"&gt;well-documented&lt;/a&gt; in the official gRPC site, basically:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const credentials = grpc.ServerCredentials.createSsl(  
 fs.readFileSync(\_\_dirname + ‘/cert/ca.crt’),  
 \[{  
   cert\_chain: fs.readFileSync(\_\_dirname + ‘/cert/server.crt’),  
   private\_key: fs.readFileSync(\_\_dirname + ‘/cert/server.key’)  
 }\], true);this.server.start("0.0.0.0:50051", credentials);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And on the client side:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const packageDefinition = protoLoader.loadSync(... + '/Post.proto');const  proto = grpc.loadPackageDefinition(packageDefinition);let credentials = grpc.credentials.createSsl(  
 fs.readFileSync(\_\_dirname + ‘/../cert/ca.crt’),  
 fs.readFileSync(\_\_dirname + ‘/../cert/client.key’),  
 fs.readFileSync(\_\_dirname + ‘/../cert/client.crt’)  
 );const options = {  
 "grpc.ssl\_target\_name\_override": "localhost",  
};const client = proto.sample.PostService(host, credentials, options);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;️&lt;strong&gt;Small tip 💡:&lt;/strong&gt; the certificates have been generated to use with localhost, so the option &lt;code&gt;grpc.ssl_target_name_override&lt;/code&gt; allows us to reuse the same certificates with a remote gRPC server. Without this option, you have to generate new certificate with the right domain name.&lt;/p&gt;
&lt;h2&gt;
  
  
  Sample authorization mechanism using interceptors
&lt;/h2&gt;

&lt;p&gt;Mali offers a great mechanism to intercept calls done to the API. You can intercept globally, at the service level, or at the operation level. In our case, Health service stays insecure, and we secure the PostService like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function **auth(apiKey: string)** {  
 return async function(ctx: any, next: any) {  
   const apiKeyProvided:string = ctx.request.get("x-api-key");  
   if (!apiKeyProvided || apiKeyProvided !== apiKey) {  
     throw new Error(‘invalid.apiKey’);  
   }  
   await next();  
  }  
}this.server = new Mali()  
this.server.addService("\[...\]/Post.proto", "PostService");  
this.server.use("PostService", **auth("myapikey")**);  
this.server.use({ PostService: { addPost, listPost } });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;On the client side, you can pass the API key, through metadata, globally:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import \* as grpc from 'grpc';const interceptorAuth:any = (options:any, nextCall:any) =&amp;gt;  
   new grpc.InterceptingCall(nextCall(options), {  
     start: function(metadata, listener, next) {  
       metadata.add(‘x-api-key’, API\_KEY);  
       next(metadata, listener);  
     }  
   });const client = new proto.sample.PostService(  
  host, credentials, {interceptors: \[interceptorAuth\]}  
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Or you can pass metadata at the operation level:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import \* as grpc from 'grpc';const metadata = new grpc.Metadata();  
metadata.add(‘x-api-key’, API\_KEY);client.listPosts({page: 1}, metadata, (err:any, response:any) =&amp;gt; {  
 console.log(‘Post list’, err, response);  
 });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Error handling
&lt;/h1&gt;

&lt;p&gt;With grpc-node, you have to catch all exceptions, which could quickly become a pain …. Fortunately, Mali catches exceptions for you and sends back to the graphQL server as an error.&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%2Flzkgvcfyh6e898ndobxk.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%2Flzkgvcfyh6e898ndobxk.png" alt="Error thrown by gRPC and send back using GraphQL API" width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Error thrown by gRPC and send back using GraphQL API&lt;/p&gt;
&lt;h1&gt;
  
  
  Deployment on K8
&lt;/h1&gt;

&lt;p&gt;Kubernetes doesn’t support gRPC health checks natively, but gRPC comes with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a sample &lt;a href="https://github.com/grpc/grpc/blob/master/doc/health-checking.md" rel="noopener noreferrer"&gt;proto contract&lt;/a&gt; to implement, with a &lt;strong&gt;Check&lt;/strong&gt; method.&lt;/li&gt;
&lt;li&gt;the tool &lt;a href="https://github.com/grpc-ecosystem/grpc-health-probe/" rel="noopener noreferrer"&gt;grpc-health-probe&lt;/a&gt; to install in your docker image, which will call the &lt;strong&gt;Check&lt;/strong&gt; method.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/grpc-ecosystem/grpc-health-probe/" rel="noopener noreferrer"&gt;grpc-health-probe&lt;/a&gt; needs to be configured to run with SSL and the command line is a bit long:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/bin/grpc\_health\_probe   
 -tls   
 -tls-server-name localhost   
 -tls-ca-cert cert/ca.crt   
 -tls-client-cert cert/client.crt   
 -tls-client-key cert/client.key   
 -addr=:4000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;So I’ve put it in a script called&lt;code&gt;bin/grpc-health-probe.sh&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Once the Check service up and running, you just need to configure k8 with:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spec:  
 containers:  
 - name: server  
  image: "\[YOUR-DOCKER-IMAGE\]"  
  ports:  
   - containerPort: 4000  
   readinessProbe:  
    exec:  
     command: \["/usr/src/app/src/bin/grpc\_health\_probe.sh", ":4000"\]  
     initialDelaySeconds: 5  
   livenessProbe:  
    exec:  
     command: \["/usr/src/app/src/bin/grpc\_health\_probe.sh", ":4000"\]  
     initialDelaySeconds: 10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

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

&lt;p&gt;gRPC and GraphQL work great together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GraphQL is in charge of setting up a contract with the outside world,&lt;/li&gt;
&lt;li&gt;while gRPC is in charge of communication between micro-services within the company.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not all gRPC libraries are at the same level, both in terms of documentation and code. Better reading the doc carefully (proto version, authentication, interceptor support) before starting with a library.&lt;br&gt;&lt;br&gt;
For Nodejs, server-side interceptors are sorely lacking in the official library.&lt;/p&gt;

&lt;p&gt;Fortunately, Mali offers a very good alternative.&lt;/p&gt;

&lt;p&gt;Retrieve the project on Github:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/svengau" rel="noopener noreferrer"&gt;
        svengau
      &lt;/a&gt; / &lt;a href="https://github.com/svengau/grpc-graphql-sample" rel="noopener noreferrer"&gt;
        grpc-graphql-sample
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      grpc / graphql sample project
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;gRPC / graphQL sample project&lt;/h1&gt;

&lt;/div&gt;

&lt;p&gt;this PoC will allow us to create blog posts, and is composed with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a &lt;strong&gt;graphQL server&lt;/strong&gt;, in front of the client as our unique BFF entry point. Its role is mainly to validate input data (required / optional fields, type, …) and filter output data. The validation here is important since required &amp;amp; optional fields have been dropped from proto3. It also acts as a client to the gRPC micro-service.&lt;/li&gt;
&lt;li&gt;a &lt;strong&gt;gRPC server&lt;/strong&gt;, to perform all functional operations. Here to create and list some blog posts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To run the PoC, install NodeJs, Mongodb and Git, and launch the following commands:&lt;/p&gt;

&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;git clone git@github.com:svengau/grpc-graphql-sample.git
cd post-api &amp;amp;&amp;amp; npm start
cd graphql-api &amp;amp;&amp;amp; npm start
🚀 Server ready at http://localhost:4000/graphql
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and run the following query:&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;mutation {
 addPost(data: { title: "helloooo" }) {
   message
   result { _id title body }
 }
}
```
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/svengau/grpc-graphql-sample" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;And Happy coding ! 😎&lt;/p&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://grpc.io/docs/quickstart/node.html" rel="noopener noreferrer"&gt;https://grpc.io/docs/quickstart/node.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/protocol-buffers/docs/overview" rel="noopener noreferrer"&gt;https://developers.google.com/protocol-buffers/docs/overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/grpc-ecosystem/awesome-grpc" rel="noopener noreferrer"&gt;https://github.com/grpc-ecosystem/awesome-grpc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://opensource.googleblog.com/2015/02/introducing-grpc-new-open-source-http2.html" rel="noopener noreferrer"&gt;https://opensource.googleblog.com/2015/02/introducing-grpc-new-open-source-http2.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>graphql</category>
      <category>kubernetes</category>
      <category>grpc</category>
    </item>
  </channel>
</rss>
