<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[codingraj's blog]]></title><description><![CDATA[loves to build small full stack apps in HTML, CSS, and JavaScript]]></description><link>https://blog.codingraj.dev</link><generator>RSS for Node</generator><lastBuildDate>Fri, 09 Oct 2026 06:59:32 GMT</lastBuildDate><atom:link href="https://blog.codingraj.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[The 10th Victim (1965)]]></title><description><![CDATA[3 ½ / 4 Stars
Link to the Talking Cinema podcast deep dive
Why I love this movie
I loved the score. Anything Italian-ish and whimsical, I like. I think whimsical scores are underrated. And they work in comedies that are not outright comedies. The whi...]]></description><link>https://blog.codingraj.dev/the-10th-victim-1965</link><guid isPermaLink="true">https://blog.codingraj.dev/the-10th-victim-1965</guid><category><![CDATA[Movies]]></category><category><![CDATA[movie review]]></category><dc:creator><![CDATA[codingraj]]></dc:creator><pubDate>Fri, 30 Sep 2022 17:08:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1664557530525/WgDGzKsDf.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1662929598708/rUuD_LVbB.png" alt="SpoilerAlert.png" /></p>
<h2 id="heading-3-4-stars">3 ½ / 4 Stars</h2>
<h2 id="heading-link-to-the-talking-cinema-podcast-deep-dive">Link to the <a href="https://podcast.talkingcinemapod.com/episodes/the-10th-victim-1965" target="_blank">Talking Cinema podcast deep dive</a></h2>
<h2 id="heading-why-i-love-this-movie">Why I love this movie</h2>
<p>I loved the score. Anything Italian-ish and whimsical, I like. I think whimsical scores are underrated. And they work in comedies that are not outright comedies. The whimsical scores let the audience know the tone of the movie. It helps them be in on the joke.</p>
<p>I love movies shot on film, and this movie, like all movies from the 60s, is shot on film.</p>
<p>I also like how Caroline, who is supposed to be American but speaks Italian (dubbed, by the way, which all or most Italian movies filmed during that time were). But with no accent. Which got me thinking, do any country other than American movies depict foreigners in the same language but with an accent? Like Schindler’s List is in English with a German accent.</p>
<p>I didn’t mind the dubbing. I’m used to it. One of my favorite movies is “The Good, The Bad And The Ugly”; that movie is poorly dubbed. I thought about it while watching this movie on Plex, which is dubbed in English, but I like the Italian language too much.</p>
<p>I love the costumes and set design. I think this movie may have been more influential to Austin Powers than the Beatles’ movie “Help.”</p>
<p>But I also think this government controls everything in our lives. One of the sub-themes in the movie is that the government is controlling our lives - confiscating items from people’s homes, taking old people away from society, and locking them up. </p>
<p>And old people are a problem? I wonder if it is because of health care costs. Or that young and middle age people don’t like old people. I think it’s true, by the way. I think the government and people in charge in general, which are usually made up of old people, don’t like old people. It is just that people in power think they are different and not that old.</p>
<p>And I love the ending before the ending. And I think it would have been a better ending. But maybe not. They fell in love, but it was more lust than love. They still killed each other, or at least they thought. Caroline had doubts and was pressured to kill because the cameras were rolling, but Marcello gave Caroline a gun with blanks without her knowing. But Marcello just flat-out killed her, if it wasn’t for her body armor. He wasn’t pressured.</p>
<p>And would a forced marriage of two people who aren’t good and evil (I think both Marcello and Caroline don’t care about much) even last long? But Marcello is a man’s man, and Caroline wants a man’s man. She likes the company of effeminate men, but she doesn’t want to be with one of them.</p>
<p>I love this movie, not 4 out of 4 stars but 3 ½ out of 4 stars. Which is still very good.</p>
<h2 id="heading-favorite-scenes">Favorite Scenes</h2>
<ol>
<li>Caroline is starting to be conflicted when they transport the beach studio/home. You know she is having doubts about killing Marcello.</li>
<li>Marcello laughed when Caroline outsmarted him and had a gun pointing at him. The best defense is laughter. Accept death. It’s a nice fuck you.</li>
<li>Caroline is happy that Marcello is not dead. The money and fame are not what she wants. She wants a relationship. She wants a man. And not just any man, but a man’s man. When you’re in love, you always make mistakes.</li>
<li>My first thought - I loved how she shot him, and we thought Marcello died. Then I loved that he killed her. And wanted to kill her. I think the movie should have ended there - it would have been a sad ending, but better.</li>
</ol>
<h2 id="heading-flaws">Flaws</h2>
<p>I think the shootout with Olga and Lidia was just bad. But the movie is supposed to be ridiculous, and I think Elio Petri, the director, didn’t want to kill one or both of the leads.</p>
<h2 id="heading-writing">Writing</h2>
<p>The script is good, but I think the set design, acting, and mood carry the movie.</p>
<p>“An enemy a day keeps the doctor away.”</p>
<p>“I like effeminate men. They’re ideal friends for women. They’re great company. Have you ever been like them?”</p>
<h2 id="heading-directingeditingsound">Directing/Editing/Sound</h2>
<p>From a technical level, it is great. All around. The camera movement and angles are incredible. It reminds me of the Coen brothers and Scorsese movies.</p>
<h2 id="heading-acting">Acting</h2>
<p>The acting is great. And playing it seriously with less dialogue with the main leads actually makes it more compelling to watch. Especially on rewatch.</p>
]]></content:encoded></item><item><title><![CDATA[On Her Majesty's Secret Service (1969)]]></title><description><![CDATA[3 ½ / 4 Stars
Link to the Talking Cinema podcast deep dive
Why I love this movie
The first hour is so good. It moves fast. We don’t even know Bond’s mission until about 45 - 60 minutes into the movie. I love that.
I also like that this is similar to ...]]></description><link>https://blog.codingraj.dev/on-her-majestys-secret-service-1969</link><guid isPermaLink="true">https://blog.codingraj.dev/on-her-majestys-secret-service-1969</guid><category><![CDATA[Movies]]></category><category><![CDATA[movie review]]></category><category><![CDATA[James Bond]]></category><dc:creator><![CDATA[codingraj]]></dc:creator><pubDate>Fri, 23 Sep 2022 14:43:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1664030418286/eomAjPsOG.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1662929598708/rUuD_LVbB.png" alt="SpoilerAlert.png" /></p>
<h2 id="heading-3-4-stars">3 ½ / 4 Stars</h2>
<h2 id="heading-link-to-the-talking-cinema-podcast-deep-dive">Link to the <a href="https://podcast.talkingcinemapod.com/episodes/on-her-majestys-secret-service-1969" target="_blank">Talking Cinema podcast deep dive</a></h2>
<h2 id="heading-why-i-love-this-movie">Why I love this movie</h2>
<p>The first hour is so good. It moves fast. We don’t even know Bond’s mission until about 45 - 60 minutes into the movie. I love that.</p>
<p>I also like that this is similar to License to Kill, which shows Bond going rouge from central command.</p>
<p>It is a shame that the combination of Peter Hunt, the director, and George Lazenby, the actor that plays Bond, did not make another Bond movie. They would have gotten better if they had kept making Bond movies.</p>
<p>I also like the humor; the comedy is played up in the movie’s first half.</p>
<p>And I love how Bond works with the 2nd biggest criminal organization to go after the number 1 biggest criminal organization. Sometimes you have to work with bad guys who are competitors of other bad guys.</p>
<p>Then finally, and this applies to all Bond movies, is the score. The score is so good. It’s right up there with Indiana Jones and Back to the Future movies. The score really makes the movie better.</p>
<h2 id="heading-favorite-scenes">Favorite Scenes</h2>
<ol>
<li>The intro - the first seven minutes. It shows the physicalness of Bond. Bond can fight. And the humor of Bond. </li>
<li>The car ride to Draco’s place to the whistling of the little guy sweeping to the fight scene to having a drink with Draco. </li>
<li>Does Draco have a master plan for Bond to go after Blofeld and Spectre? I didn’t think about it until the movie’s end, but that seemed to be his main motive - not to get his daughter married or be in better health.</li>
<li>M and Ms. Moneypenny’s brilliant setup motivates Bond to go after the criminal.</li>
<li>The scene at the bullfighting event - Theresa is amazing. She is different than the other Bond girls. She gets her dad, Draco, to tell Bond what he wants. So Bond is now not obligated to play along for information. Theresa wants love - true love. Not to be caught in the middle of the mission.</li>
<li>The montage of them is romantic and funny. So good. Bond is playing the long game. But he only has two weeks, though. Bond is a romantic. He loves women. He doesn’t like just the sex, but he likes the wooing. This Bond does sleep with other women, but he wants to settle down with Theresa. It is genuine. </li>
<li>The set-piece to unlock the safe is brilliant. He decides to look at the playboy instead of the read the newspaper while waiting.</li>
<li>The villain - a lot like Dr. Evil.</li>
<li>Alpine room - Women all around the world just hanging out.</li>
</ol>
<h2 id="heading-flaws">Flaws</h2>
<p>The extended ski chase scene is too long and not suspenseful. The 2nd half is not as good as the 1st half.</p>
<h2 id="heading-writing">Writing</h2>
<p> Here are my favorite lines in the movie:</p>
<p>“Do not kill me, Mr. Bond. At least we’ve had a drink.  And then if you wish, I’ll give you another chance” - Draco.</p>
<p>“There is always something formal about the point of the pistol” - Bond.</p>
<p>“What she needs is a man to dominate her” - Draco.</p>
<p>“You must give me the name of your occultist” - Bond.</p>
<h2 id="heading-directingeditingsound">Directing/Editing/Sound</h2>
<p>The editing is great. The hand-to-hand combat scenes were ahead of their time. Fast cutting, which I normally don’t like - but I like it in this film, playing with the film speed, and the sound effects are fantastic. Many movies now do the same thing, but this movie seems like an early pioneer.</p>
<h2 id="heading-acting">Acting</h2>
<p>I really really liked George Lazenby as Bond. I think he gets too much criticism. It is hard to be sandwiched between Sean Connery and Roger Moore. But Lazenby has good looks, the physicalness, and his acting is good. Sure he doesn’t have long dialogue or a scene where he is shouting, but most Bond movies don’t have that.</p>
<p>Also, he does show some vulnerable-ness in the movie - the scene where he flys in the helicopter (you can tell he is nervous), after the ski chase at the skating rink (he is nervous because he is surrounded and he gets scared by one of the giant snow monsters), and the ending where he cries over the death of his newlywed wife.</p>
<p>This is a different James Bond. I want more of this Bond.</p>
]]></content:encoded></item><item><title><![CDATA[Licence to Kill (1988)]]></title><description><![CDATA[3 ½ / 4 Stars
Link to the Talking Cinema podcast deep dive
Why I love this movie
It’s a revenge movie, and I love revenge movies. And this is a different Bond movie. It’s darker than the other Bond movies. You could say that Skyfall is somewhat of a ...]]></description><link>https://blog.codingraj.dev/licence-to-kill-1988</link><guid isPermaLink="true">https://blog.codingraj.dev/licence-to-kill-1988</guid><category><![CDATA[Movies]]></category><category><![CDATA[movie review]]></category><category><![CDATA[James Bond]]></category><category><![CDATA[revenge movie]]></category><dc:creator><![CDATA[codingraj]]></dc:creator><pubDate>Fri, 16 Sep 2022 14:00:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1663269959012/ihOrMUYx7.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1662929598708/rUuD_LVbB.png" alt="SpoilerAlert.png" /></p>
<h2 id="heading-3-4-stars">3 ½ / 4 Stars</h2>
<h2 id="heading-link-to-the-talking-cinema-podcast-deep-dive">Link to the <a href="https://podcast.talkingcinemapod.com/episodes/licence-to-kill-1988" target="_blank">Talking Cinema podcast deep dive</a></h2>
<h2 id="heading-why-i-love-this-movie">Why I love this movie</h2>
<p>It’s a revenge movie, and I love revenge movies. And this is a different Bond movie. It’s darker than the other Bond movies. You could say that Skyfall is somewhat of a dark movie with a revenge element, but Licence to Kill is flat-out a revenge movie.</p>
<p>And it’s a revenge movie, and this is a spoiler if you have been listening to this pod (we give spoilers), but Bond kills the villain at the end. No prison, have someone else kill him, or have the bad guy kill himself. Bond even tells the bad guy, Sanchez, why he is killing him. All the elements you need that are in a revenge movie, at least for my definition.</p>
<p>And this movie wastes no time, especially the first half. In the first 15 minutes, you are introduced to Bond, his friend Felix (and his wife, which ends up getting killed), who gets severely injured, and the bad guy. From there, you know what the movie is going to be. And Bond has no time to be the funny, witting guy. He is on a mission, but not from his boss. It is his own mission. He wants revenge.</p>
<h2 id="heading-favorite-scenes">Favorite Scenes</h2>
<p>The first 8 minutes are off the hook. From the coast guard helicopter to the DEA handing a gun to Felix and then having them run, I think in slow motion, to get Sanchez. To Bond, with the strange look from the DEA and Coast Guard, performing a death-defying stunt to capture Sanchez’s plane.</p>
<p>The shark scene where Feliz gets severely hurt. I love the line - “See you in hell.” Felix just knows he is going to hell even though he is a good guy.</p>
<p>A short scene, but the look on Bond’s face when he finds out the bad guys killed Sharky. Bond was already on a mission to get revenge. Now the bad guys just turned it up a notch.</p>
<p>The scene with Q. Q is also in on this rouge mission too. He loves Bond. And he knows that Bond needs his help. It might be the most extensive that Q has been used in a Bond mission. Pretty cool. </p>
<p>Also, I love all the scenes with Benicio del Toro, who plays Dario - Sanchez’s henchman. Watching an actor play a small role in a movie before they get big is fun. And Del Toro has had a great career with The Usual Suspects, Snatch, Traffic (he won an oscar for that role), and Sicario.</p>
<p>The drug scene is where they mix it with petrol or some solution. Pretty ingenious idea.</p>
<h2 id="heading-flaws">Flaws</h2>
<p>I could probably go with a shorter action set piece at the end. I’m not a big-action set-piece type of guy. But it’s the 80s and a Bond movie, so it is known to have action sequences. Also, this movie has a teenage audience, so you have to include that. But I do like this movie predates Fast and Furious, because a lot of that action at the end is very Fast and the Furious.</p>
<p>The movie would have been better served if it ended with Sanchez being lit on fire. But I guess you needed to see if Felix survived and if Bond ended up with Lupe or Pam.</p>
<h2 id="heading-writing">Writing</h2>
<p>Great script. Simple plot, but you don’t need something complicated for a revenge movie. I love how they set up what the movie is about right from the beginning. </p>
<p>Some of the lines by Pam, played by Carey Lowell, are a little weak. I don’t think it’s her fault. Movies from that time just had underdeveloped women characters. But Carey Lowell looks great. The same with Lupe, played by Talisa Soto.</p>
<h2 id="heading-directingeditingsound">Directing/Editing/Sound</h2>
<p>This movie is directed by John Glen - who directed 5 James Bond movies. This was his last one and probably his best.  He also edited 3 other Bond movies -  On Her Majesty's Secret Service (1969), The Spy Who Loved Me (1977), and Moonraker (1979) - so he has a lot of experience making James Bond movies.</p>
<h2 id="heading-acting">Acting</h2>
<p>Timothy Dalton makes a great Bond. I think he got too much criticism for playing this role. It is just hard to follow Sean Connery and Roger Moore. The latter being a great all-time actor and the former having the great looks and timing to play Bond. But Dalton has the good looks and that edge to him - which serves him well in this movie because it is a darker movie.</p>
<p>I think because this movie was a disappointment compared to previous Bond movies, they wanted to do a reboot. They didn’t do another bond movie until six years after Licence to Kill.</p>
<p>And I think they wanted to reboot it to give it more humor and less dark.</p>
<h2 id="heading-other">Other</h2>
<p>Bond has a lot of fans, but what I find interesting is how many people are interested in the casting of Bond. That is like it’s another whole thing in itself. It’s like the casting of Bond is its own headline. It has cultural significance. Even politicians would remark on who is playing Bond. 
It’s like Bond represents the type of guy we should honor and even strive to be, which can be problematic. Bond is a womanizer, but he does it for the mission.</p>
]]></content:encoded></item><item><title><![CDATA[Web3 Use Case - Charities]]></title><description><![CDATA[Web3 Use Case - Charities
The Problem
You have money and want to use it to make the world a better place. Giving money to a charity seems like a good idea. They have people that have dedicated their lives to helping others. Giving money to a charity ...]]></description><link>https://blog.codingraj.dev/web3-use-case-charities</link><guid isPermaLink="true">https://blog.codingraj.dev/web3-use-case-charities</guid><category><![CDATA[4articles4weeks]]></category><category><![CDATA[Web3]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[#week4]]></category><dc:creator><![CDATA[codingraj]]></dc:creator><pubDate>Sun, 11 Sep 2022 21:55:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1662933079464/BTItRzzGx.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-web3-use-case-charities">Web3 Use Case - Charities</h2>
<h3 id="heading-the-problem">The Problem</h3>
<p>You have money and want to use it to make the world a better place. Giving money to a charity seems like a good idea. They have people that have dedicated their lives to helping others. Giving money to a charity will help more people than using your money to help people directly.</p>
<p>But is that money being used to help people in need? Is that money being used effectively, where the services the charity provides are helping people?</p>
<p>The first part, the money used to help the people in need, is the part web3, and blockchain can bring some transparency. The second part, the funds used effectively to help people, is a little tougher to solve and won’t be addressed in this article (or <a target="_blank" href="https://web3inplainenglish.transistor.fm/">pod</a>).</p>
<h3 id="heading-the-solution">The Solution</h3>
<p>The blockchain can be used as a public ledger to track the money donated to the charity and where that money is getting spent.</p>
<p>The benefits of the blockchain are that it is public, and any transaction that gets recorded on the blockchain can’t be deleted or edited.</p>
<ol>
<li>So imagine if someone wanted to donate money to a charity that helps pay for a family’s energy bills. </li>
<li>There is a charity that only accepts cryptocurrencies as their donation, and that donation will be recorded on the blockchain.</li>
<li>The family sends the cryptocurrency to the charity, which is recorded on the blockchain.</li>
<li>The charity finds an eligible family that needs assistance with their energy bill.</li>
<li>The charity gets the family account number of the energy company that provides energy to that family.</li>
<li>The charity works with the energy company to help it accept cryptocurrency.</li>
<li>The charity sends the money to the energy company to pay for a family’s (or multiple families') energy bill. This transaction gets recorded on the blockchain along with the families’ account numbers.</li>
<li>The charity takes a percentage of the money donated to pay for its administration.</li>
<li>The person who donated the money can look up online where the money went and see how much was used to pay for the families’ energy bills and how much was used for the charity’s administration.</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Vengeance (2022)]]></title><description><![CDATA[3 ½ / 4 Stars
Link to the Talking Cinema podcast deep dive
Why I love this movie
I came into this movie with low expectations. Actually, I came in with negative expectations. I thought it would be a blue state “know-it-all” who would make fun of the ...]]></description><link>https://blog.codingraj.dev/vengeance-2022</link><guid isPermaLink="true">https://blog.codingraj.dev/vengeance-2022</guid><category><![CDATA[Movies]]></category><category><![CDATA[movie review]]></category><category><![CDATA[mystery]]></category><category><![CDATA[slow burn]]></category><dc:creator><![CDATA[codingraj]]></dc:creator><pubDate>Fri, 09 Sep 2022 20:55:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1662929548273/06kH7_3QE.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1662929598708/rUuD_LVbB.png" alt="SpoilerAlert.png" /></p>
<h2 id="heading-3-4-stars">3 ½ / 4 Stars</h2>
<h2 id="heading-link-to-the-talking-cinema-podcast-deep-dive">Link to the <a href="https://podcast.talkingcinemapod.com/episodes/vengeance-2022" target="_blank">Talking Cinema podcast deep dive</a></h2>
<h2 id="heading-why-i-love-this-movie">Why I love this movie</h2>
<p>I came into this movie with low expectations. Actually, I came in with negative expectations. I thought it would be a blue state “know-it-all” who would make fun of the red state “dimwit” and that it would be a fake vengeance movie. The type of vengeance movie where there is no vengeance.</p>
<p>I was wrong. Yes, there was blue-state/red-state comedy, but then it became a mystery.</p>
<p>And I’ll give the ending away since I do give away spoilers since this movie review (and <a href="https://podcast.talkingcinemapod.com/episodes/vengeance-2022" target="_blank">pod</a>) is a deep dive, and you can’t do a deep dive if you don’t talk about the plot, the twists, and the ending.</p>
<p>But I never thought the character, Ben, played by B.J. Novak, would kill the bad guy. I never thought B.J. Novak would write a character that he would play himself that would kill another character. But he did. The balls of him to make a movie that makes fun of himself - because I think he did write the character to show that Ben is a loser. Not a bad guy. But a guy who is a big city snob. He only cares for himself. He cares only about his work, hooking up with chicks, wanting to be a voice that others hear and become famous in that elite academic way, and having a lot of fun with alcohol, parties, and more sex. Your classic workaholic hedonist that many upper middle classic liberal school graduates want to be.</p>
<p>That is why I love this movie. B.J. Novak decides to make fun of himself and people like him, and he doesn’t shy away from being a vengeance movie. And for it to be a legit good vengeance movie, you have to kill the person at the end. No way around it. No jail time. No bad guy is killing himself. You have to kill the bad guy or have the bad guy kill the good guy while the good tries to kill the bad guy. That is it. And B.J. Novak follows through with it.</p>
<h2 id="heading-favorite-scenes">Favorite Scenes</h2>
<ol>
<li>When it gets to Texas, it gets good. The funeral is great. The funeral has a picture of Ben. You can’t even see the dead girl’s face. Ben thinks of things to say, and he pulls it off. Short and sweet, all while ad-libbing the whole thing.</li>
<li>I love the guns in the truck. I think B.J. Novak fell in love with the red state.</li>
<li>Calling his producer Eloise - I think a single person’s dream is drinking, being on the internet, and living in a $2 million apartment. Not sure if they are making fun of that person that lives in that apartment. I’ll be honest, because I have a kid, and I’m in my 40s, and I don’t want to rule the world like I used to, but when I see people live like that, I just feel sorry for them. I feel like they live an empty life, and I wonder if B.J. Novak and Issa Rae, who plays Eloise, know that. That is why they made that apartment so outrageous - clean looking, expensive, great furniture, her drinking wine on the couch, face mask, nice clothes. Eloise calls him out - his life is empty. All he cares about is being an intellectual, hooking up, and being famous.</li>
<li>“Dead white girl, the holy grail of podcasts.” - Eloise</li>
<li>I never liked Ashton Kushner, but he is great in this movie. But it is obvious that he is the bad guy or the secret good guy. There are very few movies where a famous actor plays a small role at the beginning of the movie, and they don’t turn up to be bigger later in the movie. I can think of one movie - Inside Man, directed by Spike Lee, which has Willem Dafoe in a small, no-nothing role.</li>
<li>“You’re wasting my time, I might as well waste yours” - Gangster Sancholo.</li>
<li>“Why I like Whataburger, it’s always there.”</li>
<li>The scene where Shaw’s family is waiting for Ben after he checks out of the hospital. He is surprised that they are waiting for him. Also, I liked how they didn’t play up that scene. They could have made it gut-wrenching with crying, but it was kept low-key. I liked it.</li>
<li>The vengeance scene. I would prefer the shooting scene with no music playing. And maybe more of a darker tone. But that is just me picking on it. I was more surprised that he pulled it off. He shot him. And missed because he is not a guy with any experience with guns. The chances of missing the shot would be more realistic. I do wonder if Ben will suffer from PTSD because of this. Killing someone is not something you can just brush off.</li>
<li>In the end scene, Sharon Shaw, Abilene’s mom, played by J. Smith-Cameron, talks about life is about regret. It starts with regrets and ends with regrets. And the in-between is all regrets — very good dialogue.</li>
</ol>
<h2 id="heading-flaws">Flaws</h2>
<p>Quinten, played by Ashton Kutcher, was a great character. But it was flawed. I don’t think he would so brazenly give away to Ben that he is the one that left Abilene to die from a drug overdose. </p>
<p>Sure Quinten could have gotten away with it, as he said, but it would have ruined his reputation. Also, is he involved with dealing drugs? That would get him in trouble. </p>
<p>Or maybe he thought Ben would not have gone through with the podcast because of the scrutiny the Shaw family would have gotten. And Ben would want to protect his career and reputation and never release the pod.</p>
<p>I thought the Whataburger scene in the parking lot was a little much. But I think the movie needed one angry rant about the blue versus red states. Also, I think it needed to play up that Ben can be condescending douche.</p>
<h2 id="heading-writing">Writing</h2>
<p>The script is good because of its ending. The jokes and light-heartedness in the beginning make the ending so much better.</p>
<h2 id="heading-directingeditingsound">Directing/Editing/Sound</h2>
<p>B.J. Novak can direct. I would have liked a darker ending. No music score. But other than that. No complaints. I loved the Texas landscape. It makes good cinematography. </p>
<h2 id="heading-acting">Acting</h2>
<p>The stand-outs are the cast that plays the Shaw family. Everybody is so good — I love Boyd Holbrook at Ty Shaw and the mom, played by J. Smith-Cameron. J. Smith-Cameron has a small role, but she is great in this movie.</p>
<p>And B.J. Novak is great. He doesn’t go over the top. And that is smart. There is no woe in me with his character.</p>
]]></content:encoded></item><item><title><![CDATA[Meet my Latest Project - I Built "ideas by robot" using HTML, CSS, and Vanilla JS; and I Learned How to Build a 3rd party API]]></title><description><![CDATA[Meet my latest project - I built "ideas by robot" using HTML, CSS, and Vanilla JS
Meet my latest project - ideas by robot
I love movies. So much so, I have a podcast where I do a deep dive on movies I love - Talking Cinema.
I love building web apps t...]]></description><link>https://blog.codingraj.dev/meet-my-latest-project-i-built-ideas-by-robot-using-html-css-and-vanilla-js-and-i-learned-how-to-build-a-3rd-party-api</link><guid isPermaLink="true">https://blog.codingraj.dev/meet-my-latest-project-i-built-ideas-by-robot-using-html-css-and-vanilla-js-and-i-learned-how-to-build-a-3rd-party-api</guid><category><![CDATA[4articles4weeks]]></category><category><![CDATA[#week3]]></category><category><![CDATA[GPT 3]]></category><category><![CDATA[APIs]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[codingraj]]></dc:creator><pubDate>Mon, 05 Sep 2022 04:33:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1662351431093/N39oVf31B.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-meet-my-latest-project-i-built-ideas-by-robot-using-html-css-and-vanilla-js">Meet my latest project - I built "ideas by robot" using HTML, CSS, and Vanilla JS</h1>
<h2 id="heading-meet-my-latest-project-ideas-by-robothttpsideasbyrobotnetlifyapp">Meet my latest project - <a target="_blank" href="https://ideasbyrobot.netlify.app/">ideas by robot</a></h2>
<p>I love movies. So much so, I have a podcast where I do a deep dive on movies I love - <a target="_blank" href="https://talkingcinema.transistor.fm/">Talking Cinema</a>.</p>
<p>I love building web apps that I would use myself.</p>
<p>I love to write and have always wanted to write a screenplay.</p>
<p>So I created an app that helps you develop movie ideas - a one-sentence science fiction movie plot.</p>
<h2 id="heading-front-end-github-repohttpsgithubcomcoding-island-jsideas-by-robot-frontend">Front-End (<a target="_blank" href="https://github.com/coding-island-js/ideas-by-robot-frontend">GitHub repo</a>)</h2>
<p>This front end is as simple as it gets. I used HTML, CSS, and Vanilla Javascript. That’s it. It’s amazing what you can build with no front-end framework.</p>
<p>The webpage has one button that makes a fetch request for a one-sentence movie plot to the back-end server and retrieves that request to display on the front-end.</p>
<h2 id="heading-back-end-github-repohttpsgithubcomcoding-island-jsideas-by-robot-backend">Back-End (<a target="_blank" href="https://github.com/coding-island-js/ideas-by-robot-backend">GitHub repo</a>)</h2>
<p>I built an express nodeJS server for the back-end. I used GOT for my HTTP request library.</p>
<p>I send some sample prompts to the GPT-3 API so the AI knows what I am asking for and expecting in return. </p>
<p>In this case, I want the AI to send me a one-sentence science fiction movie plot.</p>
<p>After sending the prompts to the GPT-3 API, I get a one-sentence movie plot from the AI. The movie plot then gets sent back to the front-end, ready to be displayed on the web page.</p>
<h2 id="heading-summing-it-up-tldr">Summing it up (TL;DR)</h2>
<ol>
<li>Created a Front-End with HTML, CSS, and Vanilla JS<ol>
<li>One button to fetch a science fiction movie plot from the back-end</li>
</ol>
</li>
<li>Created a Back-End express NodeJS server<ol>
<li>Used the GOT library to communicate with the GPT-3 API</li>
<li>Send the request back to the Front-End to display the one-sentence movie plot on the web page</li>
</ol>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[When I’m stuck coding, what do I do?]]></title><description><![CDATA[When I’m stuck coding, what do I do?
I get stuck all the time when I’m coding. Actually, I get stuck and look for answers or workarounds online more than I do coding. Probably at a 3:1 ratio of troubleshooting to coding.
Here is an example of me look...]]></description><link>https://blog.codingraj.dev/when-im-stuck-coding-what-do-i-do</link><guid isPermaLink="true">https://blog.codingraj.dev/when-im-stuck-coding-what-do-i-do</guid><category><![CDATA[Firebase]]></category><category><![CDATA[4articles4weeks]]></category><category><![CDATA[#week2]]></category><category><![CDATA[Stack Overflow]]></category><category><![CDATA[Google]]></category><dc:creator><![CDATA[codingraj]]></dc:creator><pubDate>Sun, 28 Aug 2022 16:59:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1661705661412/afuGymn8N.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-when-im-stuck-coding-what-do-i-do">When I’m stuck coding, what do I do?</h1>
<p>I get stuck all the time when I’m coding. Actually, I get stuck and look for answers or workarounds online more than I do coding. Probably at a 3:1 ratio of troubleshooting to coding.</p>
<p>Here is an example of me looking for an answer and finding one.</p>
<h2 id="heading-problem">Problem</h2>
<p>I’m building an app using Firebase for my authentication. I use Firebase JWTs to ensure the user is logged in and has permission to access the app.</p>
<p>Firebase uses a JSON file containing a secret key for verifying the JWT on my backend server.</p>
<p>I don’t want to put the JSON file containing the secret key in my repository, which is a no-no.</p>
<p>One solution is to put the JSON file as an environmental variable in the .ENV file.</p>
<p>However, the JSON file has some special characters and blank spaces. When I run the code to verify the token, it fails because my code doesn’t read the variable correctly in the .ENV file.</p>
<h2 id="heading-solution">Solution</h2>
<h3 id="heading-google">Google</h3>
<p>I googled “firebase auth jwt environment variables.” The first results are from the Firebase Docs. I read the docs but didn’t find the solution.</p>
<p>So I go back to the google results and see some Stackoverflow solutions. I found one solution, but it was rather complex, and some people responded that this solution didn’t work for them.</p>
<p>I just need to be able to read the JSON data from the .ENV file. It got me thinking I should just google how to do that instead of including Firebase. Maybe this will get me more results that will work.</p>
<p>So I googled it again, but with a new search - “how to store JSON in env.” I got a result with a <a target="_blank" href="https://mitchum.blog/how-to-store-json-in-an-environment-variable/">blog</a> titled “How to Store JSON in an Environment Variable.”</p>
<p>This was a perfect solution. It recommended encoding the JSON with base64 and storing that in the .ENV file. And then, in the code, you decode the env variable containing the JSON secret key.</p>
<p>That worked!</p>
<h2 id="heading-summing-it-up-tldr">Summing it up (TL;DR)</h2>
<ol>
<li>When I run into problems, I do the following:<ol>
<li>Google<ol>
<li>Search Results<ol>
<li>Docs</li>
<li>Stackoverflow</li>
<li>Blogs</li>
</ol>
</li>
</ol>
</li>
</ol>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[What made me want to be a developer?]]></title><description><![CDATA[What made me want to be a developer?
As far back as I can remember, I always wanted to be a film director.

There is still a possibility that I can be a director. With YouTube, I can upload a short film that I recorded and edited on my phone…and voil...]]></description><link>https://blog.codingraj.dev/what-made-me-want-to-be-a-developer</link><guid isPermaLink="true">https://blog.codingraj.dev/what-made-me-want-to-be-a-developer</guid><category><![CDATA[Developer]]></category><category><![CDATA[4articles4weeks]]></category><category><![CDATA[week1]]></category><dc:creator><![CDATA[codingraj]]></dc:creator><pubDate>Sun, 21 Aug 2022 17:19:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1661102086492/F0ufChNfk.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-what-made-me-want-to-be-a-developer">What made me want to be a developer?</h1>
<p>As far back as I can remember, I always wanted to be a film director.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1661101853361/d_bqN62mI.gif" alt="good-fellas-henry.gif" /></p>
<p>There is still a possibility that I can be a director. With YouTube, I can upload a short film that I recorded and edited on my phone…and voilà, I am a director.</p>
<p>Being a developer is like being a director. A director creates. Well, a developer creates too.</p>
<h2 id="heading-i-want-to-build-stuff-to-improve-peoples-lives">I want to Build Stuff to Improve People’s Lives</h2>
<p>And with web development, the developer doesn’t even need a lot. It still amazes me that you need a text editor (I prefer VS Code) and a browser (Chrome), and you can create a fantastic web application. You don’t need a powerful computer or fancy developer tools.</p>
<p>I wanted to be a developer when I realized that a developer could create with basic (and free) tools.</p>
<p>I wanted to create and build stuff. And to help people improve their lives.</p>
<p>Being a developer allows me to do that. I can create a web app that can improve the lives of others.</p>
<p>My first web app was a breathing and meditation app — a simple app created with HTML, CSS, and JavaScript.</p>
<p>It satisfied the part of me that wants to build stuff. And it fulfilled the part of me that wants to help people - breathing and meditation can increase happiness and reduce anxiety.</p>
<p>Using my developer skillset, I can create web apps to help people that cost little money to myself and those I want to help. It does cost me time to learn the developer skills to build the web app. But that is time well spent, which leads me to the second reason I want to be a developer.</p>
<h2 id="heading-exercising-my-brain">Exercising my Brain</h2>
<p>Sometimes I can get in a rut and live on autopilot. I don’t do anything to push my brain. And that is not good. We need to exercise our brain so it doesn’t become mush. <a target="_blank" href="https://www.mollers.com/everyone-should-do-brain-exercise/">Exercising your brain helps prevent cognitive decline, increases mental capacity, and improves memory</a>. </p>
<p>I needed to challenge my brain, and when I got interested in wanting to build web apps - I found my brain exercise - coding.</p>
<p>Coding makes my brain exercise from aligning elements on the web page to figuring out how to save data to a database to set up a local and cloud environment for your web app. </p>
<p>There are days I want to shake my computer because I keep getting errors, but eventually, I figure out what is causing the issue or find a workaround that makes the issue obsolete. All of that is exercising my brain. And it doesn’t feel like a chore like physical exercise because I am also working on something I love - building stuff that helps other people.</p>
<h2 id="heading-summing-it-up-tldr">Summing it up (TL;DR)</h2>
<p>What made me want to be a developer?</p>
<p>To create and build stuff. Being a developer, I can make a web app with little monetary investment.</p>
<p>To help improve other people’s lives. Being a developer, I can create a breathing and meditation app. I am working on a web app where people can read stories of others receiving gratitude that AI generates. Reading gratitude stories can reduce anxiety, increase motivation, and be optimistic.</p>
]]></content:encoded></item><item><title><![CDATA[Web3 Use Cases - Smart Contracts to Reward Your Kids]]></title><description><![CDATA[Web3 Use Cases - Smart Contracts to Reward Your Kids
The Problem
Your son or daughter wants a new e-bike or something rather expensive. As a parent, you don’t want to spoil your kids with costly gifts they may or may not use.
But kids persist and wil...]]></description><link>https://blog.codingraj.dev/web3-use-cases-smart-contracts-to-reward-your-kids</link><guid isPermaLink="true">https://blog.codingraj.dev/web3-use-cases-smart-contracts-to-reward-your-kids</guid><category><![CDATA[Web3]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[Smart Contracts]]></category><dc:creator><![CDATA[codingraj]]></dc:creator><pubDate>Tue, 16 Aug 2022 16:48:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1660668454185/mLbIx_u4t.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-web3-use-cases-smart-contracts-to-reward-your-kids">Web3 Use Cases - Smart Contracts to Reward Your Kids</h1>
<h2 id="heading-the-problem">The Problem</h2>
<p>Your son or daughter wants a new e-bike or something rather expensive. As a parent, you don’t want to spoil your kids with costly gifts they may or may not use.</p>
<p>But kids persist and will keep begging, persuading you to buy them that gift.</p>
<p>So you make a deal with your kid that if they get straight A’s, you will buy them an e-bike.</p>
<p>From the kid’s perspective - you get straight A’s, and your parents still don’t buy you that e-bike. They say the e-bike is too dangerous, which they may have a point, but they did break their word.</p>
<p>And the parents will say that we didn’t have a formal contract and we're just joking or saying it so you would concentrate on your grades.</p>
<p>The parents and kids could have made a contract, but who will enforce that? The parents can just disregard the agreement.</p>
<h2 id="heading-the-solution">The Solution</h2>
<p>That is where the smart contract could solve this problem.</p>
<p>A smart contract is code that runs on the blockchain - a decentralized, lightweight database where entries into that database can’t be edited or deleted.</p>
<p>A developer or a no-code program can be used to create a smart contract.</p>
<p><strong>So how would this work?
</strong></p>
<ol>
<li>Imagine there is a no-code website that creates smart contracts designed to look up your kid’s grades at school</li>
<li>You would go onto this smart contract website</li>
<li>Create a smart contract with the following details<ol>
<li>Checks to see if your kid got straight A’s from the school’s report card website<ol>
<li>The school report card website can provide an API that you can use in the smart contract</li>
<li>Or, if there is no API, you can enter the username/password for the report card website, and the smart contract will scrape the webpage for your kid’s grades</li>
</ol>
</li>
<li>If the kid did get straight A’s, then trigger a purchase of the e-bike using funds from the parent’s bank account or credit card<ol>
<li>The bank account or credit card number will be encrypted in the smart contract so no other party can steal it<ol>
<li>Cryptocurrencies can be used too<ol>
<li>The smart contract will have the address and amount of the cryptocurrencies needed to purchase the e-bike.</li>
</ol>
</li>
</ol>
</li>
</ol>
</li>
<li>The smart contract would run the day after the school’s report card is published.</li>
</ol>
</li>
</ol>
<p><strong>Running the smart contract:
</strong></p>
<ol>
<li>The day after the school’s report card is published, the smart contract will run</li>
<li>It will use the API or username/password to login into the school’s report card website</li>
<li>Check your kid’s grades</li>
<li>If your kid got straight A’s, it would use the credit card number to purchase the e-bike from the e-bike’s website.</li>
<li>The e-bike gets delivered to your door for your kid to use</li>
</ol>
<p>I see smart contracts having a lot of value for little things like motivating your kids to get good grades.</p>
]]></content:encoded></item><item><title><![CDATA[Web3 Use Cases - Farm to Table]]></title><description><![CDATA[Web3 Use Cases - Farm to Table
The Problem
How do you know the food you eat is from a local organic farm? Sure, the label on the bag of organic spinach says it is organic and came from a farm in the same state you live in. But is that label correct? ...]]></description><link>https://blog.codingraj.dev/web3-use-cases-farm-to-table</link><guid isPermaLink="true">https://blog.codingraj.dev/web3-use-cases-farm-to-table</guid><category><![CDATA[Web3]]></category><category><![CDATA[Blockchain]]></category><dc:creator><![CDATA[codingraj]]></dc:creator><pubDate>Tue, 26 Jul 2022 17:25:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1658856219238/T6WbfPwbH.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-web3-use-cases-farm-to-table">Web3 Use Cases - Farm to Table</h2>
<h3 id="heading-the-problem">The Problem</h3>
<p>How do you know the food you eat is from a local organic farm? Sure, the label on the bag of organic spinach says it is organic and came from a farm in the same state you live in. But is that label correct? Could the company that put that spinach in that bag be lying? The spinach could have come from an out-of-state farm, and the spinach is not organic. It was grown conventionally like most spinach, but someone along the way decided to just slap an organic label on it and charge the customer twice as much.</p>
<p>Ouch! The same goes with maybe the Alaskan salmon that you bought. Did it come from Alaska? Is it wild? Or is it farmed off the coast of the Atlantic?</p>
<p>Can you trust the labels on the food packaging? If the label says, it must be true. Or is it? Could there be a way to verify that your food is organic? Or, at the very least, you could see where the spinach originated from and what stops it made along the way before it got to your table? Similar to how you can see where a UPS package originated from and the multiple stops it took before it got to your door.</p>
<p>That is where Web3 and the blockchain can come in.</p>
<h3 id="heading-the-solution">The Solution</h3>
<p>First, we need a farm-to-table blockchain that farmers, distribution companies, and grocery stores would use to record the time and place where the food was picked, processed, packaged, transported, stored, and bought.</p>
<p>Imagine the customer buying organic spinach at the grocery store could scan a QR code or barcode using their phone and see where the spinach originated from, how it was grown, when it was picked and bagged, and when it arrived at the grocery store.</p>
<p>Sure the input data on the blockchain could be incorrect, but at least you are getting a level of transparency that you didn’t get before.</p>
<p>So how would this work?</p>
<ol>
<li>Assuming a farm-to-table blockchain has been built, all the players - farmers, food processing and packaging companies, food distributors, and grocery stores- have agreed to use this blockchain.</li>
<li>The farmer picks the organic spinach that is ready to be sent for processing and packaging. The farmer uses an app on their phone to log how much spinach was harvested. The app will record the amount, time, and date, along with the farmers’ information - the farm’s name, organic certification, if it had one, and possibly the name of the farmer that picked the spinach.</li>
<li>The food processing and packaging company goes to the farm to pick up the organic spinach. The person from the processing/packaging company uses their phone to log the receiving of the spinach. The app on the phone will log this onto the blockchain.</li>
<li>Each time the spinach gets transferred to a location, the person receiving the spinach would log the transaction on their phone, then record that transaction on the blockchain.</li>
<li>The packaging company would bag the spinach and put a QR code on the bag of spinach. The QR code will refer to an ID already created on the blockchain.</li>
<li>The food distributor will pick up the bags of spinach and scan the QR code as they load them into their truck. This will record the date/time and distributor onto the blockchain.</li>
<li>When it arrives at the grocery store, the grocers will scan the bags of spinach to record the date and time of receiving the spinach.</li>
<li>The customer can scan the QR code on the bag of spinach using their phone. The customer can see which farm the spinach came from, the date and time, and which farmer picked the spinach. The customer can see if the farm itself is certified organic. The customer can also see all the stops the spinach took up when it got to the grocery store.</li>
</ol>
<p>Now the customer knows that this spinach came from an organic farm in the same state they live in.</p>
<p>Having the blockchain can also help when food poisoning outbreaks occur from a specific batch of spinach. When an outbreak occurs to a particular bunch, that can be recorded on the blockchain. A customer can get notified on the phone that the bag of spinach they bought has been contaminated.</p>
<p>There are some potential issues with data input, the person logging the information into the blockchain could be incorrect, but at least it leaves a trail. And that trail is on the blockchain, where the data can’t be edited or deleted. If someone finds out later that there is misinformation, we can find the source of the error and prevent that from happening again.</p>
]]></content:encoded></item><item><title><![CDATA[Web 3 use cases in Plain English- Healthcare Research]]></title><description><![CDATA[The problem
The problem with Healthcare Research is that most research involves white people. And more specifically, white males. And non-white races, mainly black and brown races, are nonexistent. Women are more “complicated.”
Now Web 3 and the bloc...]]></description><link>https://blog.codingraj.dev/web-3-use-cases-in-plain-english-healthcare-research</link><guid isPermaLink="true">https://blog.codingraj.dev/web-3-use-cases-in-plain-english-healthcare-research</guid><category><![CDATA[Web3]]></category><category><![CDATA[healthcare]]></category><category><![CDATA[Blockchain]]></category><dc:creator><![CDATA[codingraj]]></dc:creator><pubDate>Tue, 19 Jul 2022 16:30:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1658248175687/e8TKv4bwy.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-the-problem">The problem</h2>
<p>The problem with Healthcare Research is that most research involves white people. And more specifically, white males. And non-white races, mainly black and brown races, are nonexistent. Women are more “complicated.”</p>
<p>Now Web 3 and the blockchain won’t solve having other races be in RCT, random controlled trials - the gold standard in scientific research. Researchers need to recruit other non-white races for their studies to solve that. Also, RCTs are expensive, and many countries with money tend to be the US and Western Europe.</p>
<p>Not every recommendation or advice that comes out of the healthcare research would apply to women or non-white races. Most health recommendations don’t apply to women and non-whites.</p>
<p>But there could be a solution that uses the blockchain and AI to analyze health data, find correlations, and develop better recommendations for specific races, gender, or even patient.</p>
<h2 id="heading-the-solution">The solution</h2>
<p>If we can get a patient’s health data onto the blockchain that involves all genders and races, then we can have data scientists and AI analyze that data and find the correlation. The more patients and their data we can get on their blockchain, along with a greater diversity of genders, races, and ages - we can get recommendations on better health specific to gender and ethnicities.</p>
<p>The advantage of the blockchain is that it is public, and we can’t edit the data - once it’s on the blockchain.</p>
<p>Any researcher or AI can look at the data and analyze it. Researchers have biases that do affect their analysis. The researcher may not think they have any bias, but they are human, and humans have biases even if we don’t think we do. The data could be the same, but two researchers could come up with two different conclusions.</p>
<p>Having the data on a blockchain allows anybody, academic researchers or just someone interested in data science, to look and analyze the data. </p>
<p>We can see competing companies or individuals that would create their own AI to research the data. Some AIs could be better than others.</p>
<p>This could create a marketplace of AIs so patients can submit their data and get a health risk assessment along with any specific treatment recommendations or lifestyle changes.</p>
<h2 id="heading-potential-problems">Potential Problems</h2>
<p>Since the blockchain is public, no one wants their health data for all to see - mainly if it is used to discriminate against you. It could be a job that may discriminate against you based on your health because they may not want to pay for your health insurance, or it may affect your career. Terrible, but that could happen.</p>
<p>One way would be to make the data anonymous, so there is no identifying information that can be tied to you - no name, driver’s license, or social security number.</p>
<p>The patient must also consent to submit their health data to the blockchain. And the patient could also choose which data they wish to withhold - like age, race, height, or weight - even though that data would help researchers and the AI find any specific health recommendation by race, gender, or age. </p>
<p>But the patient should have to consent and be able to decide which data gets onto the blockchain.</p>
<h2 id="heading-how-will-it-work">How will it work</h2>
<ol>
<li>Assumption - The patient uses the blockchain and off-chain to store their medical records.</li>
<li>A health research company wants to research cardiovascular disease and wants access to many patients across many genders, ages, and biomarkers.</li>
<li>The patient hears about this and decides they want to participate in this research.</li>
<li>The patient goes on a website and selects the cardiovascular research they want to submit their health data.</li>
<li>The patient then enters their patient ID.</li>
<li>The patient then selects which data they would like to submit.<ol>
<li>The patient selects all their data or some of their data.<ol>
<li>This includes:<ol>
<li>Gender</li>
<li>Age</li>
<li>Height</li>
<li>Weight</li>
<li>Medical History<ol>
<li>Surgeries</li>
<li>Current and Past medications</li>
<li>Allergies</li>
<li>Family Medical History</li>
<li>Past doctor visits</li>
<li>Supplements</li>
</ol>
</li>
</ol>
</li>
</ol>
</li>
</ol>
</li>
<li>The patient then consents and submits the data but not their patient ID.<ol>
<li>That way, the research company will not be able to tie the patient’s health data to a specific person.</li>
</ol>
</li>
<li>The research company will take that data and store if off-chain</li>
<li>Data scientists and AI programs can then analyze that data.</li>
<li>With more patient data, the better for the data scientists/AI to find correlations on what causes cardiovascular disease.<ol>
<li>They may find that a specific race and gender are more susceptible to cardiovascular disease, that they should see a cardiologist, and may need treatment earlier than other races and genders.</li>
</ol>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Web 3 and blockchain allow the patient to own the medical records that they can access anytime. And it will enable them to select and submit which health data they would like researchers to use.</p>
<p>Web 3 allows health researchers to get more patient data and more variety of patients. The more data a data scientist can get their hands on, the better the recommendations will be.</p>
<p>People tend to lie or not tell the whole truth when being asked about their health. Web 3 makes it easier for patients to submit their health records to researchers. And Web 3 allows researchers to quickly get more patient data and accurate health data instead of relying on patient surveys that may not reflect reality.</p>
]]></content:encoded></item><item><title><![CDATA[Web 3 use cases in Plain English- Electronic Medical Records]]></title><description><![CDATA[Web 3 use cases in Plain English- Electronic Medical Records
The problem
When a patient visits the doctor, the doctor asks you questions about any health issues, then does an examination, and at the end gives you recommendations that could involve me...]]></description><link>https://blog.codingraj.dev/web-3-use-cases-in-plain-english-electronic-medical-records</link><guid isPermaLink="true">https://blog.codingraj.dev/web-3-use-cases-in-plain-english-electronic-medical-records</guid><category><![CDATA[Web3]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[healthcare]]></category><dc:creator><![CDATA[codingraj]]></dc:creator><pubDate>Tue, 12 Jul 2022 18:02:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1657648855554/FKXSzzA-h.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-web-3-use-cases-in-plain-english-electronic-medical-records">Web 3 use cases in Plain English- Electronic Medical Records</h1>
<h2 id="heading-the-problem">The problem</h2>
<p>When a patient visits the doctor, the doctor asks you questions about any health issues, then does an examination, and at the end gives you recommendations that could involve medications, treatments, and lifestyle changes.</p>
<p>At the same time, the doctor is making notes on a paper chart, which a nurse or the front desk will later enter into the computer. Sometimes the doctor will enter their notes and assessment directly into the computer.</p>
<p>Some doctors don’t even have electronic medical records. They have a paper chart. In those cases, Web3 and the blockchain won’t solve that issue. Yikes, but they would need to upgrade to go electronic. But that will improve in the future when dictation and AI get to the point where the doctor can speak into a microphone with their patient’s notes. The AI will record and correctly categorize those notes into an electronic medical record.</p>
<p>Okay, back to the problem. If the doctor’s office or hospital has a computer to store the patient’s health records, the patient will usually have access to those records online.</p>
<p>But what if the patient switches health providers because of a new job that uses different insurance. Or you may have moved out of state. Or you don’t like your doctor and wish to go somewhere else.</p>
<p>When that happens, the new doctor will ask for your health records from your previous doctors. And usually, the records are transferred by fax. Why? Because most doctor practices are old school. They may not have the same healthcare system as the other doctor. They may not even have email, strange but true. Doctor offices tend to be very low-tech outside of medical equipment. </p>
<p>Faxing has a lot of issues. Sometimes the fax fails to send, and the sender has to send it multiple times. Sometimes the receiver says they never received it, putting the burden on the patient to ensure the data gets over to the new doctor.</p>
<p>Sometimes the fax runs out of paper, so the new doctor only gets a partial set of the patient’s records.</p>
<p>Yikes, I won’t go through all the problems with faxing, but we can see the issues that arise with faxing medical records.</p>
<p>Not to mention the person receiving the fax could be the front desk. Should the folks at the front desk be able to view the patient’s medical records?</p>
<p>The other problem is that the patient doesn’t own their medical records. They can’t just switch doctors without telling their previous doctors that they must send their medical records to their new doctor.</p>
<p>Why can’t patients go to any doctor they choose and bring their medical records to the office?</p>
<h2 id="heading-the-solution">The solution</h2>
<p>This is where a Web3 and the blockchain could be a solution. The patient and the doctor can agree to enter the patient’s medical records. </p>
<h3 id="heading-how-will-it-work">How will it work</h3>
<ol>
<li><p>A Healthcare Web3 Patient medical record storage system would need to exist</p>
<p> a. And there could be competing storage systems</p>
</li>
<li><p>The patient would sign up for this Web 3 storage system.</p>
<p> a. A recurring payment would need to be involved. If the major health insurers agree to support the Healthcare Web3 Patient medical record storage system, the insurers can cover the expense.</p>
</li>
<li><p>The doctor would then enter the patient’s health medical records into the website.</p>
</li>
<li><p>The website backend would record the data into the blockchain</p>
</li>
<li><p>The patient’s identifying information would be stored in the blockchain</p>
<p> a. The patient’s medical records would be encrypted and stored off-chain.</p>
<p> b. Why off-chain? Storing on the blockchain can be expensive because of the gas fees, and the blockchain is not designed to store large amounts of data. That is where off-chain storage comes in.</p>
</li>
<li><p>If the doctor needs to review the patient’s medical health records, they will go onto the website and request access.</p>
</li>
<li><p>The patient will get a request that the doctor wants to access their records, and the patient will need to approve the request if the doctor wants to view the medical records.</p>
<p> a. This could be tedious for the patient and the doctor. Especially if the patient is not near their phone and the doctor only has time right now to view the records.</p>
<p> b. A potential solution would be that the patient would designate the doctor to view the records anytime they want for a specific period - a week, month, or forever in the future as long the patient is seeing the doctor.</p>
</li>
<li><p>The patient approves the request. The website then authenticates that request on the blockchain, redirecting the website to retrieve and decrypt the medical records stored off-chain.</p>
</li>
<li><p>The doctor can view and update the medical records, which will then be stored off-chain.</p>
</li>
<li><p>The website will notify patients that their medical records have new and updated information. The patient can view their records anytime.</p>
</li>
<li><p>If a patient changes doctor, they can give their ID to the new doctor.</p>
</li>
<li><p>The new doctor would use the patient’s ID on the website to request access.</p>
</li>
<li><p>The approval process with the patient and doctor would occur.</p>
</li>
</ol>
<h2 id="heading-the-benefits">The Benefits</h2>
<p>The benefit of having the patient’s data on the blockchain is that they can quickly bring their health records when they see a new doctor.</p>
<p>No more faxing. More privacy. The front desk and other personnel that work in the doctor’s office won’t be able to view your records even if it is not intentional.</p>
<p>The best benefit is that patient owns their medical records. Not the doctors. Not the insurance companies. And if the patient wishes to not share their medical records with the doctors or insurance companies, they can revoke access to the website.</p>
<p>I plan to do part 2 on this use case on how having the patient’s medical records stored on the blockchain and off-chain can be used for medical research.</p>
]]></content:encoded></item><item><title><![CDATA[Potential Real-Life Web3 Use Cases in Plain English]]></title><description><![CDATA[My Bias
One of my favorite Twitter accounts I follow is Derek Thompson - Staff writer at The Atlantic and host of the “Plain English” podcast at The Ringer. When Derek writes Twitter threads, he will sometimes write his bias, letting the reader know ...]]></description><link>https://blog.codingraj.dev/potential-real-life-web3-use-cases-in-plain-english</link><guid isPermaLink="true">https://blog.codingraj.dev/potential-real-life-web3-use-cases-in-plain-english</guid><category><![CDATA[Web3]]></category><category><![CDATA[Smart Contracts]]></category><category><![CDATA[Blockchain]]></category><dc:creator><![CDATA[codingraj]]></dc:creator><pubDate>Tue, 05 Jul 2022 15:59:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1657036657259/GvVKe_nxx.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-my-bias">My Bias</h2>
<p>One of my favorite Twitter accounts I follow is <a target="_blank" href="https://twitter.com/dkthomp?lang=en">Derek Thompson</a> - Staff writer at The Atlantic and host of the “Plain English” podcast at The Ringer. When Derek writes Twitter threads, he will sometimes write his bias, letting the reader know where he stands. I love that. I will do the same.</p>
<ul>
<li>I’m a Web3 believer and skeptic.<ul>
<li>I think Web3 will have a future and disrupt many industries.</li>
<li>I don’t believe Web3 will take over the world.</li>
</ul>
</li>
<li>I’m lukewarm on a lot of the mainstream tech journalism.<ul>
<li>I think they are dismissive of the new tech because they don’t like the founders - petty but true. </li>
<li>But I’m willing to change my mind after reading Charlie Warzel’s excellent article - <a target="_blank" href="https://newsletters.theatlantic.com/galaxy-brain/62ba500cbcbd490021aaef70/web3-crypto-movement-uses-marc-andreessen/">The Petty Pleasures of Watching Crypto Profiteers Flounder</a>.<ul>
<li>I know that is a link to an essay. But the writing is straightforward, and Warzel is a professional and gifted writer.</li>
</ul>
</li>
</ul>
</li>
<li>I find tech buzzwords the bane of my existence. They are just an excuse to sound smart to impress others and increase the word count on an article or blog.<ul>
<li>If an ordinary person talked like a Web3 VC in a pitch meeting to other VCs, the VCs would turn off their brain and leave the meeting physically or mentally.</li>
</ul>
</li>
<li>It’s going to take some time on how Web3 will be used. Internet Technologies were invented in the late 1970s and early 1980s, but they didn’t take off until the mid-1990s, when the World Wide Web was invented.</li>
</ul>
<h2 id="heading-charlie-warzels-article-the-petty-pleasures-of-watching-crypto-profiteers-flounder">Charlie Warzel’s article - The Petty Pleasures of Watching Crypto Profiteers Flounder</h2>
<p>This article made me laugh and points out why I can’t read most of the blogs about Web3. I can read a technical blog where a developer writes how they created a Web3 app. But a blog on why Web3 will rule the world written by VCs and investors is not a good reading experience. I think these writers are obsessed with word count. They use a lot of buzzwords that make no sense. They could take a lesson from one of my favorite bloggers - <a target="_blank" href="https://flaviocopes.com/post/">Flavio Copes</a>. He writes short, easy-to-read blogs that give you the information you need and nothing else. And Google rewards him well with his blogs showing up on Page 1 on many different topics.
So I’ve decided to write about a potential real-life Web3 use case. I may expand this to a blog series where I write about one use case weekly.</p>
<h2 id="heading-potential-real-life-web3-use-cases-streaming-music-and-artists-royalties">Potential Real-Life Web3 Use Cases - Streaming Music and Artist’s Royalties</h2>
<p>Many people listen to music using a streaming service - Spotify, YouTube Music, or Apple Music. They are great. They have an extensive music library, and the customer only has to pay for the streaming service, not each song they listen to.</p>
<p>I don’t think that model will go away for music listeners. </p>
<p>So Spotify gets money from customers who listen to music on their platform. Then Spotify pays the money to the music rights holders (ex - record labels). The music rights holders then pay the artists their cash.</p>
<p>Money flow:</p>
<p>Customer → Spotify → Music Rights Holders → Artists</p>
<p>This model works, but Spotify and Music Rights Holders could fudge the numbers on how many people stream an artist’s music. Ultimately, the artist may not get their fair share of the money.</p>
<p>Web3 could solve this. Spotify could work with the Music Rights Holders and artists to create a smart contract, code on the blockchain, that would do the following:</p>
<ol>
<li><p>Customer listens to an artist’s song using Spotify.</p>
</li>
<li><p>As the customer plays the song on their phone, the Spotify app on the phone will communicate with the smart contract on the blockchain.</p>
</li>
<li><p>The smart contract will record the number of times the song is streamed on the blockchain.</p>
</li>
<li><p>Spotify will pay the Music Rights Holders based on the number of times that song has been played, which is publicly available for everyone to look up on the blockchain.</p>
</li>
<li><p>Then the Music Rights Holders will pay the artist.</p>
</li>
</ol>
<p>The smart contract will most likely be written by a developer, but no code is coming where the artist could write the smart contract by themselves. Everyone will review the smart contract to make sure the details are correct. This allows artists to determine how often their songs are streamed and how much they will get paid without relying on Spotify and the Music Rights Holders for that information.</p>
<p>Web3, smart contracts, and the blockchain keeps everybody honest and ensure the artists get paid their fair share.</p>
]]></content:encoded></item><item><title><![CDATA[Connect to the Ron Swanson Quotes API with Netlify Functions (serverless)]]></title><description><![CDATA[My Table of content

Intended Audience
What are we Building?
Prerequisite
Folder Structure
Create Layout with HTML and CSS
Install Netlify CLI
Write Client Side JavaScript
Write Netlify Functions
Test Locally



Intended Audience

Experience using NP...]]></description><link>https://blog.codingraj.dev/connect-to-the-ron-swanson-quotes-api-with-netlify-functions-serverless</link><guid isPermaLink="true">https://blog.codingraj.dev/connect-to-the-ron-swanson-quotes-api-with-netlify-functions-serverless</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Netlify]]></category><category><![CDATA[serverless]]></category><dc:creator><![CDATA[codingraj]]></dc:creator><pubDate>Sun, 27 Feb 2022 21:00:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1635534268324/SQUJBVXXO.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-my-table-of-content">My Table of content</h1>
<ul>
<li><a class="post-section-overview" href="#id-section1">Intended Audience</a></li>
<li><a class="post-section-overview" href="#id-section2">What are we Building?</a></li>
<li><a class="post-section-overview" href="#id-section3">Prerequisite</a></li>
<li><a class="post-section-overview" href="#id-section4">Folder Structure</a></li>
<li><a class="post-section-overview" href="#id-section5">Create Layout with HTML and CSS</a></li>
<li><a class="post-section-overview" href="#id-section6">Install Netlify CLI</a></li>
<li><a class="post-section-overview" href="#id-section7">Write Client Side JavaScript</a></li>
<li><a class="post-section-overview" href="#id-section8">Write Netlify Functions</a></li>
<li><a class="post-section-overview" href="#id-section9">Test Locally</a><div id="id-section1">

</div></li>
</ul>
<h2 id="heading-intended-audience">Intended Audience</h2>
<ul>
<li>Experience using NPM to install packages</li>
<li>Newbies are welcome. Follow along and google (I use DuckDuckGo) anything you need more clarity on. Intermediate/Advanced programmers do this all the time.<div id="id-section2">

</div></li>
</ul>
<h2 id="heading-what-are-we-building">What are we Building?</h2>
<ul>
<li>A website (<a target="_blank" href="https://ronswansonquotesapi.netlify.app/">demo link</a>) that calls the Ron Swanson Quotes API, using Netlify Functions (serverless), and displays the quote. </li>
<li>We will be using HTML, CSS, and Vanilla JavaScript to build the website.</li>
<li>The  <a target="_blank" href="https://github.com/coding-island-js/ron-swanson-api-netlify-functions">code</a> is publicly available at GitHub.<div id="id-section3">

</div></li>
</ul>
<h2 id="heading-prerequisite">Prerequisite</h2>
<ul>
<li>Node.js - here is a link to <a target="_blank" href="https://nodejs.org/">install</a><ul>
<li>this is needed to test Netlify Functions locally<div id="id-section4">

</div></li>
</ul>
</li>
</ul>
<h2 id="heading-folder-structure">Folder Structure</h2>
<pre><code>project folder
│   .env
│   .gitignore
│   index.html
│   netlify.toml
│   script.js
│   style.css  
│
└───functions
│   │   ronSwansonQuotes.js
</code></pre><div id="id-section5">

<h2 id="heading-create-layout-with-html-and-css">Create Layout with HTML and CSS</h2>
<p>Open up your code editor (I use VSCode). Create a folder. I called mine <code>ron-swanson-api-netlify-functions</code>.</p>
<p>Any name will do.</p>
<p>Create an HTML file called <code>index.html</code></p>
<p>VSCode has a shortcut to create an HTML boilerplate. Type:</p>
<pre><code><span class="hljs-addition">!</span>
</code></pre><p>or copy below:</p>
<pre><code><span class="hljs-operator">&lt;</span><span class="hljs-operator">!</span>DOCTYPE html<span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span>html lang<span class="hljs-operator">=</span><span class="hljs-string">"en"</span><span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span>head<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>meta charset<span class="hljs-operator">=</span><span class="hljs-string">"UTF-8"</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>meta http<span class="hljs-operator">-</span>equiv<span class="hljs-operator">=</span><span class="hljs-string">"X-UA-Compatible"</span> content<span class="hljs-operator">=</span><span class="hljs-string">"IE=edge"</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>meta name<span class="hljs-operator">=</span><span class="hljs-string">"viewport"</span> content<span class="hljs-operator">=</span><span class="hljs-string">"width=device-width, initial-scale=1.0"</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>title<span class="hljs-operator">&gt;</span>Document<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>title<span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>head<span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span>body<span class="hljs-operator">&gt;</span>

<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>body<span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>html<span class="hljs-operator">&gt;</span>
</code></pre><p>Give your HTML page a title. Any title will do.</p>
<pre><code><span class="hljs-operator">&lt;</span>title<span class="hljs-operator">&gt;</span>Ron Swanson Quotes<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>title<span class="hljs-operator">&gt;</span>
</code></pre><p>Create a header, main, footer section, and a p tag with an id.</p>
<pre><code><span class="hljs-operator">&lt;</span>body<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>header<span class="hljs-operator">&gt;</span>
        Ron Swanson Quotes
    <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>header<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>main<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>p id<span class="hljs-operator">=</span><span class="hljs-string">"ron-swanson-quote"</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>p<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>main<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>footer<span class="hljs-operator">&gt;</span>
        made with love @codingraj
    <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>footer<span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>body<span class="hljs-operator">&gt;</span>
</code></pre><p>Add some CSS to format the layout with Grid and add some color.</p>
<p>Create a CSS file called: <code>style.css</code></p>
<p>Create a link to the CSS file on <code>index.html</code> in the head section.</p>
<pre><code><span class="hljs-operator">&lt;</span>link rel<span class="hljs-operator">=</span><span class="hljs-string">"stylesheet"</span> href<span class="hljs-operator">=</span><span class="hljs-string">"style.css"</span><span class="hljs-operator">&gt;</span>
</code></pre><p>Open style.css and set the box-sizing to border-box. Use the body tag to create the Grid plus some color and spacing between elements.</p>
<pre><code><span class="hljs-comment">/* Box sizing rules */</span>
* {
  <span class="hljs-attribute">box-sizing</span>: border-box;
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
}

<span class="hljs-comment">/* Set Grid Layout, min-height, some color, and padding on the top and bottom */</span>
<span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">grid-template-rows</span>: auto <span class="hljs-number">1</span>fr auto;
  <span class="hljs-attribute">min-height</span>: <span class="hljs-number">100vh</span>;
  <span class="hljs-attribute">background</span>: <span class="hljs-number">#d1bdf7</span>;
  <span class="hljs-attribute">place-items</span>: center;
  <span class="hljs-attribute">padding-block</span>: <span class="hljs-number">2vw</span>;
}
</code></pre><div id="id-section6">

<h2 id="heading-install-netlify-cli-to-test-netlify-function-serverless-locally">Install Netlify CLI to test Netlify Function (serverless) locally</h2>
<p>Run npm init to create a <code>package.json</code> file.</p>
<p>Type this in the terminal:</p>
<pre><code>npm <span class="hljs-keyword">init</span> -y
</code></pre><p>Create/open a new file called <code>.gitignore</code> and type:</p>
<pre><code><span class="hljs-selector-tag">node_modules</span>
# <span class="hljs-selector-tag">Local</span> <span class="hljs-selector-tag">Netlify</span> <span class="hljs-selector-tag">folder</span>
<span class="hljs-selector-class">.netlify</span>
<span class="hljs-selector-class">.env</span>
</code></pre><p>These folders/files will not be tracked or pushed to GitHub.</p>
<p>Open up the terminal to install Netlify CLI. For this tutorial, I have it installed locally. Type:</p>
<pre><code>npm install netlify<span class="hljs-operator">-</span>cli <span class="hljs-operator">-</span><span class="hljs-operator">-</span>save<span class="hljs-operator">-</span>dev
</code></pre><p>Install node-fetch version 2.6.5 in the terminal.</p>
<p><em>Don't install node-fetch latest version 3.x. This version breaks Netlify Functions. I think it may have to do with serverless functions performed by AWS Lamda, which Netlify uses, are not support ES6 modules yet.</em></p>
<p>Type:</p>
<pre><code><span class="hljs-attribute">npm</span> install node-fetch@<span class="hljs-number">2</span>.<span class="hljs-number">6</span>.<span class="hljs-number">5</span>
</code></pre><p>We will use this library to get a quote from the Ron Swanson quote generator.</p>
<p>Create a <code>netlify.toml</code> file in the root directory - a configuration file that Netlify will use to find the location of the Netlify Function (serverless code).</p>
<pre><code>[<span class="hljs-keyword">functions</span>]
  # Directory <span class="hljs-keyword">with</span> serverless <span class="hljs-keyword">functions</span>, including background <span class="hljs-keyword">functions</span>,
  # <span class="hljs-keyword">to</span> deploy. This <span class="hljs-keyword">is</span> relative <span class="hljs-keyword">to</span> the base directory <span class="hljs-keyword">if</span> one has been <span class="hljs-keyword">set</span>, 
  # <span class="hljs-keyword">or</span> the root directory <span class="hljs-keyword">if</span> a base hasn’t been <span class="hljs-keyword">set</span>.
  directory = "functions/"
</code></pre><div id="id-section7">

<h2 id="heading-write-netlify-functions">Write Netlify Functions</h2>
<p>Create a folder in the root directory called <code>functions</code>. Create a file called <code>ronSwansonQuotes.js</code> in the functions folder. Type the below code:</p>
<pre><code>const fetch <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">"node-fetch"</span>);

const API_ENDPOINT <span class="hljs-operator">=</span> <span class="hljs-string">"https://ron-swanson-quotes.herokuapp.com/v2/quotes"</span>;

exports.handler <span class="hljs-operator">=</span> async (<span class="hljs-function"><span class="hljs-keyword">event</span>, <span class="hljs-title">context</span>, <span class="hljs-title">callback</span>) =&gt; </span>{
  <span class="hljs-keyword">return</span> fetch(API_ENDPOINT)
    .then((response) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> response.json())
    .then((data) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> ({
      statusCode: <span class="hljs-number">200</span>,
      body: JSON.stringify(data),
    }))
    .catch((<span class="hljs-function"><span class="hljs-keyword">error</span>) =&gt; (<span class="hljs-params">{ statusCode: <span class="hljs-number">422</span>, body: String(<span class="hljs-params"><span class="hljs-keyword">error</span></span>) }</span>))</span>;
};
</code></pre><p><code>return fetch(API_ENDPOINT)</code>. This will get the Ron Swanson quote.</p>
<p><code>.then((response) =&gt; response.json())</code>. This will parse the quote as JSON.</p>
<p><code>.then((data) =&gt; ({ statusCode: 200, body: JSON.stringify(data) }))</code>. This sends the quote back as a string to the client.</p>
<p><em>From my testing, it seems that Netlify Functions requires that data getting sent back to the client must be a string and not an object. And it requires a statusCode being sent back.</em></p>
<div id="id-section8">

<h2 id="heading-code-client-side-javascript-to-call-netlify-function">Code Client-side JavaScript to call Netlify Function</h2>
<p>Create a file called <code>script.js</code> in the root folder. Write a function to call the Netlify Function when the page loads.</p>
<pre><code><span class="hljs-comment">// url for Netlify Functions. When Netlify builds the site, it places all functions in the "/.netlify/" folder</span>
const quoteNetlifyFunctions <span class="hljs-operator">=</span> <span class="hljs-string">"/.netlify/functions/ronSwansonQuotes"</span>;

<span class="hljs-comment">//call api when page loads</span>
callQuoteAPI();

<span class="hljs-comment">//call netlify functions for api</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">callQuoteAPI</span>(<span class="hljs-params"></span>) </span>{
  fetch(quoteNetlifyFunctions)
    .then((response) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> response.json())
    .then((data) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
      console.log(data);
      <span class="hljs-comment">//display the quote on the HTML Page</span>
      document.getElementById(<span class="hljs-string">"ron-swanson-quote"</span>).innerText <span class="hljs-operator">=</span> data;
    })
    .catch((<span class="hljs-function"><span class="hljs-keyword">error</span>) =&gt; <span class="hljs-title">console</span>.<span class="hljs-title"><span class="hljs-keyword">error</span></span>(<span class="hljs-params"><span class="hljs-keyword">error</span></span>))</span>;
}
</code></pre><p>Add a script tag to link the script.js to the <code>index.html</code>.</p>
<pre><code><span class="hljs-operator">&lt;</span>script src<span class="hljs-operator">=</span><span class="hljs-string">"/script.js"</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>script<span class="hljs-operator">&gt;</span>
</code></pre><div id="id-section9">

<h3 id="heading-test-netlify-function-locally">Test Netlify Function locally</h3>
<p>Start a local development server with Netlify CLI. </p>
<pre><code><span class="hljs-attribute">npx</span> netlify dev
</code></pre><p>Make sure to type in <code>npx</code> if you installed the Netlify CLI locally. Otherwise, you will get this error <code>zsh: command not found: netlify</code>.</p>
<p>This starts a server on localhost:8888. Open your web browser, if it doesn't open automatically, and type in the browser's address bar <code>http://localhost:8888/index.html</code>.</p>
<p>You will see the Ron Swanson Quote on the HTML page and console log. If you refresh the browser, you will see a different quote again.</p>
</div></div></div></div></div>]]></content:encoded></item><item><title><![CDATA[Build a Website Maker that creates and deploys a decentralized webpage using Web3.storage]]></title><description><![CDATA[We will build a frontend with HTML, CSS, and Vanilla JS where users can upload a picture along with the alt text and write a website title.
We will build a backend with Express.JS that receives the uploaded files and store them in Web3.storage, decen...]]></description><link>https://blog.codingraj.dev/build-a-website-maker-that-creates-and-deploys-a-decentralized-webpage-using-web3storage</link><guid isPermaLink="true">https://blog.codingraj.dev/build-a-website-maker-that-creates-and-deploys-a-decentralized-webpage-using-web3storage</guid><category><![CDATA[Web3]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[Netlify]]></category><dc:creator><![CDATA[codingraj]]></dc:creator><pubDate>Sun, 27 Feb 2022 19:54:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1637783050805/KZvpCTpM4.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>We will build a frontend with HTML, CSS, and Vanilla JS where users can upload a picture along with the alt text and write a website title.</p>
<p>We will build a backend with Express.JS that receives the uploaded files and store them in Web3.storage, decentralized storage backed by Filecoin.</p>
<p>The final result will be a website maker, (<a target="_blank" href="https://web3-website-maker.netlify.app/">demo link</a>), that will create a decentralized website -  <a target="_blank" href="https://bafybeibet3nvwktjavnuk6icxnn7rts6rheyzhpbxh6iynpr66nshvfzvq.ipfs.dweb.link/files/index.html">example</a>. </p>
<h1 id="heading-my-table-of-content">My Table of content</h1>
<ul>
<li><a class="post-section-overview" href="#id-section1">Intended Audience</a></li>
<li><a class="post-section-overview" href="#id-section2">What are we Building?</a></li>
<li><a class="post-section-overview" href="#id-section3">Prerequisite</a></li>
<li><a class="post-section-overview" href="#id-section4">Folder Structure</a></li>
<li><a class="post-section-overview" href="#id-section5">Create Frontend Website</a></li>
<li><a class="post-section-overview" href="#id-section6">Create Express.JS Backend Server</a><div id="id-section1">

</div></li>
</ul>
<h2 id="heading-intended-audience">Intended Audience</h2>
<ul>
<li>Experience or familiarity with creating a full-stack app</li>
<li>Newbies are welcome. Follow along and google (I use DuckDuckGo) anytime you need more clarity. Intermediate/Advanced programmers do this all the time.<div id="id-section2">

</div></li>
</ul>
<h2 id="heading-what-are-we-building">What are we Building?</h2>
<ul>
<li>A website (<a target="_blank" href="https://web3-website-maker.netlify.app/">demo link</a>) can create and deploy a one-page decentralized website      </li>
<li>We will be using HTML, CSS, and Vanilla JavaScript to build the frontend website.</li>
<li>We will be using the expressJS framework to create our backend server.</li>
<li>The  <a target="_blank" href="https://github.com/coding-island-js/web3-static-website-maker-frontend">frontend code</a> and <a target="_blank" href="https://github.com/coding-island-js/web3-static-website-maker-backend">backend code</a> is publicly available at GitHub.<ul>
<li>They are split up into two repos. For some reason, I don't like mono-repos, but I'm willing to change my mind.</li>
</ul>
</li>
<li>We won't be covering the code step by step with an explanation.<ul>
<li>Instead, I will explain what the code is doing at a high to medium level<div id="id-section3">

</div></li>
</ul>
</li>
</ul>
<h2 id="heading-prerequisite">Prerequisite</h2>
<ul>
<li>Any code editor (I use VSCode)</li>
<li>Node.js - here is a link to <a target="_blank" href="https://nodejs.org/en/">install</a> <div id="id-section4">

</div></li>
</ul>
<h2 id="heading-folder-structure">Folder Structure</h2>
<h3 id="heading-frontend">Frontend</h3>
<pre><code>project folder
│   index.html
│   script.js
│   style.css
</code></pre><h3 id="heading-backend">Backend</h3>
<pre><code>project folder
│   .env
│   .gitignore
│   server.js
│
└───controller
│   │   createFolders.js
│   │   createHtmlFile.js
│   │   storeFilesToWeb3Storage.js
│   │   uploadFilesFromClient.js
└───routes
│   │   receiveFilesFromClient.js
</code></pre><div id="id-section5">

<h2 id="heading-create-frontend-website">Create Frontend Website</h2>
<p>Open up your code editor (I use VSCode). Create a folder. I called mine <code>web3-static-website-maker-frontend</code>.</p>
<p>Create an HTML file called <code>index.html</code></p>
<p>Below is the HTML code. I will explain some of the parts that I think are important after the code.</p>
<pre><code><span class="hljs-operator">&lt;</span><span class="hljs-operator">!</span>DOCTYPE html<span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span>html lang<span class="hljs-operator">=</span><span class="hljs-string">"en"</span><span class="hljs-operator">&gt;</span>
  <span class="hljs-operator">&lt;</span>head<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>meta charset<span class="hljs-operator">=</span><span class="hljs-string">"UTF-8"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>meta http<span class="hljs-operator">-</span>equiv<span class="hljs-operator">=</span><span class="hljs-string">"X-UA-Compatible"</span> content<span class="hljs-operator">=</span><span class="hljs-string">"IE=edge"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>meta name<span class="hljs-operator">=</span><span class="hljs-string">"viewport"</span> content<span class="hljs-operator">=</span><span class="hljs-string">"width=device-width, initial-scale=1.0"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>meta
      name<span class="hljs-operator">=</span><span class="hljs-string">"description"</span>
      content<span class="hljs-operator">=</span><span class="hljs-string">"make web3 decentralized websites using Web3.storage"</span>
    <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>meta name<span class="hljs-operator">=</span><span class="hljs-string">"keywords"</span> content<span class="hljs-operator">=</span><span class="hljs-string">"web3 decentralized web3.storage"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>meta name<span class="hljs-operator">=</span><span class="hljs-string">"author"</span> content<span class="hljs-operator">=</span><span class="hljs-string">"codingraj"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>link rel<span class="hljs-operator">=</span><span class="hljs-string">"preconnect"</span> href<span class="hljs-operator">=</span><span class="hljs-string">"https://fonts.googleapis.com"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>link rel<span class="hljs-operator">=</span><span class="hljs-string">"preconnect"</span> href<span class="hljs-operator">=</span><span class="hljs-string">"https://fonts.gstatic.com"</span> crossorigin <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>link
      href<span class="hljs-operator">=</span><span class="hljs-string">"https://fonts.googleapis.com/css2?family=Merriweather+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;1,300;1,400;1,500;1,600;1,700;1,800&amp;display=swap"</span>
      rel<span class="hljs-operator">=</span><span class="hljs-string">"stylesheet"</span>
    <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>link rel<span class="hljs-operator">=</span><span class="hljs-string">"stylesheet"</span> href<span class="hljs-operator">=</span><span class="hljs-string">"/style.css"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>script src<span class="hljs-operator">=</span><span class="hljs-string">"/script.js"</span> defer<span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>script<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>title<span class="hljs-operator">&gt;</span>Web3 Static Website Maker<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>title<span class="hljs-operator">&gt;</span>
  <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>head<span class="hljs-operator">&gt;</span>
  <span class="hljs-operator">&lt;</span>body<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>header<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>div class<span class="hljs-operator">=</span><span class="hljs-string">"logo-title"</span><span class="hljs-operator">&gt;</span>Web3 Decentralized Website Maker<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>div<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>header<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>main<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>h1<span class="hljs-operator">&gt;</span>Create a one page website hosted on Web3.storage&lt;<span class="hljs-operator">/</span>h1<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>br <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span>br <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>p<span class="hljs-operator">&gt;</span>
        Get your
        <span class="hljs-operator">&lt;</span>a href<span class="hljs-operator">=</span><span class="hljs-string">"https://docs.web3.storage/#get-an-api-token"</span> target<span class="hljs-operator">=</span><span class="hljs-string">"_blank"</span><span class="hljs-operator">&gt;</span>
          Free Web3.storage API Token here<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>a
        <span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>p<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>br <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>div class<span class="hljs-operator">=</span><span class="hljs-string">"card"</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>label <span class="hljs-keyword">for</span><span class="hljs-operator">=</span><span class="hljs-string">"website-title"</span><span class="hljs-operator">&gt;</span>Web3.storage API Token<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>label<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>span class<span class="hljs-operator">=</span><span class="hljs-string">"inputRequired"</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>span<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>span class<span class="hljs-operator">=</span><span class="hljs-string">"incorrectAPI"</span> id<span class="hljs-operator">=</span><span class="hljs-string">"incorrectAPI-id"</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>span<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>br <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>input
          <span class="hljs-keyword">type</span><span class="hljs-operator">=</span><span class="hljs-string">"text"</span>
          name<span class="hljs-operator">=</span><span class="hljs-string">"api-token"</span>
          id<span class="hljs-operator">=</span><span class="hljs-string">"api-token-id"</span>
          placeholder<span class="hljs-operator">=</span><span class="hljs-string">"API token not saved on the server"</span>
          required
          autofocus
        <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>br <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>br <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>label <span class="hljs-keyword">for</span><span class="hljs-operator">=</span><span class="hljs-string">"header-title"</span><span class="hljs-operator">&gt;</span>Header Title<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>label<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>span class<span class="hljs-operator">=</span><span class="hljs-string">"inputRequired"</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>span<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>br <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>input
          <span class="hljs-keyword">type</span><span class="hljs-operator">=</span><span class="hljs-string">"text"</span>
          name<span class="hljs-operator">=</span><span class="hljs-string">"header-title"</span>
          id<span class="hljs-operator">=</span><span class="hljs-string">"header-title-id"</span>
          placeholder<span class="hljs-operator">=</span><span class="hljs-string">"ex - I love pineapple on pizza"</span>
          required
        <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>br <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>br <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>label <span class="hljs-keyword">for</span><span class="hljs-operator">=</span><span class="hljs-string">""</span><span class="hljs-operator">&gt;</span>Upload Image<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>label<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>span class<span class="hljs-operator">=</span><span class="hljs-string">"inputRequired"</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>span<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>br <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>input
          <span class="hljs-keyword">type</span><span class="hljs-operator">=</span><span class="hljs-string">"file"</span>
          accept<span class="hljs-operator">=</span><span class="hljs-string">"image/*"</span>
          name<span class="hljs-operator">=</span><span class="hljs-string">"image-file"</span>
          id<span class="hljs-operator">=</span><span class="hljs-string">"image-file-id"</span>
          required
        <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>br <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>br <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>label <span class="hljs-keyword">for</span><span class="hljs-operator">=</span><span class="hljs-string">"image-alt-text"</span><span class="hljs-operator">&gt;</span>Image Alt Text<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>label<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>br <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>textarea
          name<span class="hljs-operator">=</span><span class="hljs-string">"image-alt-text"</span>
          id<span class="hljs-operator">=</span><span class="hljs-string">"image-alt-text-id"</span>
          placeholder<span class="hljs-operator">=</span><span class="hljs-string">"ex - a slice of pizza with pineapple toppings on a paper plate"</span>
        <span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>textarea<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>br <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>div class<span class="hljs-operator">=</span><span class="hljs-string">"buttonRequired"</span> id<span class="hljs-operator">=</span><span class="hljs-string">"buttonRequired-id"</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>div<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>br <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>button id<span class="hljs-operator">=</span><span class="hljs-string">"generate-button-id"</span> data<span class="hljs-operator">-</span>cy<span class="hljs-operator">=</span><span class="hljs-string">"generate-button"</span><span class="hljs-operator">&gt;</span>
          Create Website on Web3.storage
        <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>button<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>br <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span>br <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span>br <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>a class<span class="hljs-operator">=</span><span class="hljs-string">"web3-website-link"</span> id<span class="hljs-operator">=</span><span class="hljs-string">"web3-website-link-id"</span> target<span class="hljs-operator">=</span><span class="hljs-string">"_blank”"</span><span class="hljs-operator">&gt;</span>
          your <span class="hljs-keyword">new</span> website
        <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>a<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>div<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>main<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>footer<span class="hljs-operator">&gt;</span>made with <span class="hljs-operator">&lt;</span>span class<span class="hljs-operator">=</span><span class="hljs-string">"heart"</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">&amp;</span>hearts;<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>span<span class="hljs-operator">&gt;</span> @codingraj<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>footer<span class="hljs-operator">&gt;</span>
  <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>body<span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>html<span class="hljs-operator">&gt;</span>
</code></pre><p>Important Parts:</p>
<ul>
<li>3 sections<ul>
<li>Header</li>
<li>Main<ul>
<li>Card div for the input fields and button<ul>
<li>I like the card layout</li>
</ul>
</li>
</ul>
</li>
<li>Footer</li>
</ul>
</li>
<li>Input fields<ul>
<li>Web3.Storage API Token<ul>
<li>This is needed to use their API to store files</li>
<li>Required field</li>
</ul>
</li>
<li>Header Title<ul>
<li>Displayed above the image</li>
<li>Required field</li>
</ul>
</li>
<li>Upload Image<ul>
<li>Restricted to selecting only image files</li>
<li>Required field</li>
</ul>
</li>
<li>Image Alt Text<ul>
<li>Ability to add alt text for the image file</li>
<li>Optional field</li>
</ul>
</li>
<li>Upload Image<ul>
<li>Restricted to selecting only image files</li>
<li>Required field</li>
</ul>
</li>
<li>Span tags<ul>
<li>To display error messages for<ul>
<li>Incorrect API Token</li>
<li>Incomplete Fields</li>
<li>Button</li>
</ul>
</li>
<li>Submit user input<ul>
<li>New Website Link</li>
</ul>
</li>
<li>After clicking the button, the server will send a URL for the new decentralized website</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>Add some CSS to format the layout with Grid and add some color.</p>
<p>Create a CSS file called: <code>style.css</code></p>
<pre><code><span class="hljs-comment">/* Box sizing rules */</span>
*,
*<span class="hljs-selector-pseudo">::before</span>,
*<span class="hljs-selector-pseudo">::after</span> {
  <span class="hljs-attribute">box-sizing</span>: border-box;
}

<span class="hljs-comment">/* Remove default margin */</span>
<span class="hljs-selector-tag">body</span>,
<span class="hljs-selector-tag">h1</span>,
<span class="hljs-selector-tag">h2</span>,
<span class="hljs-selector-tag">h3</span>,
<span class="hljs-selector-tag">h4</span>,
<span class="hljs-selector-tag">p</span>,
<span class="hljs-selector-class">.logo-title</span> {
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
}

<span class="hljs-comment">/* Set core root defaults */</span>
<span class="hljs-selector-tag">html</span> {
  <span class="hljs-attribute">scroll-behavior</span>: smooth;
}

<span class="hljs-comment">/* Set core body defaults */</span>
<span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">text-rendering</span>: optimizeSpeed;
  <span class="hljs-attribute">line-height</span>: <span class="hljs-number">1.5</span>;
}

<span class="hljs-selector-pseudo">:root</span> {
  <span class="hljs-attribute">--font-family</span>: <span class="hljs-string">"Merriweather Sans"</span>, sans-serif;

  <span class="hljs-attribute">--color-background-header-footer</span>: <span class="hljs-number">#d1bdf7</span>;
  <span class="hljs-attribute">--color-button-background</span>: <span class="hljs-number">#1a45df</span>;

  <span class="hljs-attribute">--color-primary-font</span>: <span class="hljs-number">#000036</span>;
  <span class="hljs-attribute">--color-secondary-font</span>: <span class="hljs-number">#ffffff</span>;
  <span class="hljs-attribute">--color-complimentary-font</span>: <span class="hljs-number">#1a45df</span>;
  <span class="hljs-attribute">--color-placeholder-font</span>: <span class="hljs-number">#4e5b62</span>;

  <span class="hljs-attribute">--font-size-sm</span>: <span class="hljs-built_in">clamp</span>(<span class="hljs-number">0.5rem</span>, <span class="hljs-number">0.5rem</span> + <span class="hljs-number">1.5vw</span>, <span class="hljs-number">2rem</span>);
  <span class="hljs-attribute">--font-size-100</span>: <span class="hljs-number">0.775rem</span>;
  <span class="hljs-attribute">--font-size-200</span>: <span class="hljs-number">0.875rem</span>;
  <span class="hljs-attribute">--font-size-300</span>: <span class="hljs-number">1rem</span>;
  <span class="hljs-attribute">--font-size-400</span>: <span class="hljs-number">1.125rem</span>;
  <span class="hljs-attribute">--font-size-500</span>: <span class="hljs-number">1.25rem</span>;
  <span class="hljs-attribute">--font-size-600</span>: <span class="hljs-number">1.5rem</span>;
  <span class="hljs-attribute">--font-size-700</span>: <span class="hljs-number">1.875rem</span>;
  <span class="hljs-attribute">--font-size-xl</span>: <span class="hljs-built_in">clamp</span>(<span class="hljs-number">2rem</span>, <span class="hljs-number">1rem</span> + <span class="hljs-number">3vw</span>, <span class="hljs-number">5.75rem</span>);
}

<span class="hljs-selector-tag">h1</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-built_in">var</span>(--font-size-<span class="hljs-number">700</span>);
  <span class="hljs-attribute">line-height</span>: <span class="hljs-number">1.1</span>;
}

<span class="hljs-selector-class">.logo-title</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-built_in">var</span>(--font-size-<span class="hljs-number">700</span>);
}

<span class="hljs-comment">/* Set Grid Layout, min-height, some color, and padding on the top and bottom */</span>

<span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">1</span>fr;
  <span class="hljs-attribute">grid-template-rows</span>: auto <span class="hljs-number">5</span>fr auto;
  <span class="hljs-attribute">min-height</span>: <span class="hljs-number">100vh</span>;
  <span class="hljs-attribute">gap</span>: <span class="hljs-number">2vw</span>;
  <span class="hljs-attribute">font-family</span>: <span class="hljs-built_in">var</span>(--font-family);
  <span class="hljs-attribute">text-align</span>: center;
}

<span class="hljs-selector-tag">header</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-built_in">var</span>(--font-size-<span class="hljs-number">700</span>);
  <span class="hljs-attribute">grid-row</span>: <span class="hljs-number">1</span> / <span class="hljs-number">2</span>;
  <span class="hljs-attribute">padding-block</span>: <span class="hljs-number">1vw</span>;
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">var</span>(--color-background-header-footer);
}

<span class="hljs-selector-tag">main</span> {
  <span class="hljs-attribute">grid-row</span>: <span class="hljs-number">2</span> / <span class="hljs-number">3</span>;
}

<span class="hljs-selector-tag">footer</span> {
  <span class="hljs-attribute">padding-block</span>: <span class="hljs-number">1vw</span>;
  <span class="hljs-attribute">grid-row</span>: <span class="hljs-number">3</span> / <span class="hljs-number">4</span>;
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">var</span>(--color-background-header-footer);
}

<span class="hljs-comment">/* # card   */</span>

<span class="hljs-selector-class">.card</span> {
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">var</span>(--color-background-header-footer);
  <span class="hljs-attribute">outline</span>: none;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">1.5rem</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">8px</span>;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">90vw</span>;
  <span class="hljs-attribute">margin</span>: auto;
}

<span class="hljs-keyword">@media</span> <span class="hljs-keyword">only</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">min-width:</span> <span class="hljs-number">50em</span>) {
  <span class="hljs-selector-class">.card</span> {
    <span class="hljs-attribute">width</span>: <span class="hljs-number">60vw</span>;
  }
}

<span class="hljs-selector-tag">input</span> {
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.75em</span> <span class="hljs-number">0.5em</span>;
  <span class="hljs-attribute">border</span>: <span class="hljs-number">2px</span> solid;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">4px</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-built_in">var</span>(--font-size-<span class="hljs-number">300</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">90%</span>;
}

<span class="hljs-selector-tag">label</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.125rem</span>;
  <span class="hljs-attribute">font-weight</span>: <span class="hljs-number">500</span>;
  <span class="hljs-attribute">line-height</span>: <span class="hljs-number">2</span>;
}

<span class="hljs-comment">/* # input and textarea fields   */</span>

<span class="hljs-selector-tag">input</span><span class="hljs-selector-pseudo">:required</span> {
  <span class="hljs-attribute">border-color</span>: <span class="hljs-number">#1a45df</span>;
  <span class="hljs-attribute">border-width</span>: <span class="hljs-number">2px</span>;
}
<span class="hljs-selector-tag">textarea</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">90%</span>;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">15%</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.75em</span> <span class="hljs-number">0.5em</span>;
  <span class="hljs-attribute">border</span>: <span class="hljs-number">2px</span> solid;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">4px</span>;
}

<span class="hljs-keyword">@media</span> <span class="hljs-keyword">only</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">min-width:</span> <span class="hljs-number">50em</span>) {
  <span class="hljs-selector-tag">input</span>,
  <span class="hljs-selector-tag">textarea</span> {
    <span class="hljs-attribute">width</span>: <span class="hljs-number">70%</span>;
  }
}

<span class="hljs-selector-pseudo">::placeholder</span> {
  <span class="hljs-attribute">color</span>: <span class="hljs-built_in">var</span>(--color-placeholder-font);
  <span class="hljs-attribute">font-size</span>: <span class="hljs-built_in">var</span>(--font-size-<span class="hljs-number">100</span>);
}

<span class="hljs-comment">/* # buttons  */</span>

<span class="hljs-selector-tag">button</span> {
  <span class="hljs-attribute">border</span>: none;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-built_in">var</span>(--color-button-background);
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.4rem</span> <span class="hljs-number">0.6rem</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-built_in">var</span>(--font-size-sm);
  <span class="hljs-attribute">color</span>: <span class="hljs-built_in">var</span>(--color-secondary-font);
  <span class="hljs-attribute">cursor</span>: pointer;
  <span class="hljs-attribute">text-align</span>: center;
}

<span class="hljs-selector-class">.inputRequired</span><span class="hljs-selector-pseudo">:after</span> {
  <span class="hljs-attribute">content</span>: <span class="hljs-string">"required"</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-built_in">var</span>(--font-size-<span class="hljs-number">100</span>);
  <span class="hljs-attribute">color</span>: <span class="hljs-built_in">var</span>(--color-complimentary-font);
  <span class="hljs-attribute">margin-left</span>: <span class="hljs-number">0.5vw</span>;
}

<span class="hljs-comment">/* # error message display and style   */</span>

<span class="hljs-selector-class">.buttonRequired</span> {
  <span class="hljs-attribute">display</span>: none;
}

<span class="hljs-selector-class">.buttonRequired</span><span class="hljs-selector-pseudo">:after</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-built_in">var</span>(--font-size-<span class="hljs-number">100</span>);
  <span class="hljs-attribute">color</span>: <span class="hljs-built_in">var</span>(--color-complimentary-font);
  <span class="hljs-attribute">margin-left</span>: <span class="hljs-number">0.5vw</span>;
}

<span class="hljs-selector-class">.incorrectAPI</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-built_in">var</span>(--font-size-<span class="hljs-number">100</span>);
  <span class="hljs-attribute">color</span>: red;
  <span class="hljs-attribute">margin-left</span>: <span class="hljs-number">0.5vw</span>;
}

<span class="hljs-comment">/* # decentralized website link returned from server   */</span>

<span class="hljs-selector-class">.web3-website-link</span> {
  <span class="hljs-attribute">border</span>: <span class="hljs-number">5px</span> solid orange;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">1vw</span>;
  <span class="hljs-attribute">width</span>: fit-content;
  <span class="hljs-attribute">margin</span>: auto;
  <span class="hljs-attribute">animation</span>: blink <span class="hljs-number">1.5s</span> infinite;
  <span class="hljs-attribute">display</span>: none;
}

<span class="hljs-comment">/* # loading animation after user clicks button   */</span>

<span class="hljs-selector-class">.loading</span> {
  <span class="hljs-attribute">position</span>: relative;
  <span class="hljs-attribute">overflow</span>: hidden;
}

<span class="hljs-selector-class">.loading</span><span class="hljs-selector-pseudo">:before</span> {
  <span class="hljs-attribute">position</span>: absolute;
  <span class="hljs-attribute">left</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">top</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">bottom</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">right</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">content</span>: <span class="hljs-string">""</span>;
  <span class="hljs-attribute">z-index</span>: <span class="hljs-number">1</span>;
  <span class="hljs-attribute">background</span>: pink;
  <span class="hljs-attribute">animation</span>: slide <span class="hljs-number">1.5s</span> ease infinite;
}

<span class="hljs-keyword">@keyframes</span> slide {
  0% {
    <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translateX</span>(-<span class="hljs-number">100%</span>);
  }
  100% {
    <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translateX</span>(<span class="hljs-number">340%</span>);
  }
}

<span class="hljs-keyword">@keyframes</span> blink {
  0% {
    <span class="hljs-attribute">border-color</span>: lightgreen;
  }
  50% {
    <span class="hljs-attribute">border-color</span>: darkgreen;
  }
  100% {
    <span class="hljs-attribute">border-color</span>: lightgreen;
  }
}

<span class="hljs-comment">/* # heart color for footer   */</span>

<span class="hljs-selector-class">.heart</span> {
  <span class="hljs-attribute">color</span>: red;
}
</code></pre><p>Important Parts:</p>
<ul>
<li>CSS Grid for layout<ul>
<li>3-row layout</li>
<li>Used semantic tags instead of div tags for layout</li>
</ul>
</li>
<li>Card div to group input fields<ul>
<li>Media Query to make the Card width smaller for larger screens</li>
</ul>
</li>
<li>Input + Label styling<ul>
<li>Placeholder text styling</li>
<li>Required text label styling</li>
<li>Media Query to make the input width smaller for larger screens</li>
</ul>
</li>
<li>Button styling<ul>
<li>Loading animation to display after clicking the button</li>
</ul>
</li>
<li>Span tag styling<ul>
<li>The span tags is where the error message will be displayed</li>
</ul>
</li>
<li>New Website Link styling</li>
</ul>
<p>Create a file called <code>script.js</code> in the root folder.</p>
<pre><code><span class="hljs-comment">// declare environment</span>
<span class="hljs-comment">// to determine API url</span>
let env <span class="hljs-operator">=</span> <span class="hljs-string">"dev"</span>;
let url;

<span class="hljs-keyword">if</span> (env <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-string">"dev"</span>) {
  url <span class="hljs-operator">=</span> <span class="hljs-string">"http://localhost:8080/upload-files"</span>;
}

<span class="hljs-keyword">if</span> (env <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-string">"prod"</span>) {
  url <span class="hljs-operator">=</span> <span class="hljs-string">"https://web3-website-maker.herokuapp.com/upload-files"</span>;
}

<span class="hljs-comment">// select button Id</span>
const createWebsiteButton <span class="hljs-operator">=</span> document.getElementById(<span class="hljs-string">"generate-button-id"</span>);

<span class="hljs-comment">// add click event listener that</span>
<span class="hljs-comment">// will get Input Ids, Input Values</span>
createWebsiteButton.addEventListener(<span class="hljs-string">"click"</span>, async () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
  const apiTokenInput <span class="hljs-operator">=</span> document.getElementById(<span class="hljs-string">"api-token-id"</span>);
  const fileInput <span class="hljs-operator">=</span> document.getElementById(<span class="hljs-string">"image-file-id"</span>);
  const headerTitleInput <span class="hljs-operator">=</span> document.getElementById(<span class="hljs-string">"header-title-id"</span>);
  const altImageInput <span class="hljs-operator">=</span> document.getElementById(<span class="hljs-string">"image-alt-text-id"</span>);

  <span class="hljs-comment">// check if Input fields is complete</span>
  <span class="hljs-comment">// if complete then call Function uploadFile</span>
  <span class="hljs-comment">// pass file selected, api token value, alt image value, and header title value</span>
  <span class="hljs-keyword">if</span> (
    apiTokenInput.<span class="hljs-built_in">value</span> <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-string">""</span> <span class="hljs-operator">&amp;</span><span class="hljs-operator">&amp;</span>
    headerTitleInput.<span class="hljs-built_in">value</span> <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-string">""</span> <span class="hljs-operator">&amp;</span><span class="hljs-operator">&amp;</span>
    fileInput.<span class="hljs-built_in">value</span> <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-string">""</span>
  ) {
    uploadFile(fileInput, apiTokenInput, altImageInput, headerTitleInput);
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-comment">// if the fields are incomplete</span>
    <span class="hljs-comment">// display error message</span>
    document.getElementById(<span class="hljs-string">"buttonRequired-id"</span>).style.display <span class="hljs-operator">=</span> <span class="hljs-string">"block"</span>;
    document.getElementById(<span class="hljs-string">"buttonRequired-id"</span>).style.color <span class="hljs-operator">=</span> <span class="hljs-string">"orange"</span>;
    document.getElementById(<span class="hljs-string">"buttonRequired-id"</span>).innerText <span class="hljs-operator">=</span>
      <span class="hljs-string">"fill in required fields"</span>;
  }
});

async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">uploadFile</span>(<span class="hljs-params">
  fileInput,
  apiTokenInput,
  altImageInput,
  headerTitleInput
</span>) </span>{
  <span class="hljs-comment">// create random 4 digit number to create folder on server with a unique name</span>
  <span class="hljs-keyword">var</span> folderName <span class="hljs-operator">=</span> String(Math.floor(<span class="hljs-number">1000</span> <span class="hljs-operator">+</span> Math.random() <span class="hljs-operator">*</span> <span class="hljs-number">9000</span>));

  <span class="hljs-comment">// grab website link element ID</span>
  <span class="hljs-comment">// we will use this to display the link after a successful response from the server</span>
  const websiteLink <span class="hljs-operator">=</span> document.getElementById(<span class="hljs-string">"web3-website-link-id"</span>);

  <span class="hljs-comment">// add file and user input to FormData object</span>
  const userFormData <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> FormData();
  userFormData.append(<span class="hljs-string">"folderName"</span>, folderName);
  userFormData.append(<span class="hljs-string">"image"</span>, fileInput.files[<span class="hljs-number">0</span>]);
  userFormData.append(<span class="hljs-string">"headerTitle"</span>, headerTitleInput.<span class="hljs-built_in">value</span>);
  userFormData.append(<span class="hljs-string">"token"</span>, apiTokenInput.<span class="hljs-built_in">value</span>);
  userFormData.append(<span class="hljs-string">"altImage"</span>, altImageInput.<span class="hljs-built_in">value</span>);
  console.log([...userFormData]);
  createWebsiteButton.classList.add(<span class="hljs-string">"loading"</span>);
  createWebsiteButton.innerText <span class="hljs-operator">=</span> <span class="hljs-string">"wait"</span>;
  websiteLink.style.display <span class="hljs-operator">=</span> <span class="hljs-string">"none"</span>;
  document.getElementById(<span class="hljs-string">"buttonRequired-id"</span>).innerText <span class="hljs-operator">=</span> <span class="hljs-string">""</span>;
  document.getElementById(<span class="hljs-string">"incorrectAPI-id"</span>).innerText <span class="hljs-operator">=</span> <span class="hljs-string">""</span>;
  document.getElementById(<span class="hljs-string">"api-token-id"</span>).style.borderColor <span class="hljs-operator">=</span> <span class="hljs-string">"#1a45df"</span>;

  <span class="hljs-comment">// send `POST` request</span>
  await fetch(url, {
    mode: <span class="hljs-string">"cors"</span>,
    method: <span class="hljs-string">"POST"</span>,
    headers: {
      Accept: <span class="hljs-string">"application/json"</span>,
    },
    body: userFormData,
  })
    .then((res) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
      <span class="hljs-comment">// if status is OK from server, then set the button to its original text</span>
      <span class="hljs-keyword">if</span> (res.status <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">200</span>) {
        createWebsiteButton.classList.remove(<span class="hljs-string">"loading"</span>);
        createWebsiteButton.innerText <span class="hljs-operator">=</span> <span class="hljs-string">"Create Website on Web3.storage"</span>;
        <span class="hljs-keyword">return</span> res.json();
      }
    })
    .then((data) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
      <span class="hljs-comment">// display the website link with the URL from the backend server</span>
      websiteLink.style.display <span class="hljs-operator">=</span> <span class="hljs-string">"block"</span>;
      websiteLink.href <span class="hljs-operator">=</span> data.url;
      headerTitleInput.<span class="hljs-built_in">value</span> <span class="hljs-operator">=</span> <span class="hljs-string">""</span>;
      fileInput.<span class="hljs-built_in">value</span> <span class="hljs-operator">=</span> <span class="hljs-string">""</span>;
    })
    .catch((err) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
      <span class="hljs-comment">// catch error and display a message</span>
      <span class="hljs-comment">// apply border styling</span>
      <span class="hljs-comment">// set the button to its original text</span>
      console.log(<span class="hljs-string">"error: "</span> <span class="hljs-operator">+</span> err);
      document.getElementById(<span class="hljs-string">"api-token-id"</span>).style.borderColor <span class="hljs-operator">=</span> <span class="hljs-string">"red"</span>;
      document.getElementById(<span class="hljs-string">"incorrectAPI-id"</span>).innerText <span class="hljs-operator">=</span>
        <span class="hljs-string">"Something went wrong. Your API token might be incorrect"</span>;
      createWebsiteButton.classList.remove(<span class="hljs-string">"loading"</span>);
      createWebsiteButton.innerText <span class="hljs-operator">=</span> <span class="hljs-string">"Create Website on Web3.storage"</span>;
    });
}
</code></pre><p>Important Parts:</p>
<ul>
<li>Fetch call to send and receive from backend server<ul>
<li>send different data types as Form Object</li>
</ul>
</li>
<li>Added wait text and loading animation after clicking the button</li>
<li>Added error handling if<ul>
<li>Origin is incorrect<ul>
<li>The backend server will only accept the API request if it comes from the frontend website origin.</li>
</ul>
</li>
<li>API token is incorrect</li>
<li>The form is incomplete</li>
</ul>
</li>
<li>Display new website link after a successful response from backend server<div id="id-section6">

</div></li>
</ul>
<h2 id="heading-create-expressjs-backend-server">Create Express.JS Backend Server</h2>
<p>Open up a new project folder to create your backend server. I called mine <code>web3-static-website-maker-backend</code>.</p>
<p>In the terminal, type to initialize our repository.</p>
<p><code>npm init</code></p>
<p>Now install NPM packages we will use to build our backend:</p>
<pre><code>npm i express express<span class="hljs-operator">-</span>fileupload express<span class="hljs-operator">-</span>validator web3.storage cors dotenv
</code></pre><p><code>express</code> - Node.js framework for creating our backend server and API endpoints</p>
<p><code>express-fileupload</code> - To handle the files being uploaded from the frontend</p>
<p><code>express-validator</code> - To sanitize user input coming from the frontend</p>
<p><code>web3.storage</code> - Library that will upload and store files in decentralized storage</p>
<p><code>cors</code> - To restrict the use of our backend APIs to request coming from our frontend</p>
<p><code>dotenv</code> - Use a .env file to store the origin URL in our backend. It is optional since the origin URL does not need to be private. I used it, so I don't have to keep changing the origin for dev and prod environments.</p>
<p>Now we will install <code>nodemon</code> as a dev dependency - To restart our dev server when there are any changes.</p>
<pre><code><span class="hljs-built_in">npm</span> i nodemon -D
</code></pre><p>After the npm install, this will create a <code>package.json</code> file. Open the file, remove the original scripts section (we will be adding our own), and add the following attributes.</p>
<pre><code><span class="hljs-string">"type"</span>: <span class="hljs-string">"module"</span>,
<span class="hljs-string">"scripts"</span>: {
    <span class="hljs-string">"devTest"</span>: <span class="hljs-string">"nodemon server.js"</span>,
    <span class="hljs-string">"start"</span>: <span class="hljs-string">"node server.js"</span>
  },
</code></pre><p>We will be using ES6 module imports for the backend server, so the <code>type</code> is required.</p>
<p>The scripts' attributes are the commands to start our dev and prod backend server.</p>
<p>Create a file called <code>server.js</code> and put it in the root directory.</p>
<pre><code><span class="hljs-comment">// server setup</span>
<span class="hljs-keyword">import</span> <span class="hljs-title">dotenv</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"dotenv"</span>;
dotenv.config();
<span class="hljs-keyword">import</span> <span class="hljs-title">express</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"express"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">fileUpload</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"express-fileupload"</span>;

<span class="hljs-comment">// API routes</span>
<span class="hljs-keyword">import</span> <span class="hljs-title">receiveFilesFromClient</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"./routes/receiveFilesFromClient.js"</span>;

const app <span class="hljs-operator">=</span> express();

<span class="hljs-comment">// enable express-filesupload</span>
app.use(fileUpload());

<span class="hljs-comment">// bring the API routs</span>
app.use(receiveFilesFromClient);

<span class="hljs-comment">// start server</span>

const port <span class="hljs-operator">=</span> process.env.PORT;

app.listen(port <span class="hljs-operator">|</span><span class="hljs-operator">|</span> <span class="hljs-number">8080</span>, () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
  console.log(<span class="hljs-string">"all systems are a go on port "</span> <span class="hljs-operator">+</span> port);
});
</code></pre><p>Important Parts:</p>
<ul>
<li>Created backend server with Express.JS</li>
</ul>
<p>Create a folder called <code>routes</code>. Create a file in that folder called <code>receiveFilesFromClient.js</code>.</p>
<p>Type the following code:</p>
<pre><code><span class="hljs-keyword">import</span> <span class="hljs-title">dotenv</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"dotenv"</span>;
dotenv.config();
<span class="hljs-keyword">import</span> { <span class="hljs-title">Router</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"express"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">cors</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"cors"</span>;
<span class="hljs-comment">// import all the logic for the API routes</span>
<span class="hljs-keyword">import</span> { <span class="hljs-title">createFolders</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"../controller/createFolders.js"</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title">createHtmlFile</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"../controller/createHtmlFile.js"</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title">storeFilesToWeb3Storage</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"../controller/storeFilesToWeb3Storage.js"</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title">uploadFilesFromClient</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"../controller/uploadFilesFromClient.js"</span>;

<span class="hljs-comment">// used to validate the user input from the frontend</span>
<span class="hljs-keyword">import</span> { <span class="hljs-title">body</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"express-validator"</span>;

<span class="hljs-comment">// create Express router for API routes</span>
const router <span class="hljs-operator">=</span> Router();

<span class="hljs-comment">// using CORS to restrict the origin requests to come from the Frontend only</span>
const whitelist <span class="hljs-operator">=</span> [process.env.ORIGIN];
const corsOptions <span class="hljs-operator">=</span> {
  origin: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">origin, callback</span>) </span>{
    <span class="hljs-keyword">if</span> (whitelist.indexOf(origin) <span class="hljs-operator">!</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">-1</span>) {
      console.log(<span class="hljs-string">"origin: "</span> <span class="hljs-operator">+</span> origin);
      callback(null, <span class="hljs-literal">true</span>);
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-comment">// throw error and stop API call if the origin is forbidden</span>
      <span class="hljs-comment">// I'm using a Heroku which restarts the server if it stops</span>
      <span class="hljs-comment">// so no need to restart server in code for production</span>
      console.log(<span class="hljs-string">"origin: "</span> <span class="hljs-operator">+</span> origin);
      <span class="hljs-keyword">throw</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Not allowed by CORS"</span>);
    }
  },
};

router.post(
  <span class="hljs-comment">// the route of the API</span>
  <span class="hljs-string">"/upload-files"</span>,
  <span class="hljs-comment">// check request origin</span>
  cors(corsOptions),
  <span class="hljs-comment">// check and sanitize any user text using express-validator</span>
  body(<span class="hljs-string">"headerTitle"</span>).not().isEmpty().trim().escape(),
  body(<span class="hljs-string">"altImage"</span>).not().isEmpty().trim().escape(),
  <span class="hljs-comment">// call these functions in order</span>
  createFolders,
  createHtmlFile,
  uploadFilesFromClient,
  storeFilesToWeb3Storage
);

export default router;
</code></pre><p>Important Parts:</p>
<ul>
<li>Checking CORS origin first<ul>
<li>throw an error if the origin is forbidden</li>
<li>If you are using a Platform as a Service (PaaS), like Heroku, then you don't have to worry about restarting the server if an error occurs and crashes your backend server. A PaaS will restart the server for you automatically.</li>
</ul>
</li>
<li>Using express-validator to check and sanitize code instead of writing custom logic</li>
<li>Separated the backend logic to the <code>Controller</code> folder to make the code cleaner are easier to read.</li>
</ul>
<p>Create a folder called <code>controller</code>. Create a file in that folder called <code>createFolders.js</code>.</p>
<p>Type the following code:</p>
<pre><code><span class="hljs-keyword">import</span> <span class="hljs-title">fs</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"fs"</span>;

export async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createFolders</span>(<span class="hljs-params">req, res, next</span>) </span>{
  <span class="hljs-comment">//create directory</span>
  <span class="hljs-comment">//create temp dir</span>
  <span class="hljs-comment">// use the folder name received from the Frontend</span>
  const tempDir <span class="hljs-operator">=</span> <span class="hljs-string">"./upload"</span> <span class="hljs-operator">+</span> req.body.folderName;

  <span class="hljs-keyword">if</span> (<span class="hljs-operator">!</span>fs.existsSync(tempDir)) {
    fs.mkdirSync(tempDir);
  }

  <span class="hljs-comment">// create a sub directory to store the file received from the Frontend</span>
  const childTempDir <span class="hljs-operator">=</span> tempDir <span class="hljs-operator">+</span> <span class="hljs-string">"/files/"</span>;

  <span class="hljs-keyword">if</span> (<span class="hljs-operator">!</span>fs.existsSync(childTempDir)) {
    fs.mkdirSync(childTempDir);
  }
  <span class="hljs-comment">// call next() to go to the next function on the route list</span>
  next();
}
</code></pre><p>Important Parts:</p>
<ul>
<li>The <code>fs</code> module is included in Express. There is no need to npm install it separately.</li>
<li>Create a parent folder using the unique name coming from the Frontend</li>
<li>Create a subdirectory to store the file received from the Frontend</li>
<li>Call next() to go to the next function on the route list</li>
</ul>
<p>Create a file in the <code>controller</code> folder called <code>createHtmlFile.js</code>.</p>
<p>Type the following code:</p>
<pre><code><span class="hljs-keyword">import</span> fs <span class="hljs-keyword">from</span> <span class="hljs-string">"fs"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> function createHtmlFile(req, res, next) {
  <span class="hljs-regexp">//</span> Assign variables to the received data
  let headerTitle = req.body.headerTitle;
  <span class="hljs-regexp">//</span> express-fileupload will put any file received <span class="hljs-keyword">from</span> the frontend <span class="hljs-keyword">as</span> req.files
  let imageFile = req.files.image;
  let srcImage = <span class="hljs-string">"/files/"</span> + imageFile.name;
  let altImage = req.body.altImage;
  <span class="hljs-regexp">//</span> define folder path to store the files <span class="hljs-keyword">and</span> user input
  let path = <span class="hljs-string">"./upload"</span> + req.body.folderName + <span class="hljs-string">"/files/"</span>;

  <span class="hljs-regexp">//</span> create HTML file <span class="hljs-keyword">from</span> the user input
  <span class="hljs-regexp">//</span> This <span class="hljs-keyword">is</span> the website the app <span class="hljs-keyword">is</span> making
  <span class="hljs-regexp">//</span> included CSS styling <span class="hljs-keyword">in</span> the style tag
  let htmlContent = `<span class="javascript">&lt;!DOCTYPE html&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">http-equiv</span>=<span class="hljs-string">"X-UA-Compatible"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"IE=edge"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"preconnect"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://fonts.googleapis.com"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"preconnect"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://fonts.gstatic.com"</span> <span class="hljs-attr">crossorigin</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span>
      <span class="hljs-attr">href</span>=<span class="hljs-string">"https://fonts.googleapis.com/css2?family=Merriweather+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;1,300;1,400;1,500;1,600;1,700;1,800&amp;display=swap"</span>
      <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span>
    /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Web3 decentralized website<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">header</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"logo-title"</span>&gt;</span>Web3 Decentralized Website<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">main</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>${headerTitle}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">${srcImage}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"${altImage}"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">footer</span>&gt;</span>made with <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"heart"</span>&gt;</span><span class="hljs-symbol">&amp;hearts;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">footer</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
    <span class="hljs-comment">/* Box sizing rules */</span>
    * {
      <span class="hljs-attribute">box-sizing</span>: border-box;
      <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
      <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
    }

    <span class="hljs-comment">/* Make images easier to work with */</span>
    <span class="hljs-selector-tag">img</span>,
    <span class="hljs-selector-tag">picture</span> {
      <span class="hljs-attribute">max-width</span>: <span class="hljs-number">80%</span>;
    }

    <span class="hljs-selector-pseudo">:root</span> {
      <span class="hljs-attribute">--font-family-header</span>: <span class="hljs-string">"Merriweather Sans"</span>, sans-serif;

      <span class="hljs-attribute">--color-background-header-footer</span>: <span class="hljs-number">#d1bdf7</span>;
      <span class="hljs-attribute">--color-background-body</span>: <span class="hljs-number">#ffffff</span>;
      <span class="hljs-attribute">--color-complimentary-two-background</span>: <span class="hljs-number">#fff4f9</span>;

      <span class="hljs-attribute">--color-primary-font</span>: <span class="hljs-number">#000036</span>;
      <span class="hljs-attribute">--color-secondary-font</span>: <span class="hljs-number">#ffffff</span>;

      <span class="hljs-attribute">--font-size-sm</span>: <span class="hljs-built_in">clamp</span>(<span class="hljs-number">0.5rem</span>, <span class="hljs-number">0.5rem</span> + <span class="hljs-number">1.5vw</span>, <span class="hljs-number">2rem</span>);
      <span class="hljs-attribute">--font-size-100</span>: <span class="hljs-number">0.775rem</span>;
      <span class="hljs-attribute">--font-size-200</span>: <span class="hljs-number">0.875rem</span>;
      <span class="hljs-attribute">--font-size-300</span>: <span class="hljs-number">1rem</span>;
      <span class="hljs-attribute">--font-size-400</span>: <span class="hljs-number">1.125rem</span>;
      <span class="hljs-attribute">--font-size-500</span>: <span class="hljs-number">1.25rem</span>;
      <span class="hljs-attribute">--font-size-600</span>: <span class="hljs-number">1.5rem</span>;
      <span class="hljs-attribute">--font-size-700</span>: <span class="hljs-number">1.875rem</span>;
      <span class="hljs-attribute">--font-size-xl</span>: <span class="hljs-built_in">clamp</span>(<span class="hljs-number">2rem</span>, <span class="hljs-number">1rem</span> + <span class="hljs-number">3vw</span>, <span class="hljs-number">5.75rem</span>);
    }

    <span class="hljs-selector-tag">h1</span> {
      <span class="hljs-attribute">font-size</span>: <span class="hljs-built_in">var</span>(--font-size-xl);
      <span class="hljs-attribute">line-height</span>: <span class="hljs-number">1.1</span>;
    }

    <span class="hljs-selector-class">.logo-title</span> {
      <span class="hljs-attribute">font-size</span>: <span class="hljs-built_in">var</span>(--font-size-<span class="hljs-number">700</span>);
    }

    <span class="hljs-comment">/* Set Grid Layout, min-height, some color, and padding on the top and bottom */</span>
    <span class="hljs-selector-tag">body</span> {
      <span class="hljs-attribute">display</span>: grid;
      <span class="hljs-attribute">grid-template-rows</span>: auto <span class="hljs-number">1</span>fr auto;
      <span class="hljs-attribute">min-height</span>: <span class="hljs-number">100vh</span>;
      <span class="hljs-attribute">font-family</span>: <span class="hljs-built_in">var</span>(--font-family-header);
    }

    <span class="hljs-selector-tag">main</span> {
      <span class="hljs-attribute">margin</span>: auto;
      <span class="hljs-attribute">text-align</span>: center;
      <span class="hljs-attribute">padding-block</span>: <span class="hljs-number">2vw</span>;
    }

    <span class="hljs-selector-tag">header</span> {
      <span class="hljs-attribute">font-size</span>: <span class="hljs-built_in">var</span>(--font-size-<span class="hljs-number">700</span>);
    }

    <span class="hljs-selector-tag">header</span>,
    <span class="hljs-selector-tag">footer</span> {
      <span class="hljs-attribute">text-align</span>: center;
      <span class="hljs-attribute">padding-block</span>: <span class="hljs-number">2vw</span>;
      <span class="hljs-attribute">background</span>: <span class="hljs-built_in">var</span>(--color-background-header-footer);
    }

    <span class="hljs-selector-class">.heart</span> {
      <span class="hljs-attribute">color</span>: red;
    }
  </span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span></span>`;

  //create html page <span class="hljs-keyword">and</span> save html page to file folder using the FS <span class="hljs-built_in">module</span>
  fs.writeFile(path + <span class="hljs-string">"index.html"</span>, htmlContent, function (err) {
    <span class="hljs-keyword">if</span> (err) <span class="hljs-keyword">throw</span> err;
  });

  <span class="hljs-regexp">//</span> call next() to go to the next function <span class="hljs-literal">on</span> the route list
  next();
}
</code></pre><p>Important Parts:</p>
<ul>
<li>Assign variables to the received data</li>
<li><code>Express-fileupload</code> will put any file received from the frontend as req.files</li>
<li>Define folder path to store the files and user input</li>
<li>Create an HTML file from the user input</li>
<li>Save HTML file to the file folder</li>
<li>Call next() to go to the next function on the route list</li>
</ul>
<p>Create a file in the <code>controller</code> folder called <code>uploadFilesFromClient.js</code>.</p>
<p>Type the following code:</p>
<pre><code>export async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">uploadFilesFromClient</span>(<span class="hljs-params">req, res, next</span>) </span>{
  <span class="hljs-keyword">try</span> {
      <span class="hljs-comment">//Use the name of the input field to retrieve the uploaded file</span>
      let imageFile <span class="hljs-operator">=</span> req.files.image;

      <span class="hljs-comment">//Use the mv() method to place the file in upload directory (i.e. "uploads")</span>
      imageFile.mv(
        <span class="hljs-string">"./upload"</span> <span class="hljs-operator">+</span> req.body.folderName <span class="hljs-operator">+</span> <span class="hljs-string">"/files/"</span> <span class="hljs-operator">+</span> imageFile.<span class="hljs-built_in">name</span>
      );
      <span class="hljs-comment">// call next() to go to the next function on the route list</span>
      next();
  } <span class="hljs-keyword">catch</span> (err) {
    res.status(<span class="hljs-number">500</span>).<span class="hljs-built_in">send</span>(err);
  }
}
</code></pre><p>Important Parts:</p>
<ul>
<li>Move the files using <code>express-fileupload</code> to the files directory</li>
<li>Call next() to go to the next function on the route list</li>
</ul>
<p>Create a file in the <code>controller</code> folder called <code>storeFilesToWeb3Storage.js</code>.</p>
<p>Type the following code:</p>
<pre><code><span class="hljs-comment">// import the web3.storage library</span>
<span class="hljs-keyword">import</span> { <span class="hljs-title">Web3Storage</span>, <span class="hljs-title">getFilesFromPath</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"web3.storage"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">fs</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"fs"</span>;

export async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">storeFilesToWeb3Storage</span>(<span class="hljs-params">req, res</span>) </span>{
  <span class="hljs-comment">// define folder path where the files are located</span>
  let parentPath <span class="hljs-operator">=</span> <span class="hljs-string">"./upload"</span> <span class="hljs-operator">+</span> req.body.folderName;
  let path <span class="hljs-operator">=</span> <span class="hljs-string">"./upload"</span> <span class="hljs-operator">+</span> req.body.folderName <span class="hljs-operator">+</span> <span class="hljs-string">"/files/"</span>;

  const token <span class="hljs-operator">=</span> req.body.token;

  <span class="hljs-comment">// Use API token to start the storage process</span>
  const <span class="hljs-keyword">storage</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> Web3Storage({ token });

  <span class="hljs-comment">// get the files that the user uploaded</span>
  const files <span class="hljs-operator">=</span> await getFiles(path);

  console.log(`Uploading ${files.<span class="hljs-built_in">length</span>} files`);
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// store files</span>
    <span class="hljs-comment">// Store the files in web3.storage, if successful it will return a cid - address where the files are stored</span>
    const cid <span class="hljs-operator">=</span> await <span class="hljs-keyword">storage</span>.put(files);
    console.log(<span class="hljs-string">"Content added with CID:"</span>, cid);
    <span class="hljs-comment">// remove the temp folders so we don't store anything the user sent on the backend server</span>
    await removeDir(parentPath);
    <span class="hljs-comment">//send new website URL in response</span>
    res.json({
      message: <span class="hljs-string">"File is uploaded"</span>,
      url: <span class="hljs-string">"https://"</span> <span class="hljs-operator">+</span> cid <span class="hljs-operator">+</span> <span class="hljs-string">".ipfs.dweb.link/files/index.html"</span>,
    });
  } <span class="hljs-keyword">catch</span> (<span class="hljs-function"><span class="hljs-keyword">error</span>) </span>{
    <span class="hljs-comment">// if the token is incorrect, catch the error and send status to client</span>
    res.status(<span class="hljs-number">403</span>).json({ <span class="hljs-function"><span class="hljs-keyword">error</span>: "<span class="hljs-title">incorrect</span> <span class="hljs-title">token</span>: " + <span class="hljs-title"><span class="hljs-keyword">error</span></span> })</span>;
    console.error(<span class="hljs-string">"i found error: "</span> <span class="hljs-operator">+</span> <span class="hljs-function"><span class="hljs-keyword">error</span>)</span>;
    await removeDir(parentPath);
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  }
}

<span class="hljs-comment">// function that gets the files stored in the file folder</span>
async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getFiles</span>(<span class="hljs-params">path</span>) </span>{
  const files <span class="hljs-operator">=</span> await getFilesFromPath(path);
  console.log(`read ${files.<span class="hljs-built_in">length</span>} file(s) <span class="hljs-keyword">from</span> ${path}`);
  <span class="hljs-keyword">return</span> files;
}
<span class="hljs-comment">// function to remove file directory</span>
async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">removeDir</span>(<span class="hljs-params">path</span>) </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">//  fs.rmdirSync(removePath);</span>
    fs.rmSync(path, { recursive: <span class="hljs-literal">true</span> });
  } <span class="hljs-keyword">catch</span> (<span class="hljs-function"><span class="hljs-keyword">error</span>) </span>{
    console.error(<span class="hljs-function"><span class="hljs-keyword">error</span>)</span>;
  }
}
</code></pre><p>Important Parts:</p>
<ul>
<li>Use web3.storage library to store files in decentralized storage</li>
<li>If the API token is incorrect, then it will throw an error<ul>
<li>The frontend site will display an error</li>
<li>The backend site will crash but will get restarted in prod if using a PaaS, like Heroku</li>
</ul>
</li>
<li>remove the temp directory<ul>
<li>this is important because we don't want to store any files from the user on our backend server</li>
</ul>
</li>
<li>Send the URL of the new website that was created and deployed onto decentralized storage.</li>
</ul>
<p>You have now created a full-stack app that makes and deploys a one-page decentralized website.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Build a ETH Gas Price Tracker and convert to USD with HTML, CSS, Vanilla JavaScript, and Web3.js library]]></title><description><![CDATA[My Table of content

Intended Audience
What are we Building?
Prerequisite
Folder Structure
Create Layout with HTML and CSS
Write Client-Side JavaScript



Intended Audience

Experience or familiarity of using JavaScript to write into HTML elements
do...]]></description><link>https://blog.codingraj.dev/build-a-eth-gas-price-tracker</link><guid isPermaLink="true">https://blog.codingraj.dev/build-a-eth-gas-price-tracker</guid><category><![CDATA[Web3]]></category><category><![CDATA[Ethereum]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Netlify]]></category><dc:creator><![CDATA[codingraj]]></dc:creator><pubDate>Sun, 27 Feb 2022 17:03:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1636821587480/i70DTHQ0q.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-my-table-of-content">My Table of content</h1>
<ul>
<li><a class="post-section-overview" href="#id-section1">Intended Audience</a></li>
<li><a class="post-section-overview" href="#id-section2">What are we Building?</a></li>
<li><a class="post-section-overview" href="#id-section3">Prerequisite</a></li>
<li><a class="post-section-overview" href="#id-section4">Folder Structure</a></li>
<li><a class="post-section-overview" href="#id-section5">Create Layout with HTML and CSS</a></li>
<li><a class="post-section-overview" href="#id-section6">Write Client-Side JavaScript</a></li>
</ul>
<div id="id-section1">

<h2 id="heading-intended-audience">Intended Audience</h2>
<ul>
<li>Experience or familiarity of using JavaScript to write into HTML elements<ul>
<li>document.createElement()</li>
<li>document.createTextNode()</li>
<li>appendChild()</li>
<li>insertBefore()</li>
</ul>
</li>
<li>Experience or familiarity of using 3rd party API</li>
<li>Newbies are welcome. Follow along and google (I use DuckDuckGo) anything you need more clarity on. Intermediate/Advanced programmers do this all the time.<div id="id-section2">

</div></li>
</ul>
<h2 id="heading-what-are-we-building">What are we Building?</h2>
<ul>
<li>A website (<a target="_blank" href="https://web3gaspricetracker.netlify.app">demo link</a>)<ul>
<li>Gets the current gas price using the Web3.js API every 1 second</li>
<li>Display the current price gas price in WEI, ETH</li>
<li>Convert and display the current gas price in USD using a 3rd party currency converter API</li>
<li>show a trend in % if the gas price is rising or falling from the previous price         </li>
</ul>
</li>
<li>We will be using HTML, CSS, and Vanilla JavaScript to build the website.</li>
<li>The  <a target="_blank" href="https://github.com/coding-island-js/web3-playground">code</a> is publicly available at GitHub.<div id="id-section3">

</div></li>
</ul>
<h2 id="heading-prerequisite">Prerequisite</h2>
<ul>
<li>Any code editor (I use VSCode)<div id="id-section4">

</div></li>
</ul>
<h2 id="heading-folder-structure">Folder Structure</h2>
<pre><code>project folder
│   index.html
│   script.js
│   style.css
</code></pre><div id="id-section5">

<h2 id="heading-create-layout-with-html-and-css">Create Layout with HTML and CSS</h2>
<p>Open up your code editor (I use VSCode). Create a folder. I called mine <code>web3-playground</code>.</p>
<p>Any name will do.</p>
<p>Create an HTML file called <code>index.html</code></p>
<p>VSCode has a shortcut to create an HTML boilerplate. Type:</p>
<pre><code><span class="hljs-addition">!</span>
</code></pre><p>or copy below:</p>
<pre><code><span class="hljs-operator">&lt;</span><span class="hljs-operator">!</span>DOCTYPE html<span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span>html lang<span class="hljs-operator">=</span><span class="hljs-string">"en"</span><span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span>head<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>meta charset<span class="hljs-operator">=</span><span class="hljs-string">"UTF-8"</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>meta http<span class="hljs-operator">-</span>equiv<span class="hljs-operator">=</span><span class="hljs-string">"X-UA-Compatible"</span> content<span class="hljs-operator">=</span><span class="hljs-string">"IE=edge"</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>meta name<span class="hljs-operator">=</span><span class="hljs-string">"viewport"</span> content<span class="hljs-operator">=</span><span class="hljs-string">"width=device-width, initial-scale=1.0"</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>title<span class="hljs-operator">&gt;</span>Document<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>title<span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>head<span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span>body<span class="hljs-operator">&gt;</span>

<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>body<span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>html<span class="hljs-operator">&gt;</span>
</code></pre><p>Give your HTML page a title. Any title will do.</p>
<pre><code><span class="hljs-operator">&lt;</span>title<span class="hljs-operator">&gt;</span>Web3.js Gas Price Tracker<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>title<span class="hljs-operator">&gt;</span>
</code></pre><p>Create a header and main section. We will create a 4 column layout showing Gas Price in Wei, Gas Price in ETH, Gas Price in USD, and the % trend from the price 1 second ago.</p>
<pre><code>  <span class="hljs-operator">&lt;</span>body<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>header<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>h1<span class="hljs-operator">&gt;</span>Web3.js Gas Price Tracker<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>h1<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>header<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>main<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>div class<span class="hljs-operator">=</span><span class="hljs-string">"gas-price"</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>p class<span class="hljs-operator">=</span><span class="hljs-string">"column-header"</span><span class="hljs-operator">&gt;</span>gas <span class="hljs-literal">wei</span>:<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>p<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>ul id<span class="hljs-operator">=</span><span class="hljs-string">"parent"</span><span class="hljs-operator">&gt;</span>
          <span class="hljs-operator">&lt;</span><span class="hljs-operator">!</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span> This <span class="hljs-keyword">is</span> where the current Gas Price in Wei goes <span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>ul<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>div<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>div class<span class="hljs-operator">=</span><span class="hljs-string">"eth-price"</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>p class<span class="hljs-operator">=</span><span class="hljs-string">"column-header"</span><span class="hljs-operator">&gt;</span>gas eth:<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>p<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>ul id<span class="hljs-operator">=</span><span class="hljs-string">"parent-eth"</span><span class="hljs-operator">&gt;</span>
          <span class="hljs-operator">&lt;</span><span class="hljs-operator">!</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span> This <span class="hljs-keyword">is</span> where the current Gas Price in ETH goes <span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>ul<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>div<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>div class<span class="hljs-operator">=</span><span class="hljs-string">"usd-price"</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>p class<span class="hljs-operator">=</span><span class="hljs-string">"column-header"</span><span class="hljs-operator">&gt;</span>gas usd:<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>p<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>ul id<span class="hljs-operator">=</span><span class="hljs-string">"parent-usd"</span><span class="hljs-operator">&gt;</span>
          <span class="hljs-operator">&lt;</span><span class="hljs-operator">!</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span> This <span class="hljs-keyword">is</span> where the current Gas Price in USD goes <span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>ul<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>div<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>div class<span class="hljs-operator">=</span><span class="hljs-string">"trend"</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>p class<span class="hljs-operator">=</span><span class="hljs-string">"column-header"</span><span class="hljs-operator">&gt;</span>trend:<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>p<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>ul id<span class="hljs-operator">=</span><span class="hljs-string">"parent-trend"</span><span class="hljs-operator">&gt;</span>
          <span class="hljs-operator">&lt;</span><span class="hljs-operator">!</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span> This <span class="hljs-keyword">is</span> where we show the <span class="hljs-operator">%</span> change in prices <span class="hljs-keyword">from</span> <span class="hljs-number">1</span> second ago <span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>ul<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>div<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>main<span class="hljs-operator">&gt;</span>
  <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>body<span class="hljs-operator">&gt;</span>
</code></pre><p>Add some CSS to format the layout with Grid and add some color.</p>
<p>Create a CSS file called: <code>style.css</code></p>
<p>Create a link to the CSS file on <code>index.html</code> in the head section.</p>
<pre><code><span class="hljs-operator">&lt;</span>link rel<span class="hljs-operator">=</span><span class="hljs-string">"stylesheet"</span> href<span class="hljs-operator">=</span><span class="hljs-string">"style.css"</span><span class="hljs-operator">&gt;</span>
</code></pre><p>Open style.css and set the box-sizing to border-box. Use the body tag to create the Grid for the header and main section. We will also use Grid in the Main element to create a 4 column layout for the Gas Prices.</p>
<pre><code><span class="hljs-comment">/* Box sizing rules */</span>
* {
  <span class="hljs-attribute">box-sizing</span>: border-box;
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
}

<span class="hljs-comment">/* Set Grid Layout and line height */</span>
<span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">grid-template-rows</span>: auto <span class="hljs-number">1</span>fr;
  <span class="hljs-attribute">text-rendering</span>: optimizeSpeed;
  <span class="hljs-attribute">line-height</span>: <span class="hljs-number">1.5</span>;
}

<span class="hljs-selector-tag">main</span> {
  <span class="hljs-attribute">grid-row</span>: <span class="hljs-number">2</span> / <span class="hljs-number">3</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">2vw</span>;
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">2vw</span>;
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">1</span>fr <span class="hljs-number">1</span>fr <span class="hljs-number">1</span>fr <span class="hljs-number">1</span>fr;
}

<span class="hljs-selector-class">.gas-price</span> {
  <span class="hljs-attribute">grid-column</span>: <span class="hljs-number">1</span> / <span class="hljs-number">2</span>;
}

<span class="hljs-selector-class">.eth-price</span> {
  <span class="hljs-attribute">grid-column</span>: <span class="hljs-number">2</span> / <span class="hljs-number">3</span>;
}

<span class="hljs-selector-class">.usd-price</span> {
  <span class="hljs-attribute">grid-column</span>: <span class="hljs-number">3</span> / <span class="hljs-number">4</span>;
}

<span class="hljs-selector-class">.trend</span> {
  <span class="hljs-attribute">grid-column</span>: <span class="hljs-number">4</span> / <span class="hljs-number">5</span>;
}

<span class="hljs-selector-class">.column-header</span> {
  <span class="hljs-attribute">text-align</span>: center;
  <span class="hljs-attribute">font-size</span>: larger;
  <span class="hljs-attribute">background-color</span>: beige;
}
</code></pre><div id="id-section6">

<h2 id="heading-write-client-side-javascript">Write Client-Side JavaScript</h2>
<p>Create a file called <code>script.js</code> in the root folder.</p>
<p>Add a script tag to link the script.js to the <code>index.html</code>.</p>
<p>Add a script tag to link the web3.js library to the <code>index.html</code>.</p>
<pre><code><span class="hljs-operator">&lt;</span>​script​ ​src​<span class="hljs-operator">=</span><span class="hljs-string">"​https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js​"</span>​<span class="hljs-operator">&gt;</span>​<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>​script​<span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span>script src<span class="hljs-operator">=</span><span class="hljs-string">"/script.js"</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>script<span class="hljs-operator">&gt;</span>
</code></pre><p>To read the Ethereum blockchain, you need a gateway to read it. Cloudflare provides a gateway that is free to use. Just use this URL <code>https://cloudflare-eth.com</code>.</p>
<pre><code>const web3 <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> Web3(<span class="hljs-string">"https://cloudflare-eth.com"</span>);

<span class="hljs-comment">// this variable will be the HTML ID value for the gas prices.</span>
let dynamicElementID <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;

<span class="hljs-comment">// get gas price and convert to eth and usd every 1 second using the Set Interval Function</span>
const interval <span class="hljs-operator">=</span> setInterval(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// when this function runs every 1 second, we will increment the ID value by 1. This will make more sense later in the code</span>
  dynamicElementID <span class="hljs-operator">=</span> dynamicElementID <span class="hljs-operator">+</span> <span class="hljs-number">1</span>;

  <span class="hljs-comment">// get gas price in WEI from Web3.js</span>
  web3.eth.getGasPrice().then((data) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    <span class="hljs-comment">// create bullet point element and assign an ID</span>
    <span class="hljs-comment">// the ID is used to compare the current price and the last price 1 second ago</span>
    let timeOutResults <span class="hljs-operator">=</span> document.createElement(<span class="hljs-string">"li"</span>);
    timeOutResults.id <span class="hljs-operator">=</span> dynamicElementID;

    <span class="hljs-comment">// bind and display WEI gas price to the html element</span>
    let textNode <span class="hljs-operator">=</span> document.createTextNode(data);
    timeOutResults.appendChild(textNode);
    let parent <span class="hljs-operator">=</span> document.getElementById(<span class="hljs-string">"parent"</span>);
    parent.insertBefore(timeOutResults, parent.childNodes[<span class="hljs-number">0</span>]);

    <span class="hljs-comment">// get gas price in ETH from Web3.js and show 12 decimal places</span>
    let etherValue <span class="hljs-operator">=</span> Web3.utils.fromWei(data, <span class="hljs-string">"ether"</span>);
    etherValue <span class="hljs-operator">=</span> Number(etherValue).toFixed(<span class="hljs-number">12</span>);

    <span class="hljs-comment">// bind and display ETH gas price to the html element</span>
    let ethResults <span class="hljs-operator">=</span> document.createElement(<span class="hljs-string">"li"</span>);
    let ethTextNode <span class="hljs-operator">=</span> document.createTextNode(etherValue);
    ethResults.appendChild(ethTextNode);
    let parentETH <span class="hljs-operator">=</span> document.getElementById(<span class="hljs-string">"parent-eth"</span>);
    parentETH.insertBefore(ethResults, parentETH.childNodes[<span class="hljs-number">0</span>]);

    <span class="hljs-comment">// calculate the trend</span>
    <span class="hljs-comment">// grab last price using the ID created 1 second ago (current ID - 1)</span>
    let lastPriceID <span class="hljs-operator">=</span> dynamicElementID <span class="hljs-operator">-</span> <span class="hljs-number">1</span>;
    let lastPrice <span class="hljs-operator">=</span> document.getElementById(lastPriceID);

    <span class="hljs-comment">// get current price in WEI</span>
    let currentPrice <span class="hljs-operator">=</span> data;

    <span class="hljs-comment">//calculate the difference between the current price and last price in percentage</span>
    let difference <span class="hljs-operator">=</span> Math.floor(
      ((currentPrice <span class="hljs-operator">-</span> lastPrice.innerText) <span class="hljs-operator">/</span> lastPrice.innerText) <span class="hljs-operator">*</span> <span class="hljs-number">100</span>
    );

     <span class="hljs-comment">// bind and display trend % to the html element</span>
    let trendResults <span class="hljs-operator">=</span> document.createElement(<span class="hljs-string">"li"</span>);
    trendResults.id <span class="hljs-operator">=</span> <span class="hljs-string">"trend-"</span> <span class="hljs-operator">+</span> dynamicElementID;
    let trendTextNode <span class="hljs-operator">=</span> document.createTextNode(difference <span class="hljs-operator">+</span> <span class="hljs-string">"%"</span>);
    trendResults.appendChild(trendTextNode);
    let parentTrend <span class="hljs-operator">=</span> document.getElementById(<span class="hljs-string">"parent-trend"</span>);
    parentTrend.insertBefore(trendResults, parentTrend.childNodes[<span class="hljs-number">0</span>]);

    <span class="hljs-comment">//convert ETH to USD using a free Currency Converter API</span>

    fetch(<span class="hljs-string">"https://api.cryptonator.com/api/full/eth-usd"</span>)
      .then((response) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> response.json())
      .then((data) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
        let usdResults <span class="hljs-operator">=</span> document.createElement(<span class="hljs-string">"li"</span>);
        let usdPrice <span class="hljs-operator">=</span> etherValue <span class="hljs-operator">*</span> data.ticker.price;
        let usdTextNode <span class="hljs-operator">=</span> document.createTextNode(<span class="hljs-string">"$"</span> <span class="hljs-operator">+</span> usdPrice.toFixed(<span class="hljs-number">4</span>));
        usdResults.appendChild(usdTextNode);

        <span class="hljs-comment">// use color to show if the trend is staying the same (yellow), increasing (green), or decreasing (pink)</span>
        <span class="hljs-keyword">if</span> (difference <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>) {
          trendResults.style.backgroundColor <span class="hljs-operator">=</span> <span class="hljs-string">"yellow"</span>;
          usdResults.style.backgroundColor <span class="hljs-operator">=</span> <span class="hljs-string">"yellow"</span>;
        }

        <span class="hljs-keyword">if</span> (difference <span class="hljs-operator">&gt;</span> <span class="hljs-number">0</span>) {
          trendResults.style.backgroundColor <span class="hljs-operator">=</span> <span class="hljs-string">"lightgreen"</span>;
          usdResults.style.backgroundColor <span class="hljs-operator">=</span> <span class="hljs-string">"lightgreen"</span>;
        }

        <span class="hljs-keyword">if</span> (difference <span class="hljs-operator">&lt;</span> <span class="hljs-number">0</span>) {
          trendResults.style.backgroundColor <span class="hljs-operator">=</span> <span class="hljs-string">"lightpink"</span>;
          usdResults.style.backgroundColor <span class="hljs-operator">=</span> <span class="hljs-string">"lightpink"</span>;
        }

        let parentUSD <span class="hljs-operator">=</span> document.getElementById(<span class="hljs-string">"parent-usd"</span>);
        parentUSD.insertBefore(usdResults, parentUSD.childNodes[<span class="hljs-number">0</span>]);
      });
  });
}, <span class="hljs-number">1000</span>);
</code></pre><p>You now have an ETH Gas Tracker that updates every 1 second using the Web3.js library built with HTML, CSS, and Vanilla JavaScript.</p>
</div></div></div>]]></content:encoded></item><item><title><![CDATA[Gathering Requirements Techniques - Be Flexible]]></title><description><![CDATA[No defined way to gather requirements
There is a good chance that no one at the company will tell you how to gather requirements. You have to figure it out yourself.
Why is that?
Most companies don't have a business analyst whose primary role is to g...]]></description><link>https://blog.codingraj.dev/gathering-requirements-techniques-be-flexible</link><guid isPermaLink="true">https://blog.codingraj.dev/gathering-requirements-techniques-be-flexible</guid><category><![CDATA[business]]></category><category><![CDATA[project management]]></category><category><![CDATA[Scope]]></category><category><![CDATA[software development]]></category><dc:creator><![CDATA[codingraj]]></dc:creator><pubDate>Mon, 13 Dec 2021 17:17:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1639415683108/LdFuJ-6iJj.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-no-defined-way-to-gather-requirements">No defined way to gather requirements</h2>
<p>There is a good chance that no one at the company will tell you how to gather requirements. You have to figure it out yourself.</p>
<p>Why is that?</p>
<p><strong>Most companies don't have a business analyst whose primary role is to gather requirements.</strong></p>
<p>So if there are no business analysts, then who gathers the requirements?</p>
<p>Product Owners most likely will try to gather requirements while juggling a hundred other things to do.</p>
<p>But sometimes, it is left to the developers, especially if the product owner has too much on their plate, which happens to most product owners. </p>
<p><strong>No worries. You don't have to be a business analyst to gather requirements. But if you are in a position with some sway, I would advocate having a business analyst full time to collect and refine requirements.</strong></p>
<h2 id="heading-be-flexible">Be Flexible</h2>
<p>There will be times when you set up an interview with a user, and when others find out, like your boss or colleague, they want to be in the meeting.</p>
<p>When you have too many people involved with gathering requirements, you may not be able to ask all the questions you want. </p>
<p>The user could come late or leave early for the requirements interview because they have more pressing things to do in their day job. <strong>Users are busy, so you have to have respect their time.</strong></p>
<p><strong>Be adaptable.</strong> Expect that you need to do follow-up interviews. After the meeting, ask the user if you could do a quick call or ask questions over email/chat. Chances are you have more questions for the users. <strong>Most users like to be involved, especially if their input is valued.</strong></p>
<p>If users feel what they say may change the system for the better, the more likely they will want to partake in requirements sessions.</p>
<h2 id="heading-trust-me-you-will-get-better-at-gathering-requirements">Trust me. You will get better at gathering requirements.</h2>
<p>It sounds crazy when you have a day where you can't comprehend any users' jargon when they convey their requirements and needs. It may not feel like it. But you will get better at gathering requirements.</p>
<p>You will start to understand the business processes and requirements. <strong>Just remember to keep learning. If you look back after one year, you will be amazed at how much you comprehended.</strong></p>
]]></content:encoded></item><item><title><![CDATA[Gathering Requirements Techniques - Selecting Users]]></title><description><![CDATA[Expert users vs. Newbie users
Talk to both types of users. 
Expert users will know the common pain points for features that are used a lot or impact the bottom line, which helps decide which features to develop in the upcoming development cycle.
Expe...]]></description><link>https://blog.codingraj.dev/gathering-requirements-techniques-selecting-users</link><guid isPermaLink="true">https://blog.codingraj.dev/gathering-requirements-techniques-selecting-users</guid><category><![CDATA[project management]]></category><category><![CDATA[software development]]></category><dc:creator><![CDATA[codingraj]]></dc:creator><pubDate>Sat, 04 Dec 2021 16:40:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638633582740/RiPQ3GgTb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-expert-users-vs-newbie-users">Expert users vs. Newbie users</h1>
<p>Talk to both types of users. </p>
<p><strong>Expert users will know the common pain points for features</strong> that are used a lot or impact the bottom line, which helps decide which features to develop in the upcoming development cycle.</p>
<p><strong>Expert users will answer questions that you should be asking.</strong> You may not know what to ask if you are new to the system or even the company. An expert user will know this and help you with what you should know.</p>
<p>If you find a user like this, develop a good relationship with them and ask them if you could use them as a resource in the future.</p>
<p><strong>A newbie user can tell you how easy or frustrating it is to use the system.</strong> This information helps UX designers. You want features to be discoverable and learnable without much help. Watching a new user use the system can tell you that.</p>
<p>With expert and newbie users, they will tell you solutions. Scribble them down, but they may not be the right solution. </p>
<p><strong>Design is not for everybody. Users don't surely make good designers.</strong></p>
<p>Let the design team come up with a solution. It is better to capture their idea, pain points, and goals and use that to develop a design.</p>
<p>Perhaps the design will be similar to the users' solution, but maybe not. Either way, write down what they say but don't anticipate it being the solution.</p>
]]></content:encoded></item></channel></rss>