<?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: Audrey Roy Greenfeld</title>
    <description>The latest articles on DEV Community by Audrey Roy Greenfeld (@audreyfeldroy).</description>
    <link>https://dev.to/audreyfeldroy</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%2F129155%2Fe14af08a-faeb-43bb-98a9-ee6529015f7f.jpg</url>
      <title>DEV Community: Audrey Roy Greenfeld</title>
      <link>https://dev.to/audreyfeldroy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/audreyfeldroy"/>
    <language>en</language>
    <item>
      <title>Announcing the Margarita Humanitarian Foundation Developer Blog</title>
      <dc:creator>Audrey Roy Greenfeld</dc:creator>
      <pubDate>Sun, 03 Oct 2021 03:01:21 +0000</pubDate>
      <link>https://dev.to/mhf/announcing-the-margarita-humanitarian-foundation-developer-blog-3h0i</link>
      <guid>https://dev.to/mhf/announcing-the-margarita-humanitarian-foundation-developer-blog-3h0i</guid>
      <description>&lt;p&gt;This blog is a friendly place for developers involved with Margarita Humanitarian Foundation's open source projects to share coding tips and tricks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;help&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;others&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{...}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  All Our GitHub Contributors Invited
&lt;/h2&gt;

&lt;p&gt;This offer is open to anyone who's had 1 or more pull requests merged into a project in the &lt;a href="https://github.com/margaritahumanitarian/"&gt;@margaritahumanitarian&lt;/a&gt; GitHub organization.&lt;/p&gt;

&lt;p&gt;If you're not a contributor yet, see our repos for issues to work on. We welcome everyone! You can also ask for help getting started in &lt;a href="https://discord.gg/kf3SKPMm"&gt;https://discord.gg/kf3SKPMm&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Write About
&lt;/h2&gt;

&lt;p&gt;Anything that's fun or useful to other coders! For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TIL posts (Today I Learned)&lt;/li&gt;
&lt;li&gt;Tips for getting into open source&lt;/li&gt;
&lt;li&gt;Even super-short posts are fine, such as little React or Tailwind CSS tricks plus accompanying screenshots&lt;/li&gt;
&lt;li&gt;Dev tricks that you want to keep notes on to remember later&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Is Margarita Humanitarian Foundation?
&lt;/h2&gt;

&lt;p&gt;We're a nonprofit public charity helping those who need help the most. For more info, see &lt;a href="https://www.margaritahumanitarian.org/"&gt;margaritahumanitarian.org&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>opensource</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Join Me at PyCon Asia Pacific 2020 Online</title>
      <dc:creator>Audrey Roy Greenfeld</dc:creator>
      <pubDate>Thu, 10 Sep 2020 19:46:21 +0000</pubDate>
      <link>https://dev.to/audreyfeldroy/join-me-at-pycon-asia-pacific-2020-online-56gk</link>
      <guid>https://dev.to/audreyfeldroy/join-me-at-pycon-asia-pacific-2020-online-56gk</guid>
      <description>&lt;p&gt;&lt;a href="https://pycon.my/"&gt;PyCon APAC (Asia Pacific)&lt;/a&gt; is a major Python conference held every year in a different country in Asia, this year in Malaysia as a virtual online conference.&lt;/p&gt;

&lt;p&gt;I'll be speaking in 2 sessions:&lt;/p&gt;

&lt;h2&gt;
  
  
  Special Interview: Audrey Feldroy
&lt;/h2&gt;

&lt;p&gt;Chee Yim Goh, director of Women Who Code Kuala Lumpur and cofounder of IdealHub, will be interviewing me. Join us as we share stories about teaching in the Python world, talk about my Python books and projects, and more.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Malaysian Standard Time&lt;/th&gt;
&lt;th&gt;Pacific Standard Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Saturday, Sept. 19, 2020 from 11:20am-12pm&lt;/td&gt;
&lt;td&gt;Friday, Sept. 18, 2020 from 8:20-9pm&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BOI-_VZT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/nr20x7fo7ce8rvjpgcab.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BOI-_VZT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/nr20x7fo7ce8rvjpgcab.png" alt="19th-1120-1200-interview-audrey"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Python Patterns for the Future
&lt;/h2&gt;

&lt;p&gt;This is the main panel at PyCon APAC. As the Python web framework person and as the creator of the open-source project Cookiecutter (over 500k monthly downloads), I'll be sharing my insights on where Python is headed over the next 3-5 years and beyond.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Malaysian Standard Time&lt;/th&gt;
&lt;th&gt;Pacific Standard Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sunday, Sept. 20, 2020 from 10-11am&lt;/td&gt;
&lt;td&gt;Saturday, Sept. 19, 2020 from 7-8pm&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iZOrS9sH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rmz80ruira2x95m1uca1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iZOrS9sH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rmz80ruira2x95m1uca1.png" alt="20th-1000-1100-main-panel"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Watch
&lt;/h2&gt;

&lt;p&gt;PyCon APAC 2020 is a livestream that anyone can attend remotely. Get a &lt;a href="https://pycon-apac-2020-online.peatix.com/"&gt;ticket&lt;/a&gt; for MYR20.00 ($4.79 US), then follow their email instructions to access the &lt;a href="https://pycon.my/pycon-apac-2020-event-calendar/"&gt;talks on the event calendar&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>python</category>
      <category>events</category>
      <category>pycon</category>
      <category>conferences</category>
    </item>
    <item>
      <title>Turn a REST API into a GraphQL API</title>
      <dc:creator>Audrey Roy Greenfeld</dc:creator>
      <pubDate>Mon, 27 Apr 2020 06:46:18 +0000</pubDate>
      <link>https://dev.to/feldroy/turn-a-rest-api-into-a-graphql-api-50kf</link>
      <guid>https://dev.to/feldroy/turn-a-rest-api-into-a-graphql-api-50kf</guid>
      <description>&lt;p&gt;I really like working with GraphQL APIs. I like being able to get data in the shape I want, and using subscriptions to get it in realtime. This weekend I discovered that transforming a REST API into a GraphQL one is easier than it sounds.&lt;/p&gt;

&lt;p&gt;This is a walkthrough of turning one REST endpoint to GraphQL. Once you can do one, you can do more 😀&lt;/p&gt;

&lt;h2&gt;
  
  
  The REST API Endpoint We'll Transform
&lt;/h2&gt;

&lt;p&gt;To keep things simple, we'll use a simple GET REST endpoint as our starting point:&lt;/p&gt;

&lt;p&gt;GET &lt;a href="https://pokeapi.co/api/v2/pokemon/pikachu/"&gt;https://pokeapi.co/api/v2/pokemon/pikachu/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's create a GraphQL endpoint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Define the GraphQL Schema for a Pokemon Object
&lt;/h2&gt;

&lt;p&gt;First we define our GraphQL type for the Pokemon data we'll be returning from our new API endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type Pokemon {
  id:       String!
  name:     String!
  base_experience:  Int!
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the sake of example, we're limiting the fields, but add more if you want.&lt;/p&gt;

&lt;h2&gt;
  
  
  Define the GraphQL Query Type
&lt;/h2&gt;

&lt;p&gt;Then we define a GraphQL query called &lt;code&gt;getPokemon&lt;/code&gt; that takes an &lt;code&gt;id&lt;/code&gt; and returns a &lt;code&gt;Pokemon&lt;/code&gt; object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type Query {
  getPokemon(id: String!): Pokemon
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Define the Query Resolver
&lt;/h2&gt;

&lt;p&gt;When a &lt;code&gt;getPokemon&lt;/code&gt; GraphQL query comes in, under the hood of our resolver, we send a GET request to &lt;code&gt;/pokemon/&amp;lt;id&amp;gt;/&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;const resolvers = {
  Query: {
      getPokemon: async (_, { id }) =&amp;gt; {

          const response = await fetch(MY_REST_URL + '/pokemon/' + id + '/');
          return response.json();
      },
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Try the Query in GraphQL Playground
&lt;/h2&gt;

&lt;p&gt;A copy of the above code is &lt;a href="https://glitch.com/edit/#!/audreyr-pokemon-remote-schema"&gt;editable here on Glitch&lt;/a&gt;, and running &lt;a href="https://audreyr-pokemon-remote-schema.glitch.me/"&gt;live here with interactive querying via GraphQL Playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go to GraphQL Playground and try the query we just created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;query {
  getPokemon(id: "pikachu"){
    id
    base_experience
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It responds with real data from PokeAPI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "data": {
    "getPokemon": {
      "id": "25",
      "base_experience": 112
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yay! As a practice exercise, try implementing another field besides &lt;code&gt;base_experience&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Remix my Glitch app&lt;/li&gt;
&lt;li&gt;Add the field to the &lt;code&gt;Pokemon&lt;/code&gt; schema&lt;/li&gt;
&lt;li&gt;Add it to your query and see the results in GraphQL Playground&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--z2FELErr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rkibazax5pwy70oqb38e.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--z2FELErr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rkibazax5pwy70oqb38e.jpg" alt="You Can Do It"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With this knowledge and a little practice, there's so much you can do. Enjoy!&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>graphql</category>
      <category>javascript</category>
    </item>
    <item>
      <title>JAMStack Fun: Combining StackBit, Forestry, Netlify, Gatsby, Hasura, Glitch</title>
      <dc:creator>Audrey Roy Greenfeld</dc:creator>
      <pubDate>Wed, 22 Apr 2020 08:21:06 +0000</pubDate>
      <link>https://dev.to/feldroy/jamstack-fun-combining-stackbit-forestry-netlify-gatsby-hasura-glitch-58g</link>
      <guid>https://dev.to/feldroy/jamstack-fun-combining-stackbit-forestry-netlify-gatsby-hasura-glitch-58g</guid>
      <description>&lt;p&gt;For days 6-7 of #100DaysOfCode, I did various &lt;a href="https://www.netlify.com/products/forms/"&gt;JAMStack&lt;/a&gt; experiments with SaaS and open-source tools, putting them together to see what would happen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trying Out Stackbit
&lt;/h2&gt;

&lt;p&gt;I signed up for a &lt;a href="https://www.stackbit.com/"&gt;Stackbit&lt;/a&gt; account and used their site builder to create a project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Theme: Azimuth&lt;/li&gt;
&lt;li&gt;Site generator: &lt;a href="https://www.gatsbyjs.org/"&gt;Gatsby&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;CMS: &lt;a href="https://forestry.io/"&gt;Forestry&lt;/a&gt; (Always wanted to try it!)&lt;/li&gt;
&lt;li&gt;Deployment: GitHub repository with Netlify build + deploy (the only current options available. I look forward to Gitlab coming soon!)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I connected my Forestry and GitHub accounts.&lt;/p&gt;

&lt;p&gt;Stackbit says it deployed my site. Ooh, it's really live:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EnLCGmCl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/afdfa3ahstpi4s0ift3o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EnLCGmCl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/afdfa3ahstpi4s0ift3o.png" alt="My deployed Stackbit static site"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I clicked &lt;em&gt;Claim&lt;/em&gt; to claim the Netlify project. It worked, yay.&lt;/p&gt;

&lt;p&gt;Then I clicked &lt;em&gt;Edit in Forestry&lt;/em&gt; to edit the content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trying Out Forestry
&lt;/h2&gt;

&lt;p&gt;Forestry provides a GUI for editing Gatsby content. It also supports Hugo, Gridsome, Jekyll, and other static site generators.&lt;/p&gt;

&lt;p&gt;It's pretty cool, and I could see it being useful for people who can't build their static site locally or are editing from a mobile device.&lt;/p&gt;

&lt;p&gt;The lag between updating a site via Forestry and seeing the new deployed version on Netlify was a few minutes. For my purposes, I find running &lt;code&gt;npm run develop&lt;/code&gt; easier because I can see the static site changes on localhost in seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding a Netlify Function
&lt;/h2&gt;

&lt;p&gt;Next I added a &lt;a href="https://www.netlify.com/products/functions/"&gt;Netlify function&lt;/a&gt;. Initially it'll do almost nothing, but I could see it implementing something dynamic and server-side like what you would expect of an Express or Django web application.&lt;/p&gt;

&lt;p&gt;I cloned the GitHub repo, then created a Netlify function by copying &lt;a href="https://kentcdodds.com/blog/super-simple-start-to-serverless"&gt;functions/hello.js&lt;/a&gt; by &lt;a class="mentioned-user" href="https://dev.to/kentcdodds"&gt;@kentcdodds&lt;/a&gt;
 into my project. I added it to my build in &lt;em&gt;netlify.toml&lt;/em&gt;. Then I git committed and then went to Netlify to watch the build go.&lt;/p&gt;

&lt;p&gt;Now that the function's deployed, it's here:&lt;br&gt;
&lt;a href="https://curious-rosemary-e8299.netlify.app/.netlify/functions/hello?name=Uma"&gt;https://curious-rosemary-e8299.netlify.app/.netlify/functions/hello?name=Uma&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Whatever you pass into &lt;code&gt;name&lt;/code&gt; gets shown on the page by the function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// functions/hello.js from https://kentcdodds.com/blog/super-simple-start-to-serverless&lt;/span&gt;
&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queryStringParameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;World&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Hello &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'd like to expand this into something real and maybe have it get triggered by a form submission via a &lt;a href="https://www.netlify.com/products/forms/"&gt;Netlify form&lt;/a&gt; like the &lt;code&gt;contactForm&lt;/code&gt; provided by the sample code. But in the interest of time, I'm saving that for another day to focus on getting the Gatsby site to display dynamic remote API data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Experimenting with Gatsby
&lt;/h2&gt;

&lt;p&gt;It's been years since I last used React, so getting Gatsby to do what I wanted was a challenge. My hope at this point was to replicate what a Django &lt;code&gt;ListView&lt;/code&gt; does in JAMstack.&lt;/p&gt;

&lt;p&gt;I created an &lt;code&gt;items.js&lt;/code&gt; page to play in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Hello!
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, I looked into populating the page with dynamic data. If I could grab data onto this static page from a remote GraphQL endpoint, that would be great.&lt;/p&gt;

&lt;p&gt;Gatsby uses GraphQL, so I started with using that as test data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Items List &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;siteMetadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;This is a static site, but it's loading items dynamically from GraphQL:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;siteMetadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nav_links&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;graphql&lt;/span&gt;&lt;span class="s2"&gt;`
  query {
    site {
      siteMetadata {
        header {
          nav_links {
            label
          }
        }
      }
    }
  }
`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setting Up a GraphQL API with Hasura
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://hasura.io/"&gt;Hasura&lt;/a&gt; is an open-source, Heroku-deployable tool that can take existing databases and give you a GraphQL API. &lt;/p&gt;

&lt;p&gt;I did the first part of the Hasura tutorial and loved it. Now I have a &lt;em&gt;todos&lt;/em&gt; table I can query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;query MyQuery {
  todos {
    id
    title
  }
}

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

&lt;/div&gt;



&lt;p&gt;The response from Hasura with my sample data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="err"&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="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;todos&lt;/span&gt;&lt;span class="err"&gt;":&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="err"&gt;":&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="err"&gt;":&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;My&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;First&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Todo&lt;/span&gt;&lt;span class="err"&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="err"&gt;":&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="err"&gt;":&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Todo&lt;/span&gt;&lt;span class="err"&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="err"&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="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Adding a New Gatsby GraphQL Root
&lt;/h2&gt;

&lt;p&gt;I did an &lt;code&gt;npm install gatsby-source-graphql&lt;/code&gt; then added my Hasura GraphQL API to &lt;em&gt;gatsby-config.js&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;I see that the &lt;a href="https://www.gatsbyjs.org/docs/third-party-graphql/#basic-example"&gt;example from the Gatsby docs&lt;/a&gt; points at &lt;a href="https://api.graphcms.com/simple/v1/swapi"&gt;https://api.graphcms.com/simple/v1/swapi&lt;/a&gt; which is down. &lt;/p&gt;

&lt;p&gt;Looks like that site, &lt;a href="https://graphcms.com/"&gt;GraphCMS&lt;/a&gt;, was featured on ProductHunt today...I'll sign up and see if they have an updated sample endpoint. Hmm, it looks like an interesting rabbit hole for another day.&lt;/p&gt;

&lt;p&gt;In Hasura, I went to &lt;code&gt;Remote Schemas &amp;gt; *Try it with Glitch*&lt;/code&gt; and found &lt;a href="https://hasura-sample-remote-schema.glitch.me"&gt;hasura-sample-remote-schema.glitch.me/ &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With &lt;a class="mentioned-user" href="https://dev.to/danielfeldroy"&gt;@danielfeldroy&lt;/a&gt;
's help we added the new root to &lt;em&gt;gatsby-config.js&lt;/em&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="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="err"&gt;resolve:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gatsby-source-graphql"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="err"&gt;options:&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;This&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;will&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;contain&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;remote&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;schema&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;type&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="err"&gt;typeName:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"query"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;This&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;field&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;under&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;which&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;it's&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;accessible&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="err"&gt;fieldName:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hasuraSample"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;URL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;from&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="err"&gt;url:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://hasura-sample-remote-schema.glitch.me/"&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="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then he figured out this query worked in Glitch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;query {
  hello 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;a href="http://127.0.0.1:8000/___graphql"&gt;http://127.0.0.1:8000/___graphql&lt;/a&gt; we got this query to work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;query {hasuraSample {
  hello
}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Showing Remote GraphQL Data on a Gatsby Page
&lt;/h2&gt;

&lt;p&gt;Finally, I updated &lt;em&gt;items.js&lt;/em&gt; to be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Items List&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;This is a static site, but it's loading items dynamically from GraphQL:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasuraSample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hello&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;graphql&lt;/span&gt;&lt;span class="s2"&gt;`
  query {hasuraSample {
    hello
  }}
`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that, &lt;a href="http://localhost:8000/items"&gt;http://localhost:8000/items&lt;/a&gt; now shows a static Gatsby page with the live data from the Glitch-hosted Hasura Sample Remote Schema!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lGn3qDXE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wky9toai3mqr5vpjhl8j.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lGn3qDXE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wky9toai3mqr5vpjhl8j.jpg" alt="JAMstack: Putting It All Together"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It was really fun to play around and put all these JAMstack toys together, particularly the ones that auto-configured themselves and auto-deployed. Every piece served a purpose and did it well. That was cool!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>gatsby</category>
      <category>graphql</category>
      <category>100daysofcode</category>
    </item>
    <item>
      <title>Day 5 of #100DaysOfCode: Dev.to Cover Image Generator</title>
      <dc:creator>Audrey Roy Greenfeld</dc:creator>
      <pubDate>Mon, 20 Apr 2020 06:45:41 +0000</pubDate>
      <link>https://dev.to/feldroy/day-5-of-100daysofcode-dev-to-cover-image-generator-2g6l</link>
      <guid>https://dev.to/feldroy/day-5-of-100daysofcode-dev-to-cover-image-generator-2g6l</guid>
      <description>&lt;p&gt;Tonight I created this cover image generator: &lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/audreyfeldroy/embed/rNOMxad?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;It uses JavaScript to draw on an HTML5 canvas.&lt;/p&gt;

&lt;p&gt;To change the text:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fork this on CodePen: &lt;a href="https://codepen.io/audreyfeldroy/pen/rNOMxad"&gt;https://codepen.io/audreyfeldroy/pen/rNOMxad&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;In the JS panel, change the lines with &lt;code&gt;ctx.fillText&lt;/code&gt; to be the text you want.&lt;/li&gt;
&lt;li&gt;Break any long lines into two lines, or shrink the fonts.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You'll probably also want to change:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The colors&lt;/li&gt;
&lt;li&gt;The fonts&lt;/li&gt;
&lt;li&gt;The parameters of the fractal tree&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Have fun! I'd love to see what you create, so please share your posts/forks in the comments below.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>codepen</category>
      <category>meta</category>
      <category>html</category>
    </item>
    <item>
      <title>Day 4 of #100DaysOfCode: Building My First Square App with Glitch</title>
      <dc:creator>Audrey Roy Greenfeld</dc:creator>
      <pubDate>Sun, 19 Apr 2020 00:25:44 +0000</pubDate>
      <link>https://dev.to/feldroy/day-4-of-100daysofcode-taking-orders-via-an-express-square-app-2d1l</link>
      <guid>https://dev.to/feldroy/day-4-of-100daysofcode-taking-orders-via-an-express-square-app-2d1l</guid>
      <description>&lt;p&gt;Today I built my first working Square app!&lt;/p&gt;

&lt;p&gt;I started with Square's official &lt;a href="https://github.com/square/connect-api-examples/tree/master/connect-examples/v2/node_orders-payments"&gt;Order-Ahead Sample App&lt;/a&gt;, a Node/Express project.&lt;/p&gt;

&lt;p&gt;Following its accompanying &lt;a href="https://developer.squareup.com/docs/orders-api/quick-start/start"&gt;tutorial in the Square docs&lt;/a&gt;:&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;I created an Order Ahead app in &lt;a href="https://developer.squareup.com/apps/"&gt;https://developer.squareup.com/apps/&lt;/a&gt; (you need a &lt;a href="//squareup.com/i/EATSWADESH"&gt;Square account&lt;/a&gt; to do this)&lt;/p&gt;

&lt;p&gt;I updated &lt;code&gt;config.json&lt;/code&gt; with the sandbox app ID and token.&lt;/p&gt;

&lt;p&gt;Running &lt;code&gt;npm test&lt;/code&gt; failed. I did &lt;code&gt;npm install&lt;/code&gt; and tried again. It worked:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm test

&amp;gt; order-ahead-sample-app@0.0.0 test /Users/arg/projects/3rd-party/connect-api-examples/connect-examples/v2/node_orders-payments
&amp;gt; NODE_ENV=sandbox node ./bin/www
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  First Local Run
&lt;/h2&gt;

&lt;p&gt;I went to &lt;a href="http://localhost:3000/"&gt;http://localhost:3000/&lt;/a&gt; and saw a page with "Sandbox Location Business Nickname" at the top. Yay, the app runs locally!&lt;/p&gt;
&lt;h2&gt;
  
  
  Generating Test Data
&lt;/h2&gt;

&lt;p&gt;I ran the example script to seed the sandbox store catalog with test data. It generated a bunch of restaurant food items:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm run seed

&amp;gt; order-ahead-sample-app@0.0.0 seed /Users/arg/projects/3rd-party/connect-api-examples/connect-examples/v2/node_orders-payments
&amp;gt; NODE_ENV=sandbox node ./bin/script/seed-catalog.js generate

Successfully uploaded item: #Italian Sandwich
Successfully uploaded item: #Steak Tacos
Successfully uploaded item: #Autumn Soup
Successfully uploaded item: #Sunny-Side Egg on Toast
Successfully uploaded item: #Fried Chicken Sandwich
Successfully uploaded item: #Salmon with Zucchini
Successfully uploaded item: #Oatmeal with Fruit
Successfully uploaded item: #Mediterranean Yogurt Bowl
Successfully uploaded item: #Meatballs
Successfully uploaded item: #Pancakes with Fruit
Successfully uploaded item: #Bacon Cheeseburger
Successfully uploaded item: #Grilled Steak
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Placing a Sample Order
&lt;/h2&gt;

&lt;p&gt;Restarting the local server with &lt;code&gt;npm test&lt;/code&gt;, I now see those test items. I can click them to see a pop-up with detail and a &lt;em&gt;Buy This&lt;/em&gt; button:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--w9-SoZh5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zz6fqhg6bbuu0scbro3h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--w9-SoZh5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zz6fqhg6bbuu0scbro3h.png" alt="Detail pop-up for Fried Chicken Sandwich"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clicking &lt;em&gt;Buy This&lt;/em&gt; leads to &lt;em&gt;Choose Delivery Method&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--d8LmQ1CN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/nx1zx4gq4xdergvcegz4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d8LmQ1CN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/nx1zx4gq4xdergvcegz4.png" alt="Choose Delivery Method"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Under &lt;em&gt;Delivery Method&lt;/em&gt;, the only option is &lt;em&gt;Pickup&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Under &lt;em&gt;Pickup Location&lt;/em&gt;, the only option is &lt;em&gt;Sandbox Location Business Nickname&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The next screen was &lt;em&gt;Review and Complete Your Order&lt;/em&gt;. I entered the &lt;a href="https://developer.squareup.com/docs/orders-api/quick-start/step-4"&gt;test card&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PnlRKJrs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zaaf3m3zyrh8ll0ecp3d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PnlRKJrs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zaaf3m3zyrh8ll0ecp3d.png" alt="Review and Complete Your Order page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I clicked &lt;em&gt;Pay with Card&lt;/em&gt; and it gave me this &lt;em&gt;Order Confirmation&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lUsO9G8Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/5571lbv42t29rof6tzvu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lUsO9G8Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/5571lbv42t29rof6tzvu.png" alt="Order Confirmation"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Verifying the Order in the Sandbox
&lt;/h2&gt;

&lt;p&gt;Sure enough, the order shows up under Orders:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uhiFFod0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4pd9apa2alskhm5k93z5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uhiFFod0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4pd9apa2alskhm5k93z5.png" alt="Order Detail"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I can mark it &lt;em&gt;In Progress&lt;/em&gt;, then &lt;em&gt;Ready&lt;/em&gt;, then &lt;em&gt;Picked Up&lt;/em&gt; using the upper right button.&lt;/p&gt;

&lt;p&gt;That's great that the sample Square app works locally.&lt;/p&gt;
&lt;h2&gt;
  
  
  Getting It Running on Glitch
&lt;/h2&gt;

&lt;p&gt;I made a copy of the node_orders-payments folder as OrderAhead.&lt;/p&gt;

&lt;p&gt;I copied &lt;a href="https://github.com/github/gitignore/blob/master/Node.gitignore"&gt;GitHub's Node.gitignore&lt;/a&gt; as the project .gitignore.&lt;/p&gt;

&lt;p&gt;The code's now in a GitHub repo: &lt;a href="https://github.com/feldroy/OrderAhead"&gt;https://github.com/feldroy/OrderAhead&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In Glitch, I clicked &lt;em&gt;New Project&lt;/em&gt; &amp;gt; &lt;em&gt;Clone from Git Repo&lt;/em&gt; and pasted in &lt;code&gt;git@github.com:feldroy/OrderAhead.git&lt;/code&gt;. The screen went black and it didn't like that. I tried again with &lt;a href="https://github.com/feldroy/OrderAhead.git"&gt;https://github.com/feldroy/OrderAhead.git&lt;/a&gt; and that worked.&lt;/p&gt;

&lt;p&gt;The Square tutorial had me put credentials into &lt;code&gt;config.json&lt;/code&gt; earlier, which I .gitignored. I moved those to &lt;code&gt;.env&lt;/code&gt; and now load them from there in &lt;code&gt;util/square-connect-client.js&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;const config = {
  "path": "https://connect.squareupsandbox.com",
  "squareApplicationId": process.env.SQUARE_APPLICATION_ID,
  "squareAccessToken": process.env.SQUARE_ACCESS_TOKEN
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here's the Glitch app:&lt;/p&gt;


&lt;div class="glitch-embed-wrap"&gt;
  &lt;iframe src="https://glitch.com/embed/#!/embed/orderahead?path=index.html" alt="orderahead on glitch"&gt;&lt;/iframe&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  The Deployed Demo Site
&lt;/h2&gt;

&lt;p&gt;You can experiment with this and even place test orders using the &lt;a href="https://developer.squareup.com/docs/orders-api/quick-start/step-4"&gt;demo credit card&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Play with the live demo: &lt;a href="https://orderahead.glitch.me/"&gt;https://orderahead.glitch.me/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, if you're new to Square, &lt;a href="//squareup.com/i/EATSWADESH"&gt;here's an invite&lt;/a&gt; to get free processing on up to $1,000 in credit card transactions for the first 180 days.&lt;/p&gt;

</description>
      <category>express</category>
      <category>square</category>
      <category>node</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Day 3 of #100DaysOfCode: JS Fractals in CodePen and Observable</title>
      <dc:creator>Audrey Roy Greenfeld</dc:creator>
      <pubDate>Sat, 18 Apr 2020 03:57:46 +0000</pubDate>
      <link>https://dev.to/feldroy/day-3-of-100daysofcode-js-fractals-in-codepen-and-observable-obp</link>
      <guid>https://dev.to/feldroy/day-3-of-100daysofcode-js-fractals-in-codepen-and-observable-obp</guid>
      <description>&lt;p&gt;Yesterday I saw &lt;a class="mentioned-user" href="https://dev.to/lautarolobo"&gt;@lautarolobo&lt;/a&gt;'s tutorial on &lt;a href="https://dev.to/lautarolobo/use-javascript-and-html5-to-code-a-fractal-tree-2n69"&gt;coding fractal trees in JS&lt;/a&gt;, and I knew I had to try it. Besides, it's Fractal Friday!&lt;/p&gt;

&lt;p&gt;I opened up CodePen and was going to use HAML, then realized that the Pug HTML processor was available. Why not try Pug while I'm at it, right? My Pug code was nice and short:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;h1 Fractal Tree
canvas#my_canvas(width="1000", height="800")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I gave the canvas a nice light gray background so I could see the bounds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#my_canvas { background-color: #efefef; }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I defined the recursive &lt;code&gt;draw()&lt;/code&gt; function as per the first tree version in &lt;a class="mentioned-user" href="https://dev.to/lautarolobo"&gt;@lautarolobo&lt;/a&gt;'s tutorial, where each execution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Moves to &lt;code&gt;startX&lt;/code&gt;, &lt;code&gt;startY&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Draws a line of length &lt;code&gt;len&lt;/code&gt;, angle &lt;code&gt;angle&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Calls itself to draw left and right branches until &lt;code&gt;len&lt;/code&gt; &amp;lt; 10&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/audreyr/embed/jObrOXm?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;I brought the code over to Observable and hooked it up to sliders controlling the two values that were hardcoded: the ratio of new branch length to old, and the angle at which a new branch sprouts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I got the slider code from &lt;a href="https://observablehq.com/@kuquanghuylcb/fractal-tree" rel="noopener noreferrer"&gt;Huy Nguyen's Fractal Tree notebook&lt;/a&gt; which is similar to this but more configurable.&lt;/li&gt;
&lt;li&gt;I could have implemented this in CodePen but it would have been much more verbose than in Observable (&lt;em&gt;I think&lt;/em&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fm7by7iwcwubr0e3r6kom.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fm7by7iwcwubr0e3r6kom.png" alt="Observable Notebook with JavaScript Fractal Tree"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above is just a screenshot because I don't think you can embed live running code on dev.to (unless I'm wrong?). Check out the interactive slider version: &lt;a href="https://observablehq.com/@audreyr/fractal-tree-1" rel="noopener noreferrer"&gt;https://observablehq.com/@audreyr/fractal-tree-1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, I experimented with different left vs. right branch ratios back in CodePen and got some pretty results. Here's left &lt;code&gt;branchPercent&lt;/code&gt; 0.5, right 0.8:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fj7zu4hhpfujimgxhuxr2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fj7zu4hhpfujimgxhuxr2.png" alt="Fractal Tree, Leaning Right"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>fractals</category>
      <category>javascript</category>
      <category>canvas</category>
      <category>100daysofcode</category>
    </item>
    <item>
      <title>Day 2 of #100DaysOfCode: Playing With Stripe, Tailwind, and Vue</title>
      <dc:creator>Audrey Roy Greenfeld</dc:creator>
      <pubDate>Fri, 17 Apr 2020 06:59:43 +0000</pubDate>
      <link>https://dev.to/feldroy/day-2-of-100daysofcode-playing-with-stripe-tailwind-and-vue-cmk</link>
      <guid>https://dev.to/feldroy/day-2-of-100daysofcode-playing-with-stripe-tailwind-and-vue-cmk</guid>
      <description>&lt;p&gt;I know I was supposed to start Day 2 with debugging that &lt;code&gt;fs&lt;/code&gt; error from Day 1, but I was really dreading that. I'll pick that up sometime in the future when I'm ready.&lt;/p&gt;

&lt;p&gt;I got started coding late in the day, and my brain was too tired to do much. I almost gave up. But because of the challenge, I felt like I should try to code something fun.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1du7zfi1tzixxe5cazo2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1du7zfi1tzixxe5cazo2.jpg" alt="Imagine yourself as a kid"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I decided to play with Stripe Elements, Tailwind CSS, and Vue.js today on Glitch. I remixed my &lt;a href="https://glitch.com/~vuejs-tailwind-starter" rel="noopener noreferrer"&gt;vuejs-tailwind-starter&lt;/a&gt; project to create &lt;em&gt;Subscribe to be Featured&lt;/em&gt;, a simple app where people or companies can subscribe to have their names listed on the page. It doesn't work yet, but you can see and play with the code here: &lt;a href="https://glitch.com/edit/#!/subscribetobefeatured" rel="noopener noreferrer"&gt;https://glitch.com/edit/#!/subscribetobefeatured&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My husband &lt;a class="mentioned-user" href="https://dev.to/danielfeldroy"&gt;@danielfeldroy&lt;/a&gt; joined me, pair-programming with me through Glitch, which is like a shared Google Doc but for code editing. It was a nice little coding date while our daughter was asleep.&lt;/p&gt;

&lt;p&gt;Thanks &lt;a class="mentioned-user" href="https://dev.to/danielfeldroy"&gt;@danielfeldroy&lt;/a&gt; for your help, and for helping me get going when I felt too worn out to code. 💘&lt;/p&gt;

&lt;p&gt;My tips of the day:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://nerdcave.com/tailwind-cheat-sheet" rel="noopener noreferrer"&gt;Nerdcave's Tailwind Cheat Sheet&lt;/a&gt; is awesome.&lt;/li&gt;
&lt;li&gt;Derick Sozo's article &lt;a href="https://alligator.io/vuejs/stripe-elements-vue-integration/" rel="noopener noreferrer"&gt;Integrating Stripe Elements and Vue.js to Set Up a Custom Payment Form&lt;/a&gt; was helpful today.&lt;/li&gt;
&lt;li&gt;I liked working with plain Tailwind + PostCSS in CodePen first to allow for fast visual iteration, then bringing over the element to my full JS app in Glitch once I got the styling right. Glitch ran a bit slow, even with the app boosted. It may be my fault for not having the most optimized &lt;code&gt;package.json&lt;/code&gt; scripts, though.&lt;/li&gt;
&lt;li&gt;Having played with both over the past week, &lt;a href="https://stripe.com/" rel="noopener noreferrer"&gt;Stripe&lt;/a&gt; subscriptions have a lot of features, flexibility, and come with gorgeous widgets, but &lt;a href="https://paddle.com/" rel="noopener noreferrer"&gt;Paddle&lt;/a&gt; subscriptions have decent widgets and are much easier to get started with. I do like both payment platforms.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>100daysofcode</category>
      <category>stripe</category>
      <category>tailwindcss</category>
      <category>vue</category>
    </item>
    <item>
      <title>Day 1 of #100DaysOfCode: Trying Out Tanker for End-to-End Encryption</title>
      <dc:creator>Audrey Roy Greenfeld</dc:creator>
      <pubDate>Thu, 16 Apr 2020 06:59:27 +0000</pubDate>
      <link>https://dev.to/feldroy/day-1-of-100daysofcode-trying-out-tanker-for-end-to-end-encryption-4g2o</link>
      <guid>https://dev.to/feldroy/day-1-of-100daysofcode-trying-out-tanker-for-end-to-end-encryption-4g2o</guid>
      <description>&lt;p&gt;For the longest time, it's been on my bucket list to figure out how to implement end-to-end encryption for web apps. So I'm starting with it as my first day of #100DaysOfCode.&lt;/p&gt;

&lt;p&gt;I did a quick search and discovered &lt;a class="mentioned-user" href="https://dev.to/dmerejkowsky"&gt;@dmerejkowsky&lt;/a&gt;'s post on &lt;a href="https://dev.to/tanker/taking-mastodon-security-to-the-next-level-part-1-encrypt-your-toots-2p00"&gt;adding end-to-end encryption to Mastodon&lt;/a&gt;. He uses Tanker's API to encrypt Mastodon direct messages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tanker.io/" rel="noopener noreferrer"&gt;Tanker&lt;/a&gt; looks promising:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwqgkk2i9as629mx9ir9g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwqgkk2i9as629mx9ir9g.png" alt="Tanker"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I followed Tanker's &lt;a href="https://docs.tanker.io/latest/tutorials/encrypt-decrypt-web/" rel="noopener noreferrer"&gt;Encrypt and decrypt data in a web app&lt;/a&gt; tutorial, converting it from React to Vue as I went along.&lt;/p&gt;

&lt;p&gt;I remixed &lt;a href="https://glitch.com/edit/#!/vuejs-tailwind-starter" rel="noopener noreferrer"&gt;https://glitch.com/edit/#!/vuejs-tailwind-starter&lt;/a&gt; to create a new Vue.js project with Tailwind CSS.&lt;/p&gt;

&lt;p&gt;I added my Tanker app ID to 🔑.env.&lt;/p&gt;

&lt;p&gt;In package.json &amp;gt; Add Package, I added:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;@tanker/client-browser&lt;/li&gt;
&lt;li&gt;@tanker/fake-authentication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I then added the imports as per the tutorial:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import FakeAuthentication from '@tanker/fake-authentication';
import { Tanker } from '@tanker/client-browser';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point I ran into the error &lt;code&gt;Module not found: Error: Can't resolve 'fs'&lt;/code&gt;. Commenting the second line out gets rid of the error. &lt;/p&gt;

&lt;p&gt;I tried installing graceful-fs which didn't help. Uninstalled it. Found a &lt;a href="https://support.glitch.com/t/fs-library-unable-to-be-installed/11590/5" rel="noopener noreferrer"&gt;Glitch forum post about fs&lt;/a&gt; that said fs is already part of node.js. &lt;/p&gt;

&lt;p&gt;In case memory might be the culprit, I upgraded to a paid Glitch subscription and boosted my app. That didn't help.&lt;/p&gt;

&lt;p&gt;At this point I'm stuck.&lt;/p&gt;

&lt;p&gt;That was a rough Day 1. I was hoping to at least get through the Tanker tutorial. If anyone wants to help debug this, here's the code: &lt;a href="https://glitch.com/edit/#!/morning-pages" rel="noopener noreferrer"&gt;https://glitch.com/edit/#!/morning-pages&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm also open to suggestions of other tools/libraries for web app end-to-end encryption.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>node</category>
      <category>e2ee</category>
    </item>
    <item>
      <title>#100DaysOfCode for the Experienced Developer</title>
      <dc:creator>Audrey Roy Greenfeld</dc:creator>
      <pubDate>Wed, 15 Apr 2020 03:41:27 +0000</pubDate>
      <link>https://dev.to/feldroy/100daysofcode-for-the-experienced-developer-22cm</link>
      <guid>https://dev.to/feldroy/100daysofcode-for-the-experienced-developer-22cm</guid>
      <description>&lt;p&gt;I've noticed that most people who do the #100DaysOfCode challenge are beginners learning to code. I've been coding for many years, so I wasn't sure if it was for me. &lt;/p&gt;

&lt;p&gt;Here's why I've decided to start the challenge:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Play With Cool New Toys
&lt;/h2&gt;

&lt;p&gt;There are so many fun developer tools that I haven't had a chance to try. For example, &lt;a class="mentioned-user" href="https://dev.to/vivgui"&gt;@vivgui&lt;/a&gt;
 told me about the joys of &lt;a href="https://tailwindcss.com/"&gt;Tailwind CSS&lt;/a&gt; back in 2018, and I only got around to learning it a few days ago. Whoa, its CSS classes make composing UIs so much fun! There's also collaborative JS coding tool &lt;a href="https://glitch.com/"&gt;Glitch&lt;/a&gt;, which &lt;a class="mentioned-user" href="https://dev.to/danielfeldroy"&gt;@danielfeldroy&lt;/a&gt;
 just got me into, and its cousin &lt;a href="https://observablehq.com/"&gt;Observable&lt;/a&gt; for JS notebooks. And there's the realtime GraphQL engine &lt;a href="https://hasura.io/"&gt;Hasura&lt;/a&gt; which I'm eager to play with more.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Make Fun Stuff
&lt;/h2&gt;

&lt;p&gt;Making stuff is fun. If I can't be at my local makerspace making art on the laser cutter, or in my art studio experimenting with messy mixed media painting, then at least I can code.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hard Part
&lt;/h2&gt;

&lt;p&gt;I'm not sure if an hour a day is really doable for me. The toddler, business, family obligations, and stress are already leaving me exhausted. I'll try for an hour, but if some days I can only do 10 minutes, that's still better than skipping a day.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overall Goal: Coding as Play
&lt;/h2&gt;

&lt;p&gt;It's easy to get caught up in the mentality of "Coding is work." My intention with this challenge is for it to be fun experimentation and play. If it's not fun, I'll stop doing it. I'm hoping it'll help me make time for personal fun every day.&lt;/p&gt;

&lt;p&gt;With that, I'm committing to #100DaysOfCode! Starting tomorrow I'll post about what I code each day.&lt;/p&gt;

</description>
      <category>100daysofcode</category>
      <category>css</category>
      <category>graphql</category>
      <category>javascript</category>
    </item>
    <item>
      <title>TIL: Put script tags in head and use the defer attribute</title>
      <dc:creator>Audrey Roy Greenfeld</dc:creator>
      <pubDate>Fri, 10 Apr 2020 11:13:42 +0000</pubDate>
      <link>https://dev.to/feldroy/til-put-script-in-head-and-use-its-defer-attribute-2ko8</link>
      <guid>https://dev.to/feldroy/til-put-script-in-head-and-use-its-defer-attribute-2ko8</guid>
      <description>&lt;p&gt;I noticed the starter webpage project on &lt;a href="https://glitch.com/"&gt;Glitch&lt;/a&gt; had this in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; section:&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;!-- import the webpage's javascript file --&amp;gt;
&amp;lt;script src="/script.js" defer&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I was surprised to see a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; section, since I thought the best practice was to put these before &lt;code&gt;&amp;lt;/body&amp;gt;&lt;/code&gt;. That couldn't be right...the Glitch devs seem to care about things like this. Then I saw the &lt;code&gt;defer&lt;/code&gt; attribute.&lt;/p&gt;

&lt;p&gt;MDN says about &lt;code&gt;defer&lt;/code&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This Boolean attribute is set to indicate to a browser that the script is meant to be executed after the document has been parsed, but before firing DOMContentLoaded.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://flaviocopes.com/javascript-async-defer/"&gt;Flavio Copes has a nice writeup on defer and async&lt;/a&gt;. My key takeaways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;defer&lt;/code&gt; only works in the &lt;code&gt;head&lt;/code&gt; section.&lt;/li&gt;
&lt;li&gt;With &lt;code&gt;defer&lt;/code&gt; the browser fetches the script in parallel with parsing the HTML. Even if the browser finishes fetching the script, it doesn't run it until it's done HTML parsing.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;defer&lt;/code&gt; not &lt;code&gt;async&lt;/code&gt; because parsing ideally should complete before script execution.&lt;/li&gt;
&lt;li&gt;The best practice is what Glitch does, shown above. Put &lt;code&gt;&amp;lt;script src="..." defer&amp;gt;&lt;/code&gt; in &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do you agree with this best practice?&lt;/p&gt;

</description>
      <category>todayilearned</category>
      <category>javascript</category>
      <category>html</category>
      <category>bestpractice</category>
    </item>
    <item>
      <title>TIL: The Best Way to Compress JPG Files with ImageMagick</title>
      <dc:creator>Audrey Roy Greenfeld</dc:creator>
      <pubDate>Thu, 09 Apr 2020 18:57:02 +0000</pubDate>
      <link>https://dev.to/feldroy/til-strategies-for-compressing-jpg-files-with-imagemagick-5fn9</link>
      <guid>https://dev.to/feldroy/til-strategies-for-compressing-jpg-files-with-imagemagick-5fn9</guid>
      <description>&lt;p&gt;Got a JPEG that's too big to upload?&lt;/p&gt;

&lt;p&gt;Lazy to open Photoshop?&lt;/p&gt;

&lt;p&gt;ImageMagick to the rescue!&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is ImageMagick?
&lt;/h2&gt;

&lt;p&gt;ImageMagick is a tool for editing images. When you install it, you can type &lt;code&gt;convert&lt;/code&gt; at the command line (followed by whatever parameters you want) to resize, optimize, distort, and draw on images.&lt;/p&gt;

&lt;p&gt;If you don't have it yet, follow the instructions at &lt;a href="https://imagemagick.org/" rel="noopener noreferrer"&gt;imagemagick.org&lt;/a&gt; to install it. (I did &lt;code&gt;brew install imagemagick&lt;/code&gt; to get it onto my Mac.)&lt;/p&gt;

&lt;h2&gt;
  
  
  How Do You Compress JPG Files With It?
&lt;/h2&gt;

&lt;p&gt;Honestly, every time I've needed to optimize images, I've always googled "imagemagick convert compress jpg" and copy-pasted from StackOverflow. &lt;/p&gt;

&lt;p&gt;Today I decided it's time to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Learn which &lt;code&gt;convert&lt;/code&gt; arguments/parameters are best for balancing quality with file size&lt;/li&gt;
&lt;li&gt;Write it up on here as a handy copy-paste reference for future me&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's now look at the top two ImageMagick JPEG compression strategies from &lt;a href="https://stackoverflow.com/questions/7261855/recommendation-for-compressing-jpg-files-with-imagemagick" rel="noopener noreferrer"&gt;this StackOverflow post&lt;/a&gt;, then try combining them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 1: Lighthouse Compression Strategy
&lt;/h3&gt;

&lt;p&gt;According to one StackOverflow poster, this strategy focuses on following Google Lighthouse's guide on how to pass the &lt;a href="https://developers.google.com/web/tools/lighthouse/audits/optimize-images" rel="noopener noreferrer"&gt;"Optimize Images" Lighthouse audit&lt;/a&gt; in Chrome DevTools:&lt;/p&gt;

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

convert feldroy-512x512-unoptimized.jpg \
-sampling-factor 4:2:0 \
-strip \
-quality 85 \
-interlace JPEG \
-colorspace RGB \
feldroy-512x512-pagespeed.jpg 


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

&lt;/div&gt;

&lt;p&gt;Note: Lighthouse was formerly &lt;em&gt;Google Pagespeed Insights&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 2: Gaussian Blur Strategy
&lt;/h3&gt;

&lt;p&gt;This strategy was the most upvoted post on StackOverflow due to its age (2011). It's also quite good. Blurring smooths out any high-frequency color and tonal changes:&lt;/p&gt;

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

convert feldroy-512x512-unoptimized.jpg \
-strip \
-interlace Plane \
-gaussian-blur 0.05 \
-quality 85% \
feldroy-512x512-gaussian.jpg


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  Option 3: Combined Strategy
&lt;/h3&gt;

&lt;p&gt;Combining the above 2 options, we get:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

convert feldroy-512x512-unoptimized.jpg \
-sampling-factor 4:2:0 \
-strip \
-quality 85 \
-interlace Plane \
-gaussian-blur 0.05 \
-colorspace RGB \
feldroy-512x512-combined.jpg 


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;As you can see, the combined strategy (Option 3) had the best results with my test JPEG:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ ls -lh
total 360
-rw-r--r--  1 arg  staff    23K Apr  9 10:55 feldroy-512x512-combined.jpg
-rw-r--r--  1 arg  staff    28K Apr  9 05:30 feldroy-512x512-gaussian.jpg
-rw-r--r--  1 arg  staff    27K Apr  9 05:21 feldroy-512x512-pagespeed.jpg
-rw-r--r--@ 1 arg  staff    95K Feb 24 06:57 feldroy-512x512-unoptimized.jpg


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

&lt;/div&gt;

&lt;p&gt;Looking at the original and resulting files side-by-side, they all looked good to me, though someone with better eyesight may be pickier:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcdrc5n9kdgn7t6jaa26a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcdrc5n9kdgn7t6jaa26a.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Other Things to Know
&lt;/h2&gt;

&lt;p&gt;You can also use ImageMagick to resize images to smaller pixel dimensions or even convert between file formats (like .png to .jpg). &lt;a href="https://dev.to/listnux/fun-with-imagemagick-57d1"&gt;Here's an article&lt;/a&gt; by &lt;a class="mentioned-user" href="https://dev.to/listnux"&gt;@listnux&lt;/a&gt; showing cool things you can do with it.&lt;/p&gt;

&lt;p&gt;Finally, if you have a better way to compress jpg files with ImageMagick &lt;code&gt;convert&lt;/code&gt; or even other tools, I'd love to hear your tips.&lt;/p&gt;

</description>
      <category>todayilearned</category>
      <category>imagemagick</category>
      <category>commandline</category>
    </item>
  </channel>
</rss>
