<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: an-object-is-a</title>
    <description>The latest articles on DEV Community by an-object-is-a (@anobjectisa).</description>
    <link>https://dev.to/anobjectisa</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F475657%2F58613a66-65ca-4354-93d5-3c726b0ac0ff.png</url>
      <title>DEV Community: an-object-is-a</title>
      <link>https://dev.to/anobjectisa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/anobjectisa"/>
    <language>en</language>
    <item>
      <title>How Taskade Helps You With Project Management (Hint: Take some stress away)</title>
      <dc:creator>an-object-is-a</dc:creator>
      <pubDate>Fri, 04 Jun 2021 13:41:14 +0000</pubDate>
      <link>https://dev.to/anobjectisa/how-taskade-helps-you-with-project-management-hint-take-some-stress-away-jpn</link>
      <guid>https://dev.to/anobjectisa/how-taskade-helps-you-with-project-management-hint-take-some-stress-away-jpn</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kJLpLQmX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120724052-0524ab00-c4a1-11eb-90e7-c8332e2d21d2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kJLpLQmX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120724052-0524ab00-c4a1-11eb-90e7-c8332e2d21d2.png" alt="a look at Taskade"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;This is a sponsored blog post. Thanks to &lt;a href="https://www.taskade.com"&gt;Taskade&lt;/a&gt; for reaching out to me.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;I'm going to come right out and say it, &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I don't want the chaos of the pre-Covid office world in my home.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It was already enough when you could totally and without retribution answer office e-mails only when on-the-clock (&lt;em&gt;wink&lt;/em&gt; &lt;em&gt;wink&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Imagine the "just one more thing"-creep (read: &lt;a href="https://en.wikipedia.org/wiki/Mission_creep"&gt;Mission creep&lt;/a&gt;) now that companies are developing strategies for tackling &lt;strong&gt;&lt;em&gt;the new workplace environment&lt;/em&gt;&lt;/strong&gt;...&lt;/p&gt;

&lt;p&gt;One of the complications that comes with working in this new normal--especially a remote one--is,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How do you manage shared work-loads when missing the nuance of face-to-face communication?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;All of the subtleties of in-person communication have been turned on their head.&lt;/p&gt;

&lt;p&gt;I hear companies want the in-office days to come back...&lt;/p&gt;

&lt;p&gt;I hear employees have gotten a taste of that sweet sweet work from home/park/cafe/library/&lt;em&gt;boat&lt;/em&gt;? freedom--cubicles or a work-life balance? &lt;strong&gt;&lt;em&gt;Very&lt;/em&gt;&lt;/strong&gt; difficult decision...&lt;/p&gt;

&lt;p&gt;We're entering a new world and when life gets chaotic, what's the solution for coping?&lt;/p&gt;

&lt;p&gt;Simplify.&lt;/p&gt;

&lt;p&gt;Control what you can; the rest? Que Sera, Sera (translation: What will be will be).&lt;/p&gt;

&lt;p&gt;Simplify your life in general, but your work especially.&lt;/p&gt;

&lt;p&gt;For those of you new to this remote work game--welcome, glad to have you; for those of you looking to become self-starting, go get'em entrepreneurs!--multiple streams of income anyone?; for those of you who just want to simplify your work life...&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Taskade&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  So let's get to it.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  What is Taskade?
&lt;/h4&gt;

&lt;p&gt;Taskade is a project management platform.&lt;br&gt;
Basically it's an app that helps coordinate a workload between team members or just all by yourself.&lt;br&gt;
Think of it like a combination of to-do lists, zoom meetings, and deadline planning.&lt;/p&gt;

&lt;p&gt;You can use it for any project timeline: daily, weekly, monthly, yearly...&lt;/p&gt;

&lt;p&gt;Taskade is designed to be simple and to-the-point. It helps you get your goals "on paper" as effortlessly as possible.&lt;/p&gt;

&lt;p&gt;After all, &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You don't want to stress out over &lt;strong&gt;planning&lt;/strong&gt; your goals. You're not getting paid for that. You're getting paid to &lt;strong&gt;achieve&lt;/strong&gt; your goals.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's break this down into 6 sections:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A meta-view of the platform--the general work-flow of Taskade.&lt;/li&gt;
&lt;li&gt;In-depth into the parts of that work-flow.&lt;/li&gt;
&lt;li&gt;Keeping track of the work-flow. Now that you have all of that information swimming around, how do you manage it?&lt;/li&gt;
&lt;li&gt;How to bring in and manage team members--communication between colleagues.&lt;/li&gt;
&lt;li&gt;Platform &amp;amp; pricing options.&lt;/li&gt;
&lt;li&gt;My final impressions.&lt;/li&gt;
&lt;/ol&gt;


&lt;h3&gt;
  
  
  Meta-view.
&lt;/h3&gt;

&lt;p&gt;The Taskade dashboard is very basic. Taskade emphasizes simplicity. You have your left hand sidebar, the main window in the center, and a user &amp;amp; app settings button in the top-right corner.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hmXAN7g1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120724420-c6dbbb80-c4a1-11eb-86d4-861fa02d0a6c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hmXAN7g1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120724420-c6dbbb80-c4a1-11eb-86d4-861fa02d0a6c.png" alt="taskade dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Very simple. Very clean.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now on to the work-flow.&lt;/p&gt;
&lt;h4&gt;
  
  
  The Taskade work-flow is broken down into 4 stages.
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;Workspace -&amp;gt; Project -&amp;gt; Block -&amp;gt; Task&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P72m_JEt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120725737-a06b4f80-c4a4-11eb-9a6d-dfd8d9872b19.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P72m_JEt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120725737-a06b4f80-c4a4-11eb-9a6d-dfd8d9872b19.png" alt="work-flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You start by creating a workspace.&lt;/p&gt;

&lt;p&gt;Within workspaces you create projects.&lt;/p&gt;

&lt;p&gt;Within projects you create blocks.&lt;/p&gt;

&lt;p&gt;And within blocks you create tasks. Tasks are the "&lt;strong&gt;do's&lt;/strong&gt;" of your to-do lists.&lt;/p&gt;

&lt;p&gt;Let's go into more depth.&lt;/p&gt;


&lt;h3&gt;
  
  
  The Work-flow In-Depth.
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Workspace
&lt;/h4&gt;

&lt;p&gt;You start Taskade by creating a workspace. It's easy and straightforward; there's not much to it.&lt;/p&gt;
&lt;h4&gt;
  
  
  Project
&lt;/h4&gt;

&lt;p&gt;In our new workspace, we can create a project in one of three ways: &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. A blank canvas.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HU0Ok68O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120726060-474feb80-c4a5-11eb-8cb8-01b92faffc19.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HU0Ok68O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120726060-474feb80-c4a5-11eb-8cb8-01b92faffc19.png" alt="taskade blank project"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Using a template.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can use templates &lt;a href="https://www.taskade.com/templates"&gt;created by Taskade&lt;/a&gt; or you can create your own. A template is just a pre-configurations of a use-case you would see in personal and professional environments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mKGAsb8C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120726064-48811880-c4a5-11eb-825e-0694fe1c5bf9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mKGAsb8C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120726064-48811880-c4a5-11eb-825e-0694fe1c5bf9.png" alt="taskade templates"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Import from Trello.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Taskade gives you the option of importing your Trello projects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JKoGqoxw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120726065-4919af00-c4a5-11eb-957c-e2a9b7bd2854.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JKoGqoxw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120726065-4919af00-c4a5-11eb-957c-e2a9b7bd2854.png" alt="taskade from trello"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From here we can name the project and &lt;strong&gt;attach some properties&lt;/strong&gt;. We can add due dates, assign different team members to the project, or tag the project to help with filtering when searching.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QEPGn87I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120726300-bd545280-c4a5-11eb-98a6-e55881e1b55b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QEPGn87I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120726300-bd545280-c4a5-11eb-98a6-e55881e1b55b.png" alt="project properties"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Block
&lt;/h4&gt;

&lt;p&gt;From a project, we can get straight into adding tasks, but blocks are the best way to organize.&lt;/p&gt;

&lt;p&gt;There are different &lt;em&gt;types&lt;/em&gt; of blocks. "Types" refers to the category of tasks within the block.&lt;br&gt;
There are checklists, bullet lists, numbered lists, and simple paragraph options.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We can also attach properties to our blocks&lt;/em&gt;; just the like our projects, due dates and assignments but with two additions: the ability to leave comments and attach files.&lt;/p&gt;
&lt;h4&gt;
  
  
  Task
&lt;/h4&gt;

&lt;p&gt;Finally to a block we add tasks. Tasks act just like any list you would code in HTML, write in a markdown file or use in your word processor.&lt;/p&gt;

&lt;p&gt;Like a block you can add due dates, assignments, comments, and files.&lt;/p&gt;

&lt;p&gt;Now that we know how to &lt;strong&gt;ORGANIZE&lt;/strong&gt; our ideas into a project, let's take a look at how we can &lt;strong&gt;VISUALIZE&lt;/strong&gt; those ideas.&lt;/p&gt;
&lt;h4&gt;
  
  
  Taskade offers 5 different layouts.
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;1. List&lt;/strong&gt; - this is our default view; a simple line-by-line presentation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ivx6wq5o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120726702-b548e280-c4a6-11eb-87c8-b32a3faff06a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ivx6wq5o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120726702-b548e280-c4a6-11eb-87c8-b32a3faff06a.png" alt="taskade list view"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Board&lt;/strong&gt; - if you're familiar with Trello boards, this is the same thing; we have these cards that we can horizontally scroll on as well as drag to reorganize.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CnG--G82--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120726704-b5e17900-c4a6-11eb-9d04-751a2b412787.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CnG--G82--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120726704-b5e17900-c4a6-11eb-9d04-751a2b412787.png" alt="taskade board view"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Action&lt;/strong&gt; - think of this like a more functional version of the list view; all of the attachment properties are one click away.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EoGeYShn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120726707-b67a0f80-c4a6-11eb-8362-c6f8f6ebaff1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EoGeYShn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120726707-b67a0f80-c4a6-11eb-8362-c6f8f6ebaff1.png" alt="taskade action view"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next two are pretty interesting. I don't personally use these on my laptop (screen too small), but they would be perfect for a multi-monitor setups, a large tv, or projector--maybe for meetings at an office. These two layouts give a great birds-eye view of your project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Mindmap&lt;/strong&gt; - this is like a horizontal tree where everything cascades from left-to-right; all of the functionality is still there: adding blocks, tasks, attaching properties, collapsing sections...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XjiFPfOB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120726708-b712a600-c4a6-11eb-8e1c-a7609c9b49da.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XjiFPfOB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120726708-b712a600-c4a6-11eb-8e1c-a7609c9b49da.png" alt="taskade mindmap view"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Org Chart&lt;/strong&gt; - this is a vertical tree; again, same functionality just a different way of conceptualizing the entire project&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Cqq7jvgX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120726710-b7ab3c80-c4a6-11eb-8a00-bd850d7d2fd7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Cqq7jvgX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120726710-b7ab3c80-c4a6-11eb-8a00-bd850d7d2fd7.png" alt="taskade orgchart view"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We now know how to &lt;strong&gt;ORGANIZE&lt;/strong&gt; and &lt;strong&gt;VISUALIZE&lt;/strong&gt; our work-flow.&lt;/p&gt;

&lt;p&gt;How do we &lt;strong&gt;KEEP TRACK&lt;/strong&gt; of our work-flow?&lt;/p&gt;

&lt;p&gt;Let's talk deadlines.&lt;/p&gt;


&lt;h3&gt;
  
  
  Keeping track of progress.
&lt;/h3&gt;

&lt;p&gt;When we add a '&lt;strong&gt;due date&lt;/strong&gt;' to a project it gets tracked in two places:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The 'Roadmap' tab&lt;/li&gt;
&lt;li&gt;The 'Calendar' tab&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_dKrJUXf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120779744-61191f00-c4f5-11eb-9281-bd7d9951d394.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_dKrJUXf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120779744-61191f00-c4f5-11eb-9281-bd7d9951d394.png" alt="taskade cal and road"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we add a '&lt;strong&gt;due date&lt;/strong&gt;' or '&lt;strong&gt;assignment&lt;/strong&gt;' to a block or task it gets tracked in 3 places:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The 'My Tasks'/'Tasks' tab&lt;/li&gt;
&lt;li&gt;The 'Roadmap' tab&lt;/li&gt;
&lt;li&gt;The 'Calendar' tab&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qo1SFCwk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120779749-624a4c00-c4f5-11eb-9ddd-f807c2059222.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qo1SFCwk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/83028597/120779749-624a4c00-c4f5-11eb-9ddd-f807c2059222.png" alt="taskade tasks"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Personally I prefer the 'Task' or 'Calendar', the 'Roadmap' is too much scrolling--it feels claustrophobic.&lt;/p&gt;

&lt;p&gt;Now, managing the information in multiple projects can be a lot of work so Taskade has a notification system that alerts you of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;when tasks are due&lt;/li&gt;
&lt;li&gt;when comments have been added&lt;/li&gt;
&lt;li&gt;when attachments have been added&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;basically just monitoring your workspaces for you. These notifications also push to your desktop, mobile, and email if you choose.&lt;/p&gt;

&lt;p&gt;They also have a 'Recent'/'History' tab that keeps track of blocks &amp;amp; tasks you've added, deleted, edited, or completed.&lt;/p&gt;

&lt;p&gt;For those of you who use &lt;strong&gt;Google&lt;/strong&gt; or &lt;strong&gt;Yahoo&lt;/strong&gt; calendar they allow you to sync your blocks and tasks with those two services.&lt;/p&gt;

&lt;p&gt;Now that we know how to &lt;strong&gt;KEEP TRACK&lt;/strong&gt; of our work-flow. Let's move on to &lt;strong&gt;COORDINATING&lt;/strong&gt; that work-flow between team members.&lt;/p&gt;


&lt;h3&gt;
  
  
  Including others.
&lt;/h3&gt;

&lt;p&gt;To communicate with team members, we have to first add them.&lt;/p&gt;

&lt;p&gt;Taskade offers three different ways: email, Taskade username, or link.&lt;/p&gt;

&lt;p&gt;There are 2 levels of permissions:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;editor&lt;/strong&gt;: the user can edit the project, but not manage it&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;viewer&lt;/strong&gt;: the user can comment and chat within the project, but not edit the project&lt;/p&gt;

&lt;p&gt;Once your team members are added you can communicate with them in a couple of ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;if you or they add a comment to a block or task it'll show up in that same window and in your notifications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--scuwPpY0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/83028597/120727817-7ff1c400-c4a9-11eb-84f8-b1935a1d0098.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--scuwPpY0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/83028597/120727817-7ff1c400-c4a9-11eb-84f8-b1935a1d0098.gif" alt="taskade comment string"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;if you use the 'Chat' panel (they make it very easy)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fESHG58X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/83028597/120727812-7e280080-c4a9-11eb-807d-b2f1234ec983.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fESHG58X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/83028597/120727812-7e280080-c4a9-11eb-807d-b2f1234ec983.gif" alt="taskade chat panel"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the 'Chat' panel you can text message as well as attach files.&lt;/p&gt;

&lt;p&gt;One thing they don't have--which I wish they did--is a system for global chatting. Currently, you can only chat with team members from within a project scope. You can't access the 'Chat' panel from your 'Dashboard'/'Homepage'.&lt;/p&gt;

&lt;p&gt;A major feature of Taskade that threads the needle between simplicity vs. complexity is video conferencing/screen sharing.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is so important for holding onto that "face-to-face" communication in the age of remote work.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No complicated panels and tabs, just one-click away.&lt;/p&gt;


&lt;h3&gt;
  
  
  Platform and Pricing.
&lt;/h3&gt;

&lt;p&gt;You can use Taskade on just about any platform you can think of.&lt;/p&gt;

&lt;p&gt;Desktop--Windows, Mac, Linux; Mobile--Android &amp;amp; Apple; and they even have a browser extension for Chrome, Firefox, and Edge.&lt;/p&gt;

&lt;p&gt;A few limitations I found on their mobile platform is that you can't re-organize your projects into different views--so you just &lt;br&gt;
have the list view--and you can't sync your blocks and tasks with your Google or Yahoo calendar. Other than that, your workspace activities sync across all platforms.&lt;/p&gt;

&lt;p&gt;As for pricing, Taskade offers 2 options: Free and Unlimited.&lt;/p&gt;

&lt;p&gt;Unlimited basically ups capacity for all features--more tasks, larger file sizes, more storage...&lt;/p&gt;

&lt;p&gt;You can take a look at their Free vs. Unlimited &lt;a href="https://www.taskade.com/features"&gt;comparison chart&lt;/a&gt; for a full breakdown.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you want a free upgrade to Taskade Unlimited, about 500 of you are going to be lucky!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;(be one of the first 500)&lt;/p&gt;

&lt;p&gt;Step 1: Install &lt;a href="https://www.taskade.com/downloads"&gt;Taskade Free plan&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Step 2: &lt;a href="https://www.taskade.com/contact"&gt;Contact Taskade&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Step 3: Mention me: "&lt;strong&gt;An Object Is A&lt;/strong&gt;" in your message.&lt;/p&gt;

&lt;p&gt;Step 4: Profit.&lt;/p&gt;


&lt;h3&gt;
  
  
  Final impressions.
&lt;/h3&gt;

&lt;p&gt;So what are my thoughts about Taskade?&lt;/p&gt;

&lt;p&gt;I'm not going to name any other project management platforms (other than Trello earlier), but of the ones I've tried Taskade is a great middle ground. Some of the other platforms were too simple or too complicated--too many panels, little widgets, etc.&lt;/p&gt;

&lt;p&gt;Taskade offers something that's simple to setup and integrate into any work-flow, but also has features that allow you to work efficiently--notification systems and video conferencing.&lt;/p&gt;

&lt;p&gt;You shouldn't have to fiddle around and spend unnecessary time getting your goals written down and communicated across team members. Taskade just let me hit the ground running so I can spend my time doing the actual work I'm getting paid for.&lt;/p&gt;

&lt;p&gt;You can check out Taskade over on their:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.taskade.com"&gt;Taskade Homepage&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/taskade"&gt;Twitter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.instagram.com/taskade"&gt;Instagram&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/taskade"&gt;Youtube Channel&lt;/a&gt;&lt;/p&gt;


&lt;h4&gt;
  
  
  &lt;center&gt;If you want a more in-depth guide, check out my full video tutorial on YouTube, &lt;strong&gt;&lt;a href="https://www.youtube.com/c/anobjectisa"&gt;An Object Is A&lt;/a&gt;&lt;/strong&gt;.&lt;/center&gt;
&lt;/h4&gt;

&lt;p&gt;Be sure to follow us on &lt;a href="https://www.instagram.com/an_object_is_a/"&gt;Instagram&lt;/a&gt; and &lt;a href="https://twitter.com/anobjectisa1"&gt;Twitter&lt;/a&gt; to keep up with our latest Web Development tutorials.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;center&gt;How does Taskade work? How can it help you? | My Taskade Walk-through and Impressions&lt;/center&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/8BWQqFw-W9Q"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>management</category>
      <category>teamwork</category>
      <category>startup</category>
      <category>entrepreneurship</category>
    </item>
    <item>
      <title>How To Build A Chrome Extension NEW Manifest V3</title>
      <dc:creator>an-object-is-a</dc:creator>
      <pubDate>Fri, 21 May 2021 13:49:43 +0000</pubDate>
      <link>https://dev.to/anobjectisa/how-to-build-a-chrome-extension-new-manifest-v3-5edk</link>
      <guid>https://dev.to/anobjectisa/how-to-build-a-chrome-extension-new-manifest-v3-5edk</guid>
      <description>&lt;h3&gt;
  
  
  &lt;center&gt;How To Build A Chrome Extension NEW Manifest V3&lt;/center&gt;
&lt;/h3&gt;




&lt;p&gt;If you need an easy to follow along video tutorial, you can purchase &lt;strong&gt;How To Build a Chrome Extension Manifest V3&lt;/strong&gt; over on our &lt;a href="https://sso.teachable.com/secure/792262/checkout/3415208/complete-guide-to-chrome-extension-manifest-v3-development" rel="noopener noreferrer"&gt;Teachable&lt;/a&gt; platform.&lt;/p&gt;

&lt;p&gt;Use discount code: &lt;strong&gt;ANOBJ&lt;/strong&gt; for 20% off.&lt;/p&gt;

&lt;p&gt;You can get the source files &lt;a href="https://github.com/an-object-is-a/chrome-ext-mv3-how-to" rel="noopener noreferrer"&gt;here&lt;/a&gt; to follow along.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdzq7syyzhlbrzwh03lve.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdzq7syyzhlbrzwh03lve.png" alt="building chrome extension manifest version 3" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  There Are 5 Major Components to Building a Chrome Extension
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Let's go over them briefly, then in-depth.
&lt;/h4&gt;

&lt;h4&gt;
  
  
  1. The manifest file.
&lt;/h4&gt;

&lt;p&gt;This is the ledger of a chrome extension. It's a &lt;strong&gt;JSON&lt;/strong&gt; file that describes the behavior of a Chrome extension. You list things like: your extensions &lt;strong&gt;name&lt;/strong&gt;; a &lt;strong&gt;description&lt;/strong&gt;; which files or libraries you're including; and  &lt;strong&gt;permissions&lt;/strong&gt; your extension needs. We'll get into more detail later on.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. The background script.
&lt;/h4&gt;

&lt;p&gt;This is a JavaScript file. Think of it like the mainframe or hub of a Chrome extension.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  One way to think of Chrome extension development is like full-stack web development
&lt;/h3&gt;
&lt;/blockquote&gt;

&lt;p&gt;You have the &lt;em&gt;back-end that handles heavy programming logic&lt;/em&gt; and you have the &lt;em&gt;front-end that takes in user input&lt;/em&gt;--the clicking of buttons, entering of information, etc.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;background script&lt;/strong&gt; can act like a back-end environment.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. The popup page.
&lt;/h4&gt;

&lt;p&gt;This is an HTML page users see when they click on the extension icon in the menu bar.&lt;br&gt;
This is one of the ways users can interact with your extension--like a front-end.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg6iqfuvwibux4d0xj9o0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg6iqfuvwibux4d0xj9o0.png" alt="popup" width="800" height="595"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  4. The options page.
&lt;/h4&gt;

&lt;p&gt;This page is also an HTML page. The user sees this page when they right click on your extension icon and choose for the options. This is another way users can interact with your extension--also like a front-end.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frn35sxcep043k9jr2qoe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frn35sxcep043k9jr2qoe.png" alt="options" width="800" height="582"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  5. The foreground/content script.
&lt;/h4&gt;

&lt;p&gt;This file is a JavaScript script. It's a special case and is a bit more complicated than the other files. For now, think of it like any other JS script that you can attach to the website the user is viewing.&lt;/p&gt;
&lt;h4&gt;
  
  
  Now that we know the big 5, let's go in-depth one component at a time.
&lt;/h4&gt;


&lt;h3&gt;
  
  
  The manifest file.
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;manifest&lt;/strong&gt; file is a &lt;strong&gt;JSON&lt;/strong&gt; file. Here we list the name, description, icons, and manifest version--among other things--of our Chrome extension. For this tutorial, we're working with manifest version 3; think of it like the software version.&lt;/p&gt;

&lt;p&gt;In here we define where our &lt;strong&gt;background&lt;/strong&gt;, &lt;strong&gt;popup&lt;/strong&gt;, and &lt;strong&gt;options&lt;/strong&gt; components are located in our file directory. &lt;strong&gt;&lt;em&gt;Notice I didn't include the foreground location here.&lt;/em&gt;&lt;/strong&gt; There are two ways of including the &lt;strong&gt;foreground script&lt;/strong&gt; in a Chrome extension: through the &lt;strong&gt;manifest&lt;/strong&gt; (which we won't do in this tutorial) and programmatically (which we will do in this tutorial).&lt;/p&gt;

&lt;p&gt;Here is an example of the &lt;strong&gt;manifest&lt;/strong&gt; file we'll be using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "name": "Chrome Extension MV3",
    "description": "Learning all about Chrome Extensions Manifest Version 3!",
    "version": "0.1.0",
    "manifest_version": 3,
    "icons": {
        "16": "/images/icon-16x16.png",
        "32": "/images/icon-32x32.png",
        "48": "/images/icon-48x48.png",
        "128": "/images/icon-128x128.png"
    },
    "background": {
        "service_worker": "background.js"
    },
    "action": {
        "default_popup": "popup.html",
        "default_icon": {
            "16": "/images/icon-16x16.png",
            "32": "/images/icon-32x32.png",
            "48": "/images/icon-48x48.png",
            "128": "/images/icon-128x128.png"
        }
    },
    "options_page": "options.html",
    "permissions": [
        "storage",
        "activeTab",
        "scripting",
        "tabs"
    ],
    "host_permissions": [
        "https://www.google.com/*"
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A key function of the &lt;strong&gt;manifest&lt;/strong&gt; file is defining &lt;strong&gt;&lt;em&gt;what&lt;/em&gt;&lt;/strong&gt; our Chrome extension is capable of doing. This gets handled in the &lt;strong&gt;permissions&lt;/strong&gt; properties.&lt;/p&gt;

&lt;p&gt;These permissions are APIs that let us do things like store data locally; if your Chrome extension wants to read which urls the user is looking at; and &lt;strong&gt;host&lt;/strong&gt; permissions which tell the browser which urls your Chrome extension is allowed to interact with.&lt;/p&gt;




&lt;h3&gt;
  
  
  The background script.
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;background script&lt;/strong&gt; is a regular JavaScript script with a &lt;strong&gt;very large caveat&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  the background script is a JavaScript service worker
&lt;/h3&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you don't know what a &lt;strong&gt;service worker&lt;/strong&gt; is, we did a tutorial on the basics of &lt;strong&gt;service workers&lt;/strong&gt;. You can find our video tutorial &lt;a href="https://youtu.be/wdvsbpKv5fI" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;All &lt;strong&gt;service workers&lt;/strong&gt; go through a lifecycle. The first part of that cycle is the &lt;strong&gt;&lt;em&gt;install&lt;/em&gt;&lt;/strong&gt; function. This is where we set up the default state of our Chrome extension.&lt;/p&gt;

&lt;p&gt;Think of it like this: When you first install a video game(let's say Call of Duty: Warzone) and you navigate to the key bindings, there are default bindings for all the inputs.&lt;/p&gt;

&lt;p&gt;This is the same with your Chrome Extension. When the user first installs your Chrome extension, what are the default properties? We handle this in an &lt;strong&gt;onInstalled&lt;/strong&gt; listener and just like installing a game--assuming you don't reinstall--that installation only happens once, not every time you boot the game up.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chrome.runtime.onInstalled.addListener(() =&amp;gt; {
    // default state goes here
    // this runs ONE TIME ONLY (unless the user reinstalls your extension)
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And remember, because the &lt;strong&gt;background&lt;/strong&gt; is a &lt;strong&gt;service worker&lt;/strong&gt;, it's not persistent. So if we want to save any sort of state, we need to store that state somewhere--locally, remotely...doesn't matter.&lt;/p&gt;

&lt;p&gt;We can work with temporary variables in the script like any other JavaScript environment...&lt;br&gt;
&lt;/p&gt;

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

name = "John";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;...but once the browser has determined that the user or you have stopped interacting with the &lt;strong&gt;background script&lt;/strong&gt; for a certain amount of time, the background environment will &lt;strong&gt;de-activate&lt;/strong&gt; until it's needed again.&lt;/p&gt;

&lt;p&gt;So if you want to work with any data past &lt;strong&gt;de-activation&lt;/strong&gt; you need to store it. We'll store it locally using the &lt;strong&gt;storage&lt;/strong&gt; API from our &lt;strong&gt;manifest&lt;/strong&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// setting state
chrome.storage.local.set({
    name: "Jack"
}, function ());

// getting state
chrome.storage.local.get("name", function (retrieved_data));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  The popup page.
&lt;/h3&gt;

&lt;p&gt;There's not much to be said here. The &lt;strong&gt;popup&lt;/strong&gt; page behaves exactly like any &lt;strong&gt;index.html&lt;/strong&gt; page with &lt;strong&gt;&lt;em&gt;one major difference&lt;/em&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  You cannot write in-line JavaScript in this file; only attach a script. You can however write in-line CSS styles (or choose to attach a stylesheet)
&lt;/h3&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  The options page.
&lt;/h3&gt;

&lt;p&gt;There's not much to be said here either. The &lt;strong&gt;options&lt;/strong&gt; behaves exactly like any &lt;strong&gt;index.html&lt;/strong&gt; page with &lt;strong&gt;&lt;em&gt;the same caveat&lt;/em&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  You cannot write in-line JavaScript in this file; only attach a script. You can however write in-line CSS styles (or choose to attach a stylesheet)
&lt;/h3&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  The foreground/content script.
&lt;/h3&gt;

&lt;p&gt;Now the most complicated component: the &lt;strong&gt;foreground&lt;/strong&gt; or &lt;strong&gt;content&lt;/strong&gt; script.&lt;/p&gt;

&lt;p&gt;It's called a &lt;strong&gt;foreground&lt;/strong&gt;(my wording) or &lt;strong&gt;content&lt;/strong&gt;(Google Docs' wording) &lt;strong&gt;script&lt;/strong&gt; because it gets embedded into the tab(s) the user is viewing. Think of it like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  We can monitor all of the tabs the user is viewing. When they go to a site of our choosing, we can inject our foreground script INTO THAT SITE giving us the ability to control the DOM of that site
&lt;/h3&gt;
&lt;/blockquote&gt;

&lt;p&gt;It behaves exactly like a JavaScript script--no surprises here--but incorporating it into our Chrome extension takes some work.&lt;/p&gt;

&lt;p&gt;To get our &lt;strong&gt;foreground script&lt;/strong&gt; to actually embed into the users tab(s) we need to first monitor their browsing experience with the &lt;strong&gt;tabs&lt;/strong&gt; API. We do this monitoring in the &lt;strong&gt;backround script&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) =&amp;gt; {
    if (changeInfo.status === 'complete' &amp;amp;&amp;amp; /^http/.test(tab.url)) {
    }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Notice the 'if' clause. If the web page the user is viewing is fully loaded(complete) AND it's an actual web page(http), then we do something.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now that we know the user is on a web page--fully loaded--we can inject our &lt;strong&gt;foreground script&lt;/strong&gt; using the &lt;strong&gt;scripting&lt;/strong&gt; API. Also in the &lt;strong&gt;background script&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) =&amp;gt; {
    if (changeInfo.status === 'complete' &amp;amp;&amp;amp; /^http/.test(tab.url)) {
        chrome.scripting.executeScript({
            target: { tabId: tabId },
            files: ["./foreground.js"]
        })
            .then(() =&amp;gt; {
                console.log("INJECTED THE FOREGROUND SCRIPT.");
            })
            .catch(err =&amp;gt; console.log(err));
    }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use the &lt;strong&gt;executeScript&lt;/strong&gt; method and pass in the &lt;strong&gt;target (tabId number)&lt;/strong&gt; and &lt;strong&gt;file (location of foreground script)&lt;/strong&gt; as arguments.&lt;br&gt;
You can also inject &lt;strong&gt;CSS&lt;/strong&gt; into a user's tab using the &lt;strong&gt;insertCSS&lt;/strong&gt; method of the &lt;strong&gt;scripting&lt;/strong&gt; API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) =&amp;gt; {
    if (changeInfo.status === 'complete' &amp;amp;&amp;amp; /^http/.test(tab.url)) {
        chrome.scripting.insertCSS({
            target: { tabId: tabId },
            files: ["./foreground_styles.css"]
        })
            .then(() =&amp;gt; {
                console.log("INJECTED THE FOREGROUND STYLES.");
            })
            .catch(err =&amp;gt; console.log(err));
    }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So now that we have our &lt;strong&gt;foreground script&lt;/strong&gt; injected into the user's tab, what can we do?&lt;/p&gt;

&lt;p&gt;Anything we want.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;document.querySelector("body &amp;gt; div.L3eUgb &amp;gt; div.o3j99.LLD4me.yr19Zb.LS8OJ &amp;gt; div &amp;gt; img").style.transitionDuration = '3.0s';
document.querySelector("body &amp;gt; div.L3eUgb &amp;gt; div.o3j99.LLD4me.yr19Zb.LS8OJ &amp;gt; div &amp;gt; img").style.transform = 'rotate(3000deg)';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This bit of code takes the Google logo--using the DOM--and spins it.&lt;/p&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const ce_main_container = document.createElement('DIV');
const ce_name = document.createElement('DIV');
const ce_input = document.createElement('INPUT');

...
...

ce_button.addEventListener('click', () =&amp;gt; {
    chrome.runtime.sendMessage({ 
        message: "change_name",
        payload: ce_input.value
    }, response =&amp;gt; {
        if (response.message === 'success') {
            ce_name.innerHTML = `Hello ${ce_input.value}`;
        }
    });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This bit of code puts a "form" on Google's homepage and allows the user to enter a name that gets saved in our Chrome extension.  (All of the code isn't posted, it's a bit long)&lt;/p&gt;

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

&lt;h3&gt;
  
  
  So like any script in any html page, we can manipulate the DOM AND insert our own HTML code.
&lt;/h3&gt;




&lt;h3&gt;
  
  
  Let's talk communication.
&lt;/h3&gt;

&lt;p&gt;There are two primary ways of sending message back and forth in a Chrome extension.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. chrome.runtime.sendMessage()
&lt;/h4&gt;

&lt;p&gt;When we want to send a message &lt;em&gt;from&lt;/em&gt; the &lt;strong&gt;background&lt;/strong&gt;, &lt;strong&gt;options&lt;/strong&gt;, &lt;strong&gt;popup&lt;/strong&gt;, or &lt;strong&gt;foreground&lt;/strong&gt; components to the &lt;strong&gt;background&lt;/strong&gt;, &lt;strong&gt;options&lt;/strong&gt;, or &lt;strong&gt;popup&lt;/strong&gt; components we use the &lt;strong&gt;&lt;em&gt;RUNTIME&lt;/em&gt;&lt;/strong&gt; version of &lt;strong&gt;sendMessage()&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chrome.runtime.sendMessage("message", function (response));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method take two arguments: the message you want to send and a callback to deal with a response message.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. chrome.tabs.sendMessage()
&lt;/h4&gt;

&lt;p&gt;When we want to send a message &lt;em&gt;from&lt;/em&gt; the &lt;strong&gt;background&lt;/strong&gt;, &lt;strong&gt;options&lt;/strong&gt;, or &lt;strong&gt;popup&lt;/strong&gt; components to the &lt;strong&gt;foreground&lt;/strong&gt; component we use the &lt;strong&gt;&lt;em&gt;TABS&lt;/em&gt;&lt;/strong&gt; version of &lt;strong&gt;sendMessage()&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chrome.tabs.sendMessage(tabId, "message", function (response));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method takes three arguments: the id of the tab you want to send a message to; the message; and a callback to deal with a response message.&lt;/p&gt;

&lt;h4&gt;
  
  
  So we know how to send a message, how do we receive the message?
&lt;/h4&gt;

&lt;p&gt;One way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
    // communication tree
    // if (request === 'get_name') {
    //   return "Jack";
    // }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;onMessage&lt;/strong&gt; method takes a callback which gives you 3 parameters:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;request&lt;/strong&gt; - the message being sent&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;sender&lt;/strong&gt; - whose sending the message&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;sendResponse&lt;/strong&gt; - a method that allows you send to send a message back to the original sender&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A real-life example of a communication tree might be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chrome.runtime.onMessage.addListener((request, sender, sendResponse) =&amp;gt; {
    if (request.message === 'get_name') {
        sendResponse("Jack");
    } else if (request.message === 'change_name') {
        chrome.storage.local.set({
            name: request.payload
        }, () =&amp;gt; {
            if (chrome.runtime.lastError) {
                sendResponse({ message: 'fail' });
                return;
            }

            sendResponse({ message: 'success' });
        })

        return true;
    }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In here we have two branches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;'get_name'&lt;/strong&gt; which just sends a response of (string) "Jack"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;'change_name'&lt;/strong&gt; which first saves the name sent by the sender, then sends a response of (object) { message: 'success' }.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  Using these three methods: runtime.sendMessage, tabs.sendMessage, and onMessage.addListener you have all the workings of a full-stack application
&lt;/h3&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can now communicate between "front-end" and "back-end" components. For example, when your user presses a button in your &lt;strong&gt;popup&lt;/strong&gt; page you can send a message to the &lt;strong&gt;background script&lt;/strong&gt; asking to fetch an image and send the image data as a response.&lt;/p&gt;




&lt;h3&gt;
  
  
  There is much, much more you can do with Chrome Extensions.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  But this is a great foundation for you to build from.
&lt;/h4&gt;

&lt;p&gt;You can view our video tutorial down below for more detailed information.&lt;/p&gt;

&lt;p&gt;You can get the source files &lt;a href="https://github.com/an-object-is-a/chrome-ext-mv3-how-to" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Be sure to follow us on &lt;a href="https://www.instagram.com/an_object_is_a/" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt; and &lt;a href="https://twitter.com/anobjectisa1" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; to keep up with our latest Web Development tutorials.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to Dynamically Load Markdown Files in React (markdown-to-jsx)</title>
      <dc:creator>an-object-is-a</dc:creator>
      <pubDate>Fri, 07 May 2021 14:28:10 +0000</pubDate>
      <link>https://dev.to/anobjectisa/how-to-dynamically-load-markdown-files-in-react-markdown-to-jsx-53fl</link>
      <guid>https://dev.to/anobjectisa/how-to-dynamically-load-markdown-files-in-react-markdown-to-jsx-53fl</guid>
      <description>&lt;h3&gt;
  
  
  &lt;center&gt;How to Dynamically Load Markdown Files in React (markdown-to-jsx)&lt;/center&gt;
&lt;/h3&gt;




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

&lt;h3&gt;
  
  
  I was fussing about how to display copy in one of my React components.
&lt;/h3&gt;

&lt;p&gt;Instead of dealing with HTML &lt;strong&gt;divs&lt;/strong&gt;, &lt;strong&gt;paragraphs&lt;/strong&gt;, &lt;strong&gt;images&lt;/strong&gt;, &lt;strong&gt;tables&lt;/strong&gt;, etc.&lt;/p&gt;

&lt;p&gt;I found a way to just import the &lt;strong&gt;.md&lt;/strong&gt; (&lt;strong&gt;&lt;em&gt;markdown&lt;/em&gt;&lt;/strong&gt;) files I already have.&lt;/p&gt;

&lt;p&gt;This process involves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/markdown-to-jsx" rel="noopener noreferrer"&gt;markdown-to-jsx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;light knowledge of React state management &amp;amp; life-cycles; we'll use &lt;strong&gt;hooks&lt;/strong&gt; here&lt;/li&gt;
&lt;li&gt;light knowledge of the JavaScript &lt;strong&gt;Fetch API&lt;/strong&gt; (very light knowledge, don't worry)&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  The first thing we'll need is to organize the markdown files.
&lt;/h3&gt;

&lt;p&gt;I've chosen to store the &lt;strong&gt;.md&lt;/strong&gt; files in a &lt;strong&gt;&lt;em&gt;markdown&lt;/em&gt;&lt;/strong&gt; folder in the &lt;strong&gt;src&lt;/strong&gt; directory.&lt;/p&gt;



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






&lt;h3&gt;
  
  
  Here is the code that brings everything together.
&lt;/h3&gt;

&lt;p&gt;Here is the code I'll be explaining:&lt;br&gt;
&lt;/p&gt;

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

import React, { useState, useEffect } from 'react';

import Markdown from 'markdown-to-jsx';

import './styles/main_styles.css';

function App() {
    const file_name = 'react_pinterest_clone.md';
    const [post, setPost] = useState('');

    useEffect(() =&amp;gt; {
        import(`./markdown/${file_name}`)
            .then(res =&amp;gt; {
                fetch(res.default)
                    .then(res =&amp;gt; res.text())
                    .then(res =&amp;gt; setPost(res))
                    .catch(err =&amp;gt; console.log(err));
            })
            .catch(err =&amp;gt; console.log(err));
    });

    return (
        &amp;lt;div className="container"&amp;gt;
            &amp;lt;Markdown&amp;gt;
                {post}
            &amp;lt;/Markdown&amp;gt;
        &amp;lt;/div&amp;gt;
    );
}

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  There are 3 key things happening here:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Import the &lt;strong&gt;markdown-to-jsx&lt;/strong&gt; package.&lt;/li&gt;
&lt;li&gt;Setup the state.&lt;/li&gt;
&lt;li&gt;Fetch and display the markdown.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;&lt;strong&gt;Firstly&lt;/strong&gt;, we need to of course import the &lt;strong&gt;markdown-to-jsx&lt;/strong&gt; package.&lt;/p&gt;

&lt;p&gt;We use it in our return block.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Secondly&lt;/strong&gt;, we set up the state we'll use to hold the &lt;strong&gt;.md&lt;/strong&gt; data. Initially, we set the variable &lt;strong&gt;post&lt;/strong&gt; to a &lt;strong&gt;&lt;em&gt;blank string&lt;/em&gt;&lt;/strong&gt; and place it in between the &lt;strong&gt;Markdown&lt;/strong&gt; tags.&lt;/p&gt;

&lt;p&gt;We also have a &lt;strong&gt;file_name&lt;/strong&gt; to act as a way of dynamically choosing the markdown file we want. In this case&lt;br&gt;
I hard-coded it, but you can set it to whatever you want based on some logic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thirdly&lt;/strong&gt;, once our component loads, &lt;strong&gt;useEffect()&lt;/strong&gt;, we use the &lt;strong&gt;import&lt;/strong&gt; as a function.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;import&lt;/strong&gt; used this way acts as a &lt;strong&gt;&lt;em&gt;promise&lt;/em&gt;&lt;/strong&gt; and returns the absolute path to our markdown file.&lt;/p&gt;

&lt;p&gt;We then fetch the &lt;strong&gt;markdown&lt;/strong&gt; file we want using the &lt;strong&gt;Fetch API&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Once we fetch the file, we need to parse the response as a &lt;strong&gt;text&lt;/strong&gt; file, and then store the parsed response in our &lt;strong&gt;post&lt;/strong&gt; state variable.&lt;/p&gt;


&lt;h3&gt;
  
  
  It's as simple as that.
&lt;/h3&gt;

&lt;p&gt;You can get the source files &lt;a href="https://github.com/an-object-is-a/reactjs-markdown-dynamic-file" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;


&lt;h4&gt;
  
  
  &lt;center&gt;If you want a more in-depth guide, check out my full video tutorial on YouTube, &lt;strong&gt;&lt;a href="https://www.youtube.com/c/anobjectisa" rel="noopener noreferrer"&gt;An Object Is A&lt;/a&gt;&lt;/strong&gt;.&lt;/center&gt;
&lt;/h4&gt;
&lt;h4&gt;
  
  
  &lt;center&gt;Be sure to follow us on &lt;a href="https://www.instagram.com/an_object_is_a/" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt; and &lt;a href="https://twitter.com/anobjectisa1" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; to keep up with our latest Web Development tutorials.&lt;/center&gt;
&lt;/h4&gt;
&lt;h3&gt;
  
  
  &lt;center&gt;Dynamically Load Markdown files into React for your Blog | markdown-to-jsx&lt;/center&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/qdTisPssu24"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>markdown</category>
    </item>
    <item>
      <title>Create a React Blog Site | Beginner Project for Jr. Devs</title>
      <dc:creator>an-object-is-a</dc:creator>
      <pubDate>Fri, 23 Apr 2021 13:46:44 +0000</pubDate>
      <link>https://dev.to/anobjectisa/create-a-react-blog-site-beginner-project-for-jr-devs-3h1d</link>
      <guid>https://dev.to/anobjectisa/create-a-react-blog-site-beginner-project-for-jr-devs-3h1d</guid>
      <description>&lt;h3&gt;
  
  
  &lt;center&gt;Create a React Blog Site | Beginner Project for Jr. Devs&lt;/center&gt;
&lt;/h3&gt;




&lt;h4&gt;
  
  
  &lt;center&gt;Browse our &lt;a href="http://anobject.teachable.com" rel="noopener noreferrer"&gt;Teachable&lt;/a&gt; courses.&lt;/center&gt;
&lt;/h4&gt;




&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F115167966-64f8fb00-a087-11eb-90ed-c33a948b551d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F115167966-64f8fb00-a087-11eb-90ed-c33a948b551d.png" alt="Create a React Blog Page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  We'll build this webpage out of 6 components.
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;BlogPage.js&lt;/strong&gt; - the main container for our posts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Post.js&lt;/strong&gt; - a single blog post&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WriteUp.js&lt;/strong&gt; - a place to show your copy-write&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gallery.js&lt;/strong&gt; - an image gallery&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PrimaryAsset.js&lt;/strong&gt; - a place to show a large print image or embed a video&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separator.js&lt;/strong&gt; - a simple design to separate each blog post&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All of the information displayed in a blog post will be seeded in through a &lt;strong&gt;feeder file&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This file will have the following schema:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
    {
        title: ``,
        subtitle: ``,
        images: [``],
        primary_asset: ``,
        copywrite: [``, ``]
    },
    {
        title: ``,
        subtitle: ``,
        images: [ ],
        primary_asset: ``,
        copywrite: [ ]
    }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;Each blog post will have a &lt;strong&gt;title&lt;/strong&gt;, &lt;strong&gt;subtitle&lt;/strong&gt;, an &lt;strong&gt;array of images&lt;/strong&gt; for our gallery, an &lt;strong&gt;HTML string&lt;/strong&gt; for a &lt;strong&gt;main/primary asset&lt;/strong&gt;, and an &lt;strong&gt;array of 2 HTML strings&lt;/strong&gt; for the &lt;strong&gt;copy-write&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  BlogPage.js
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Our container for our blog posts.
&lt;/h4&gt;

&lt;p&gt;Our main component, the &lt;strong&gt;BlogPage&lt;/strong&gt; will be broken up into 4 sections.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A site header.&lt;/li&gt;
&lt;li&gt;A page name.&lt;/li&gt;
&lt;li&gt;Left side for blog posts.&lt;/li&gt;
&lt;li&gt;Right side for an index/table of contents.&lt;/li&gt;
&lt;/ol&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className="blog_page"&amp;gt;
    &amp;lt;div className="site_header"&amp;gt;

    &amp;lt;/div&amp;gt;

    &amp;lt;div className="page_name"&amp;gt;
    &amp;lt;/div&amp;gt;

    &amp;lt;div className="container"&amp;gt;
        &amp;lt;div className="left_side"&amp;gt;
            &amp;lt;div className="blog_posts"&amp;gt;

            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div className="right_side"&amp;gt;
            &amp;lt;div className="blog_index"&amp;gt;

            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F115173845-2159bd80-a096-11eb-8613-79ca89510050.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F115173845-2159bd80-a096-11eb-8613-79ca89510050.png" alt="blogpage"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Post.js
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Each post we make is contained within this component.
&lt;/h4&gt;

&lt;p&gt;In here, we can design any type of post we want.&lt;/p&gt;

&lt;p&gt;For this tutorial, we'll have &lt;strong&gt;five sections&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Sections for...&lt;/p&gt;

&lt;p&gt;the post title...&lt;/p&gt;

&lt;p&gt;some copywrite...&lt;/p&gt;

&lt;p&gt;an image gallery...&lt;/p&gt;

&lt;p&gt;some more copy-write...&lt;/p&gt;

&lt;p&gt;and finally a primary or main asset (video or large print image).&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className="blog_post"&amp;gt;
    &amp;lt;div className="section section1"&amp;gt;
        // TITLE
    &amp;lt;/div&amp;gt;

    &amp;lt;div className="section section2"&amp;gt;
        // COPYWRITE
    &amp;lt;/div&amp;gt;

    &amp;lt;div className="section section3"&amp;gt;
        // GALLERY
    &amp;lt;/div&amp;gt;

    &amp;lt;div className="section section4"&amp;gt;
        // COPYWRITE
    &amp;lt;/div&amp;gt;

    &amp;lt;div className="section section5"&amp;gt;
        // MAIN ASSET (VIDEO OR IMAGE)
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F115175435-f6bd3400-a098-11eb-803d-35c2b1d665ba.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F115175435-f6bd3400-a098-11eb-803d-35c2b1d665ba.png" alt="post"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  WriteUp.js
&lt;/h3&gt;

&lt;h4&gt;
  
  
  We're going to take a piece of copy-write and add two visual flairs.
&lt;/h4&gt;

&lt;p&gt;We need to find a way to hide part of the post.&lt;/p&gt;

&lt;p&gt;If the copy-write is 700 lines long, we don't want to show all 700 lines.&lt;/p&gt;

&lt;p&gt;We want to hide the copy-write up to a specified height and then give the user the option of showing the entire copy-write.&lt;/p&gt;

&lt;p&gt;To accomplish this, we'll initially load up the copy-write through the '&lt;strong&gt;dangerouslySetInnerHTML&lt;/strong&gt;' prop of our &lt;strong&gt;div&lt;/strong&gt; element.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div ref={CopyWriteRef} dangerouslySetInnerHTML={{__html: props.copywrite}}&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;Once the component loads, we'll check it's height. If the total height of our &lt;strong&gt;div&lt;/strong&gt; once rendered is greater than a certain threshold, we'll cut the height down to that threshold.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
    const copywrite = CopyWriteRef.current;

    if (copywrite.getBoundingClientRect().height &amp;gt; text_threshold) {
        copywrite.style.height = `${text_threshold}px`;
        copywrite.nextSibling.style.display = 'block';
        copywrite.nextSibling.nextSibling.style.display = 'block';
    }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;We also show a &lt;strong&gt;linear-gradient&lt;/strong&gt; at the bottom of the copy-write as well give the user a &lt;strong&gt;read more&lt;/strong&gt; button.&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F115480473-89381180-a218-11eb-8ca9-e51262fd8a7b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F115480473-89381180-a218-11eb-8ca9-e51262fd8a7b.png" alt="writeup"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Gallery.js
&lt;/h3&gt;

&lt;h4&gt;
  
  
  A simple CSS grid-styled DIV will create our image gallery.
&lt;/h4&gt;

&lt;p&gt;We'll define our gallery in &lt;strong&gt;1 row&lt;/strong&gt; by &lt;strong&gt;2 columns&lt;/strong&gt; for &lt;strong&gt;Desktop&lt;/strong&gt; and &lt;strong&gt;1 x 1&lt;/strong&gt; for &lt;strong&gt;Mobile&lt;/strong&gt;.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.post_image_gallery {
    width: fit-content;
    height: fit-content;
    max-height: calc((270px * 2) + 20px);
    display: grid;
    gap: 10px;

    grid-template-rows: 270px;
    grid-template-columns: repeat(2, 270px);
    grid-auto-rows: 270px;

    justify-content: center;
    overflow-x: hidden;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F115481006-a7524180-a219-11eb-9dc3-e34424e8079d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F115481006-a7524180-a219-11eb-9dc3-e34424e8079d.png" alt="gallery"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  PrimaryAsset.js
&lt;/h3&gt;

&lt;h4&gt;
  
  
  A simple DIV where we show an image or video (iframe embed).
&lt;/h4&gt;

&lt;p&gt;Just like the &lt;strong&gt;WriteUp.js&lt;/strong&gt; component, we'll insert our &lt;strong&gt;image&lt;/strong&gt; or &lt;strong&gt;iframe&lt;/strong&gt; embed in the '&lt;strong&gt;dangerouslySetInnerHTML&lt;/strong&gt;' prop of our &lt;strong&gt;DIV&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For this project, we'll use an &lt;strong&gt;iframe embed&lt;/strong&gt; from our &lt;strong&gt;feeder file&lt;/strong&gt;.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;primary_asset: `&amp;lt;iframe src="https://www.youtube.com/embed/cAC4s5GuUb8" \
title="YouTube video player" frameborder="0" allow="accelerometer; \
autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" \
allowfullscreen&amp;gt;&amp;lt;/iframe&amp;gt;`,
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div dangerouslySetInnerHTML={{__html: props.primary_asset}}&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F115482750-5cd2c400-a21d-11eb-9f28-8b7fd11883dd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F115482750-5cd2c400-a21d-11eb-9f28-8b7fd11883dd.png" alt="primaryasset"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Separator.js
&lt;/h3&gt;

&lt;h4&gt;
  
  
  The final component. Just a few lines to separate one post from another.
&lt;/h4&gt;

&lt;p&gt;We'll just place three &lt;strong&gt;square icons&lt;/strong&gt; from &lt;strong&gt;&lt;a href="https://fontawesome.com/icons/square-full?style=solid" rel="noopener noreferrer"&gt;Font Awesome&lt;/a&gt;&lt;/strong&gt; into a &lt;strong&gt;DIV&lt;/strong&gt; and space them apart.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className="separator"&amp;gt;
    &amp;lt;i className="fas fa-square-full"&amp;gt;&amp;lt;/i&amp;gt;
    &amp;lt;i className="fas fa-square-full"&amp;gt;&amp;lt;/i&amp;gt;
    &amp;lt;i className="fas fa-square-full"&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F115483770-6ceba300-a21f-11eb-9e65-7e12f3ff21a7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F115483770-6ceba300-a21f-11eb-9e65-7e12f3ff21a7.png" alt="separator"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  There is much more nuance to this project.
&lt;/h3&gt;

&lt;p&gt;You can view our video tutorial down below.&lt;/p&gt;

&lt;p&gt;You can get the source files &lt;a href="https://github.com/an-object-is-a/react-webpage-04" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;center&gt;If you want a more in-depth guide, check out my full video tutorial on YouTube, &lt;strong&gt;&lt;a href="https://www.youtube.com/c/anobjectisa" rel="noopener noreferrer"&gt;An Object Is A&lt;/a&gt;&lt;/strong&gt;.&lt;/center&gt;
&lt;/h4&gt;

&lt;h3&gt;
  
  
  &lt;center&gt;Create a React Blog Site | Beginner Project for Jr. Devs&lt;/center&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/1qZE0HUclfA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>portfolio</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Valorant-inspired React Website</title>
      <dc:creator>an-object-is-a</dc:creator>
      <pubDate>Fri, 09 Apr 2021 13:36:23 +0000</pubDate>
      <link>https://dev.to/anobjectisa/valorant-inspired-react-website-14cm</link>
      <guid>https://dev.to/anobjectisa/valorant-inspired-react-website-14cm</guid>
      <description>&lt;h3&gt;
  
  
  &lt;center&gt;React Valorant Website Tutorial&lt;/center&gt;
&lt;/h3&gt;




&lt;h4&gt;
  
  
  &lt;center&gt;Browse our &lt;a href="http://anobject.teachable.com" rel="noopener noreferrer"&gt;Teachable&lt;/a&gt; courses.&lt;/center&gt;
&lt;/h4&gt;




&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F113495749-6b04ae80-94c1-11eb-9e63-39bc6cd8576b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F113495749-6b04ae80-94c1-11eb-9e63-39bc6cd8576b.png" alt="valorant website splash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  We'll build this webpage in 5 main sections.
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Section 1&lt;/strong&gt; - our product logo and an image gallery&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Section 2&lt;/strong&gt; - information about our product&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Section 3&lt;/strong&gt; - accolades about our product&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Section 4&lt;/strong&gt; - opportunities to buy our product&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Section 5&lt;/strong&gt; - contact information for our business&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  We'll create a Home.js component to hold all of this code.
&lt;/h4&gt;




&lt;h3&gt;
  
  
  Section 1.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  All we're going to do here is create containers for our product logo &amp;amp; button, and image gallery.
&lt;/h4&gt;

&lt;p&gt;We'll deal with the details of the image gallery implementation later.&lt;/p&gt;

&lt;p&gt;For now we position our logo and button on the page and place our image gallery behind everything.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className="section1"&amp;gt;
    &amp;lt;div className="container"&amp;gt;
        &amp;lt;img src="./images/reyna.png" alt="" className="splash_img" /&amp;gt;
        &amp;lt;img src="./images/val-logo.png" alt="" className="splash_logo" /&amp;gt;
        &amp;lt;div className="sign_up"&amp;gt;
            &amp;lt;a href="https://localhost" target="_blank" rel="noreferrer"&amp;gt;Sign Up&amp;lt;/a&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;

    &amp;lt;div ref={galleryRef} className="gallery"&amp;gt;
        {
            loaded ?
                &amp;lt;Deck gallery={gallery} /&amp;gt; : null
        }
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is our result:&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108641781-296af780-746f-11eb-9880-4d47afe1e488.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108641781-296af780-746f-11eb-9880-4d47afe1e488.png" alt="section 1"&gt;&lt;/a&gt;&lt;/p&gt;






&lt;h3&gt;
  
  
  Section 2.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  For this section we'll create a container for a grid of items.
&lt;/h4&gt;

&lt;p&gt;Our grid will be 2x4 and centered in the screen.&lt;/p&gt;

&lt;p&gt;Each item of the grid will be a '&lt;strong&gt;Point&lt;/strong&gt;' component (a "point" about our product)&lt;/p&gt;

&lt;p&gt;Our '&lt;strong&gt;Point&lt;/strong&gt;' component will consist of an icon, name, and brief description.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function Point(props) {
    return (
        &amp;lt;div className="point"&amp;gt;
            &amp;lt;div className="point_icon"&amp;gt;
                &amp;lt;img src={props.img} alt=""/&amp;gt;
            &amp;lt;/div&amp;gt;
            &amp;lt;div className="point_title"&amp;gt;
                &amp;lt;div className="point_name"&amp;gt;In the Crosses&amp;lt;/div&amp;gt;
                &amp;lt;div className="point_description"&amp;gt;Rewards accuracy and skill&amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
    )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108641792-3687e680-746f-11eb-8985-5677127d4c4f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108641792-3687e680-746f-11eb-8985-5677127d4c4f.png" alt="point"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Our &lt;strong&gt;Section 2&lt;/strong&gt; code is very simple.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className="section2"&amp;gt;
    &amp;lt;div className="marketing_points"&amp;gt;
        &amp;lt;Point img="./images/icons/val-symbol.png" /&amp;gt;
        &amp;lt;Point img="./images/icons/bladestorm.png" /&amp;gt;
        &amp;lt;Point img="./images/icons/dimensional-drift.png" /&amp;gt;
        &amp;lt;Point img="./images/icons/empress.png" /&amp;gt;
        &amp;lt;Point img="./images/icons/shock-bolt.png" /&amp;gt;
        &amp;lt;Point img="./images/icons/turret.png" /&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is our result:&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108641793-3687e680-746f-11eb-92bb-8537a3d9eb23.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108641793-3687e680-746f-11eb-92bb-8537a3d9eb23.png" alt="section 2"&gt;&lt;/a&gt;&lt;/p&gt;






&lt;h3&gt;
  
  
  Section 3.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  A simple flexbox of items.
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className="section3"&amp;gt;
    &amp;lt;div className="accolades"&amp;gt;
        &amp;lt;div className="accolade"&amp;gt;
            &amp;lt;i className="fas fa-award"&amp;gt;&amp;lt;/i&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div className="accolade"&amp;gt;
            &amp;lt;i className="fas fa-flag"&amp;gt;&amp;lt;/i&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div className="accolade"&amp;gt;
            &amp;lt;i className="fas fa-gamepad"&amp;gt;&amp;lt;/i&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is our result:&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108641794-37207d00-746f-11eb-9341-ba471b50a731.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108641794-37207d00-746f-11eb-9341-ba471b50a731.png" alt="section 3"&gt;&lt;/a&gt;&lt;/p&gt;






&lt;h3&gt;
  
  
  Section 4.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  For this section we'll create a container for a flexbox of items.
&lt;/h4&gt;

&lt;p&gt;Each item of the flexbox will be a '&lt;strong&gt;Package&lt;/strong&gt;' component.&lt;/p&gt;

&lt;p&gt;Our '&lt;strong&gt;Package&lt;/strong&gt;' component will consist of background image, title, description, price, purchase button, and feature list.&lt;/p&gt;

&lt;p&gt;For now, we'll just use dummy information.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className="package" style={{ backgroundColor: props.color }}&amp;gt;
    &amp;lt;img src={props.image} alt="" className="package_image" /&amp;gt;

    &amp;lt;div className="package_information"&amp;gt;
        &amp;lt;div className="package_head"&amp;gt;
            &amp;lt;div className="package_name"&amp;gt;{props.name}&amp;lt;/div&amp;gt;
            &amp;lt;div className="package_description"&amp;gt;{props.description}&amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div className="package_body"&amp;gt;
            &amp;lt;div className="package_price"&amp;gt;{`$${props.price}`}&amp;lt;/div&amp;gt;
            &amp;lt;div className="package_purchase"&amp;gt;
                &amp;lt;a href="https://localhost" target="_blank" rel="noreferrer"&amp;gt;Select&amp;lt;/a&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div className="package_foot"&amp;gt;
            Includes all base features:
            &amp;lt;ul&amp;gt;
                &amp;lt;li&amp;gt;Feature 1&amp;lt;/li&amp;gt;
                &amp;lt;li&amp;gt;Feature 2&amp;lt;/li&amp;gt;
                &amp;lt;li&amp;gt;Feature 3&amp;lt;/li&amp;gt;
                &amp;lt;li&amp;gt;Feature 4&amp;lt;/li&amp;gt;
            &amp;lt;/ul&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108641791-3687e680-746f-11eb-8c48-4029e203bf4e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108641791-3687e680-746f-11eb-8c48-4029e203bf4e.png" alt="package"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Our &lt;strong&gt;Section 4&lt;/strong&gt; code is very simple.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className="section4"&amp;gt;
    &amp;lt;div className="packages_container"&amp;gt;
        &amp;lt;Package color="#2db634" img="./images/viper.png" /&amp;gt;
        &amp;lt;Package color="#fb6c32" img="./images/phoenix.png" /&amp;gt;
        &amp;lt;Package color="#3694f5" img="./images/jett.png" /&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is our result:&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108641795-37207d00-746f-11eb-9f63-4dee9e86ebb1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108641795-37207d00-746f-11eb-9f63-4dee9e86ebb1.png" alt="section 4"&gt;&lt;/a&gt;&lt;/p&gt;






&lt;h3&gt;
  
  
  Section 5.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  For this section we'll have a series of unordered lists.
&lt;/h4&gt;

&lt;p&gt;This is just basic contact information organized into lists positioned horizontally. Nothing special here.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className="section5"&amp;gt;
    &amp;lt;section className="contact_section" &amp;gt;
        &amp;lt;ul&amp;gt;
            &amp;lt;li&amp;gt;Affiliates&amp;lt;/li&amp;gt;
            &amp;lt;li&amp;gt;Careers&amp;lt;/li&amp;gt;
            &amp;lt;li&amp;gt;Privacy&amp;lt;/li&amp;gt;
        &amp;lt;/ul&amp;gt;
    &amp;lt;/section&amp;gt;
    &amp;lt;section className="contact_section" &amp;gt;
        &amp;lt;ul&amp;gt;
            &amp;lt;li&amp;gt;Telephone &amp;lt;i className="fas fa-phone-square-alt"&amp;gt;&amp;lt;/i&amp;gt; &amp;lt;/li&amp;gt;
            &amp;lt;li&amp;gt;Email &amp;lt;i className="fas fa-envelope-square"&amp;gt;&amp;lt;/i&amp;gt; &amp;lt;/li&amp;gt;
        &amp;lt;/ul&amp;gt;
    &amp;lt;/section&amp;gt;
    &amp;lt;section className="contact_section" &amp;gt;
        &amp;lt;ul&amp;gt;
            &amp;lt;li&amp;gt;Instagram &amp;lt;i className="fab fa-instagram-square"&amp;gt;&amp;lt;/i&amp;gt; &amp;lt;/li&amp;gt;
            &amp;lt;li&amp;gt;Twitter &amp;lt;i className="fab fa-twitter-square"&amp;gt;&amp;lt;/i&amp;gt; &amp;lt;/li&amp;gt;
            &amp;lt;li&amp;gt;Facebook &amp;lt;i className="fab fa-facebook-square"&amp;gt;&amp;lt;/i&amp;gt; &amp;lt;/li&amp;gt;
        &amp;lt;/ul&amp;gt;
    &amp;lt;/section&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is our result:&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108641796-37b91380-746f-11eb-8245-ca2fc13d4dba.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108641796-37b91380-746f-11eb-8245-ca2fc13d4dba.png" alt="section 5"&gt;&lt;/a&gt;&lt;/p&gt;






&lt;h3&gt;
  
  
  Let's get our image gallery up and running.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  We created this component in a separate tutorial.
&lt;/h4&gt;

&lt;p&gt;You can find it &lt;a href="https://dev.to/anobjectisa/react-js-slideshow-responsive-autoplay-with-manual-navigation-buttons-2a49"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We're simply going to import and modify it to fit our project.&lt;/p&gt;

&lt;p&gt;We don't need the left and right navigation buttons for this gallery so we can strip those out.&lt;/p&gt;

&lt;p&gt;Then we just modify some color schemes and we're good to go.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div ref={galleryRef} className="gallery"&amp;gt;
    {
        loaded ?
            &amp;lt;Deck gallery={gallery} /&amp;gt; : null
    }
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108641787-312a9c00-746f-11eb-892f-089b04a1a147.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108641787-312a9c00-746f-11eb-892f-089b04a1a147.gif" alt="gallery"&gt;&lt;/a&gt;&lt;/p&gt;






&lt;h3&gt;
  
  
  Let's implement a navigation bar.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  We created this component in a separate tutorial.
&lt;/h4&gt;

&lt;p&gt;You can find it &lt;a href="https://dev.to/anobjectisa/react-navigation-bar-tutorial-slide-d1d"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We're simply going to import and modify it to fit our project.&lt;/p&gt;

&lt;p&gt;All we really need to do is change the color scheme and icon being used.&lt;/p&gt;

&lt;p&gt;This is our result:&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108641788-3556b980-746f-11eb-9cd6-3f3a44e4822b.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108641788-3556b980-746f-11eb-9cd6-3f3a44e4822b.gif" alt="nav bar"&gt;&lt;/a&gt;&lt;/p&gt;






&lt;h3&gt;
  
  
  There is much more nuance to this project.
&lt;/h3&gt;

&lt;p&gt;You can view our video tutorial down below.&lt;/p&gt;

&lt;p&gt;You can get the source files &lt;a href="https://github.com/an-object-is-a/react-webpage-03" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;All contact image icons we're gathered from &lt;a href="https://fontawesome.com/" rel="noopener noreferrer"&gt;Font Awesome&lt;/a&gt;.&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;center&gt;If you want a more in-depth guide, check out my full video tutorial on YouTube, &lt;strong&gt;&lt;a href="https://www.youtube.com/c/anobjectisa" rel="noopener noreferrer"&gt;An Object Is A&lt;/a&gt;&lt;/strong&gt;.&lt;/center&gt;
&lt;/h4&gt;

&lt;h3&gt;
  
  
  &lt;center&gt;React Valorant Website Tutorial&lt;/center&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/cAC4s5GuUb8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdesign</category>
      <category>webdev</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Make a Pinterest Chrome Extension</title>
      <dc:creator>an-object-is-a</dc:creator>
      <pubDate>Fri, 02 Apr 2021 13:55:02 +0000</pubDate>
      <link>https://dev.to/anobjectisa/make-a-pinterest-chrome-extension-3g4o</link>
      <guid>https://dev.to/anobjectisa/make-a-pinterest-chrome-extension-3g4o</guid>
      <description>&lt;h3&gt;
  
  
  &lt;center&gt;Make a Pinterest Google Chrome Extension&lt;/center&gt;
&lt;/h3&gt;




&lt;h4&gt;
  
  
  This write-up assumes you know how to create a JavaScript Pinterest Clone from scratch.
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;If you don't know how, see our tutorial &lt;a href="https://dev.to/anobjectisa/javascript-pinterest-clone-3pfa"&gt;here&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For this tutorial, we are simply upgrading the functionality of our JavaScript Pinterest Clone and integrating it into a Chrome Extension.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F112740045-8ca4e980-8f47-11eb-8dbb-ad70e81c9841.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F112740045-8ca4e980-8f47-11eb-8dbb-ad70e81c9841.png" alt="Pinterest Chrome Extension"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  We'll do this in 3 phases.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Phase 1: Simply integrate our Pinterest Clone into our Chrome Extension.
&lt;/h4&gt;

&lt;h4&gt;
  
  
  Phase 2: Upgrade our Pinterest Clone to allow for uploading of images from a URL.
&lt;/h4&gt;

&lt;h4&gt;
  
  
  Phase 3: Save all Pin data in local storage and have our board display all Pins in storage.
&lt;/h4&gt;




&lt;h3&gt;
  
  
  Phase 1: Integration
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Let's go over our file structure.
&lt;/h4&gt;

&lt;p&gt;We'll start with the &lt;strong&gt;manifest.json&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "name": "Pinterest Chrome Extension",
    "description": "Pinterest Chrome Extension",
    "version": "0.1.0",
    "manifest_version": 2,
    "icons": {
        "16": "./images/icon-16x16.png",
        "32": "./images/icon-32x32.png",
        "48": "./images/icon-48x48.png",
        "128": "./images/icon-128x128.png"
    },
    "background": {
        "scripts": ["./scripts/background.js"]
    },
    "browser_action": {
        "default_popup": "popup.html"
    },
    "permissions": [
        "tabs",
        "storage",
        "unlimitedStorage",
        "https://*/*png",
        "https://*/*jpg",
        "https://*/*jpeg",
        "https://*/*gif"
    ] 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Things to note:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We need a &lt;strong&gt;background script&lt;/strong&gt; to coordinate our entire extension.&lt;/li&gt;
&lt;li&gt;We need &lt;strong&gt;tabs permission&lt;/strong&gt; so we can save website URLs.&lt;/li&gt;
&lt;li&gt;We need &lt;strong&gt;storage&lt;/strong&gt; and &lt;strong&gt;unlimitedStorage permissions&lt;/strong&gt; so we can save Pin data (including the image data).&lt;/li&gt;
&lt;li&gt;We need &lt;strong&gt;domain/host permissions ending in image extensions&lt;/strong&gt; to allow our extension to download images.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Our popup.html&lt;/strong&gt; will be a simple page that offers the user the option of &lt;strong&gt;adding a new Pin based on the current site they're visiting&lt;/strong&gt; or &lt;strong&gt;opening up their Pin board and added a Pin manually&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F112740068-b78f3d80-8f47-11eb-8e21-a23c25e6011b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F112740068-b78f3d80-8f47-11eb-8e21-a23c25e6011b.png" alt="popup"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;To get our actual Pinterest Board integrated into the extension, we simply open a new tab in the user's browser with our Pinterest Board&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So when the user clicks on a button in our &lt;strong&gt;popup.html&lt;/strong&gt;, we execute a &lt;strong&gt;popup_script.js&lt;/strong&gt; script that tells our &lt;strong&gt;background.js&lt;/strong&gt; to open our board or add a Pin.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chrome.runtime.onMessage.addListener((request, sender, sendResponse) =&amp;gt; {
    if (request.message === 'add_pin') {
        new_pin_data = { ...request.payload };

        chrome.tabs.create({
            active: true,
            url: './board.html'
        }, tab =&amp;gt; recent_tab = tab.id);
    } else if (request.message === 'my_board') {
        chrome.tabs.create({
            active: true,
            url: './board.html'
        });
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F112753731-dbce3700-8fa6-11eb-970c-5a013c334cb8.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F112753731-dbce3700-8fa6-11eb-970c-5a013c334cb8.gif" alt="add pin and open board"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Phase 2: Upgrade
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Let's add the ability to save an image from a URL.
&lt;/h4&gt;

&lt;p&gt;When the user clicks on our "&lt;strong&gt;Save from site&lt;/strong&gt;" button, we'll open up an &lt;strong&gt;input&lt;/strong&gt; and take a URL.&lt;/p&gt;

&lt;p&gt;We'll use a &lt;strong&gt;fetch&lt;/strong&gt; to get the image and process it the same way as when we choose an image from our local hard-drive.&lt;br&gt;
&lt;/p&gt;

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

&amp;lt;div class="save_from_site"&amp;gt;
    &amp;lt;span style="pointer-events: none;"&amp;gt;Save From Site&amp;lt;/span&amp;gt;
    &amp;lt;input placeholder="Past a URL to an image" type="text" name="save_from_site_input"
        id="save_from_site_input"&amp;gt;
    &amp;lt;div class="upload_image_url"&amp;gt;Upload&amp;lt;/div&amp;gt;
    &amp;lt;div class="cancel_image_url"&amp;gt;Cancel&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// board.js
if (event.target === save_from_site) {
    // hide the 'save from site' button
    // show the input for taking a url
    // show the upload button
    // show the cancel button
} else if (event.target === upload_image_url) {
    // fetch the image from the url
    // parse the image as a blob
    // read the image into our Pinterest board
} else if (event.target === cancel_image_url) {
    // show the 'save from site' button
    // hide the input for taking a url
    // hide the upload button
    // hide the cancel button
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F112753733-dec92780-8fa6-11eb-98c5-dc3385909d1f.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F112753733-dec92780-8fa6-11eb-98c5-dc3385909d1f.gif" alt="add image by url"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Phase 3: Storage
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Let's use Chrome's 'localstorage' API.
&lt;/h4&gt;

&lt;p&gt;Saving data to the user's HDD is very simple. We'll save the information as an &lt;strong&gt;array of objects&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;With two calls using the 'storage' API, we can get previously saved &lt;strong&gt;Pins&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chrome.storage.local.get('pins', data =&amp;gt; {});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add a new &lt;strong&gt;Pin&lt;/strong&gt; to the dataset.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const new_pins = data.pins ? [...data.pins, new_pin_data] : [new_pin_data];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and save the updated &lt;strong&gt;Pins&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chrome.storage.local.set({ pins: new_pins });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;We can then give the Pinterest board the saved Pins when requested.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

chrome.runtime.sendMessage({
    message: 'get_pins'
}, response =&amp;gt; {
    if (response.message === 'success') {
        response.payload.forEach(pin_data =&amp;gt; {
            create_pin(pin_data);
        });
    }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// background.js
...
} else if (request.message === 'get_pins') {
    chrome.storage.local.get('pins', data =&amp;gt; {
        if (chrome.runtime.lastError) {
            sendResponse({ message: 'fail' });
            return;
        }

        sendResponse({
            message: 'success',
            payload: data.pins ? data.pins : []
        });
    });

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

&lt;/div&gt;






&lt;h3&gt;
  
  
  There is much more nuance to this project.
&lt;/h3&gt;

&lt;p&gt;You can get the source files &lt;a href="https://github.com/an-object-is-a/chrome-ext-pinterest" rel="noopener noreferrer"&gt;here&lt;/a&gt; and you can follow the video tutorial down below.&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;center&gt;If you want a more in-depth guide, check out my full video tutorial on YouTube, &lt;strong&gt;&lt;a href="https://www.youtube.com/c/anobjectisa" rel="noopener noreferrer"&gt;An Object Is A&lt;/a&gt;&lt;/strong&gt;.&lt;/center&gt;
&lt;/h4&gt;

&lt;h3&gt;
  
  
  &lt;center&gt;Make a Pinterest Google Chrome Extension&lt;/center&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/mRUTxdUHf8g"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>design</category>
      <category>ux</category>
    </item>
    <item>
      <title>React Navigation Bar Tutorial (Slide)</title>
      <dc:creator>an-object-is-a</dc:creator>
      <pubDate>Fri, 26 Mar 2021 12:33:31 +0000</pubDate>
      <link>https://dev.to/anobjectisa/react-navigation-bar-tutorial-slide-d1d</link>
      <guid>https://dev.to/anobjectisa/react-navigation-bar-tutorial-slide-d1d</guid>
      <description>&lt;h3&gt;
  
  
  &lt;center&gt;React Navigation Bar Tutorial (Slide)&lt;/center&gt;
&lt;/h3&gt;




&lt;h4&gt;
  
  
  &lt;center&gt;Browse our &lt;a href="http://anobject.teachable.com" rel="noopener noreferrer"&gt;Teachable&lt;/a&gt; courses.&lt;/center&gt;
&lt;/h4&gt;




&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F111928813-10179400-8a8b-11eb-8154-ee571c49acd2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F111928813-10179400-8a8b-11eb-8154-ee571c49acd2.png" alt="React Navigation Bar Tutorial (Slide)"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Let's get the skeleton for our component written up.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  We'll be using 'react-router-dom' and font awesome for this project.
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; &amp;lt;div className="nav_bar"&amp;gt;
    &amp;lt;div className="icon_container menu_switch"&amp;gt;

    &amp;lt;/div&amp;gt;

    &amp;lt;div className={`nav_container`}&amp;gt;
        &amp;lt;div className="icon_container logo"&amp;gt;

        &amp;lt;/div&amp;gt;
        &amp;lt;ul className="menu_items"&amp;gt;

        &amp;lt;/ul&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;We have a place for our &lt;strong&gt;open/close menu button&lt;/strong&gt;, a &lt;strong&gt;logo&lt;/strong&gt;, and the &lt;strong&gt;menu with links&lt;/strong&gt; to different pages.&lt;/p&gt;




&lt;h3&gt;
  
  
  Opening and closing our menu.
&lt;/h3&gt;

&lt;p&gt;When the user clicks our menu button, we'll open or close our menu depending on the current state of the menu.&lt;/p&gt;

&lt;p&gt;We'll have a piece of state called &lt;strong&gt;showMenu&lt;/strong&gt; to manage this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [showMenu, setShowMenu] = useState(false);

function switch_menu() {
    setShowMenu(!showMenu);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When &lt;strong&gt;showMenu&lt;/strong&gt; is &lt;strong&gt;true&lt;/strong&gt; we'll attach a &lt;strong&gt;CSS class&lt;/strong&gt; to trigger a transition.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className={`nav_container ${showMenu ? 'menu_active' : null}`}&amp;gt;
    &amp;lt;div className="icon_container logo"&amp;gt;
        &amp;lt;i className="fab fa-earlybirds" /&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;ul className="menu_items"&amp;gt;
        &amp;lt;li&amp;gt;
            &amp;lt;Link to="/" onClick={switch_menu}&amp;gt;Home&amp;lt;/Link&amp;gt;
        &amp;lt;/li&amp;gt;
        &amp;lt;li&amp;gt;
            &amp;lt;Link to="/products" onClick={switch_menu}&amp;gt;Products&amp;lt;/Link&amp;gt;
        &amp;lt;/li&amp;gt;
        &amp;lt;li&amp;gt;
            &amp;lt;Link to="/about" onClick={switch_menu}&amp;gt;About&amp;lt;/Link&amp;gt;
        &amp;lt;/li&amp;gt;
    &amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note how we use a string template to include the menu_active class in the className of our DIV.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We start the menu off-screen:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.nav_container {
    transform: translateY(-100%);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and when we "&lt;strong&gt;activate&lt;/strong&gt;" the menu, we simply translate it back to its default position.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.menu_active {
    opacity: 1;
    transform: translate(0%, 0%);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F110406844-e0ab6500-8050-11eb-9c64-7e2b8430717a.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F110406844-e0ab6500-8050-11eb-9c64-7e2b8430717a.gif" alt="nav bar desktop"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;The actual links come from the &lt;strong&gt;Link&lt;/strong&gt; element in &lt;strong&gt;react-router-dom&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Link to="/" onClick={switch_menu}&amp;gt;Home&amp;lt;/Link&amp;gt;
&amp;lt;Link to="/products" onClick={switch_menu}&amp;gt;Products&amp;lt;/Link&amp;gt;
&amp;lt;Link to="/about" onClick={switch_menu}&amp;gt;About&amp;lt;/Link&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  The mobile version.
&lt;/h3&gt;

&lt;p&gt;The mobile version is real simple.&lt;/p&gt;

&lt;p&gt;We give our navigation bar new dimenensions.&lt;/p&gt;

&lt;p&gt;Instead of taking up an 80px bar at the top of the page, we just make it take up the entire page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.nav_bar {
    width: 100vw;
    height: 100vh;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The bar is animated with the exact same logic, but instead of sliding on the &lt;strong&gt;Y-axis&lt;/strong&gt; we slide on the &lt;strong&gt;X-axis&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F111929600-3b02e780-8a8d-11eb-9f8a-1dc48e59cc3d.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F111929600-3b02e780-8a8d-11eb-9f8a-1dc48e59cc3d.gif" alt="nav bar mobile"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  There is a bit more detail to this project.
&lt;/h3&gt;

&lt;p&gt;You can find the source files &lt;a href="https://github.com/an-object-is-a/react-nav-bar-01-basic" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;All icons were gathered from &lt;a href="https://fontawesome.com/" rel="noopener noreferrer"&gt;Font Awesome&lt;/a&gt;.&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;center&gt;If you want a more in-depth guide, check out my full video tutorial on YouTube, &lt;strong&gt;&lt;a href="https://www.youtube.com/c/anobjectisa" rel="noopener noreferrer"&gt;An Object Is A&lt;/a&gt;&lt;/strong&gt;.&lt;/center&gt;
&lt;/h4&gt;

&lt;h3&gt;
  
  
  &lt;center&gt;React Navigation Bar Tutorial (Slide)&lt;/center&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/zLGdru79Ui0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>webdesign</category>
      <category>ux</category>
    </item>
    <item>
      <title>React Website with Image Slideshow</title>
      <dc:creator>an-object-is-a</dc:creator>
      <pubDate>Fri, 19 Mar 2021 13:51:23 +0000</pubDate>
      <link>https://dev.to/anobjectisa/react-website-with-image-slideshow-3bkj</link>
      <guid>https://dev.to/anobjectisa/react-website-with-image-slideshow-3bkj</guid>
      <description>&lt;h3&gt;
  
  
  &lt;center&gt;React Website With Image Slideshow&lt;/center&gt;
&lt;/h3&gt;




&lt;h4&gt;
  
  
  &lt;center&gt;Browse our &lt;a href="http://anobject.teachable.com" rel="noopener noreferrer"&gt;Teachable&lt;/a&gt; courses.&lt;/center&gt;
&lt;/h4&gt;




&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F111089213-3bd1d180-8501-11eb-84d4-a105d66b144c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F111089213-3bd1d180-8501-11eb-84d4-a105d66b144c.png" alt="React Website with Image Slideshow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  We'll build this webpage in 3 main parts.
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Top&lt;/strong&gt; - the greeting for our customer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Middle&lt;/strong&gt; - a place for information about our business' mission&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bottom&lt;/strong&gt; - a footer for information about our business&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  We'll create a Home.js component for our main page.
&lt;/h4&gt;




&lt;h3&gt;
  
  
  The Top.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  All we're going to do here is set an image for our background and title for our company.
&lt;/h4&gt;

&lt;p&gt;The image gallery comes later; it's a separate element that we float around our page depending on the dimensions.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className="section1"&amp;gt;
    &amp;lt;img src="./images/background-section1.jpg" alt="" className="background_image_section1" /&amp;gt;
    &amp;lt;div className="title"&amp;gt;Sinclaire&amp;lt;br /&amp;gt;Market&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is our result:&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108138005-103b0300-708b-11eb-82ae-14bd4192343b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108138005-103b0300-708b-11eb-82ae-14bd4192343b.png" alt="top"&gt;&lt;/a&gt;&lt;/p&gt;






&lt;h3&gt;
  
  
  The Middle.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  For this section we'll have an image for our background; a message to our user; an image; and a call to action.
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className="section2" style={{ backgroundImage: "url('images/marble.jpg')" }}&amp;gt;
    &amp;lt;img src="./images/background-section2.png" alt="" className="background_image_section2" /&amp;gt;
    &amp;lt;div className="left_side"&amp;gt;
        Organic.&amp;lt;br/&amp;gt;Ethical.&amp;lt;br/&amp;gt;Fresh.
    &amp;lt;/div&amp;gt;

    &amp;lt;div className="right_side"&amp;gt;
        &amp;lt;img src="./images/spice-bowl.png" alt=""/&amp;gt;
    &amp;lt;/div&amp;gt;

    &amp;lt;div className="call_to_action"&amp;gt;
        Browse our selection.
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is our result:&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108137658-5479d380-708a-11eb-8502-41605e61b733.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108137658-5479d380-708a-11eb-8502-41605e61b733.png" alt="middle"&gt;&lt;/a&gt;&lt;/p&gt;






&lt;h3&gt;
  
  
  The Bottom.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  A simple unordered list of items that can act as links.
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className="section3"&amp;gt;
    &amp;lt;div className="contacts" &amp;gt;
        &amp;lt;section className="contact_section" &amp;gt;
            &amp;lt;ul&amp;gt;
                &amp;lt;li&amp;gt;Affiliates&amp;lt;/li&amp;gt;
                &amp;lt;li&amp;gt;Careers&amp;lt;/li&amp;gt;
                &amp;lt;li&amp;gt;Privacy&amp;lt;/li&amp;gt;
            &amp;lt;/ul&amp;gt;
        &amp;lt;/section&amp;gt;
        &amp;lt;section className="contact_section" &amp;gt;
            &amp;lt;ul&amp;gt;
                &amp;lt;li&amp;gt;Telephone &amp;lt;i className="fas fa-phone-square-alt"&amp;gt;&amp;lt;/i&amp;gt; &amp;lt;/li&amp;gt;
                &amp;lt;li&amp;gt;Email &amp;lt;i className="fas fa-envelope-square"&amp;gt;&amp;lt;/i&amp;gt; &amp;lt;/li&amp;gt;
            &amp;lt;/ul&amp;gt;
        &amp;lt;/section&amp;gt;
        &amp;lt;section className="contact_section" &amp;gt;
            &amp;lt;ul&amp;gt;
                &amp;lt;li&amp;gt;Instagram &amp;lt;i className="fab fa-instagram-square"&amp;gt;&amp;lt;/i&amp;gt; &amp;lt;/li&amp;gt;
                &amp;lt;li&amp;gt;Twitter &amp;lt;i className="fab fa-twitter-square"&amp;gt;&amp;lt;/i&amp;gt; &amp;lt;/li&amp;gt;
                &amp;lt;li&amp;gt;Facebook &amp;lt;i className="fab fa-facebook-square"&amp;gt;&amp;lt;/i&amp;gt; &amp;lt;/li&amp;gt;
            &amp;lt;/ul&amp;gt;
        &amp;lt;/section&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is our result:&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108137671-5c397800-708a-11eb-984e-edbbcf9db970.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108137671-5c397800-708a-11eb-984e-edbbcf9db970.png" alt="bottom"&gt;&lt;/a&gt;&lt;/p&gt;






&lt;h3&gt;
  
  
  Let's get our image gallery up and running.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  We created this component in a separate tutorial.
&lt;/h4&gt;

&lt;p&gt;You can find it &lt;a href="https://dev.to/anobjectisa/react-js-slideshow-responsive-autoplay-with-manual-navigation-buttons-2a49"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We're simply going to import and modify it to fit our project.&lt;/p&gt;

&lt;p&gt;All we really need to do is create a parent element for it in our project, we'll call it the gallery, and position it on our page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className="gallery"&amp;gt;
    &amp;lt;Deck gallery={gallery} /&amp;gt; 
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108137582-23010800-708a-11eb-8b16-ab3e72b192ef.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108137582-23010800-708a-11eb-8b16-ab3e72b192ef.png" alt="gallery placeholder"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;We'll change some code in our 'Deck.js' component (the image gallery) and fit it into our parent element.&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108137737-7d9a6400-708a-11eb-884a-8063472ffa2d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108137737-7d9a6400-708a-11eb-884a-8063472ffa2d.png" alt="image gallery working"&gt;&lt;/a&gt;&lt;/p&gt;






&lt;h3&gt;
  
  
  Let's finish by implementing a navigation bar.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  We created this component in a separate tutorial.
&lt;/h4&gt;

&lt;p&gt;We're simply going to import and modify it to fit our project.&lt;/p&gt;

&lt;p&gt;All we really need to do is change the color scheme and icon being used.&lt;/p&gt;

&lt;p&gt;This is our result:&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108138302-b424ae80-708b-11eb-86a2-4b120023c567.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F108138302-b424ae80-708b-11eb-86a2-4b120023c567.png" alt="nav bar desktop"&gt;&lt;/a&gt;&lt;/p&gt;






&lt;h3&gt;
  
  
  There is much more nuance to this project.
&lt;/h3&gt;

&lt;p&gt;You can view our video tutorial down below.&lt;/p&gt;

&lt;p&gt;You can get the source files &lt;a href="https://github.com/an-object-is-a/react-webpage-02" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;All images we're gathered from &lt;a href="https://www.pexels.com/" rel="noopener noreferrer"&gt;Pexels&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;All contact image icons we're gathered from &lt;a href="https://fontawesome.com/" rel="noopener noreferrer"&gt;Font Awesome&lt;/a&gt;.&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;center&gt;If you want a more in-depth guide, check out my full video tutorial on YouTube, &lt;strong&gt;&lt;a href="https://www.youtube.com/c/anobjectisa" rel="noopener noreferrer"&gt;An Object Is A&lt;/a&gt;&lt;/strong&gt;.&lt;/center&gt;
&lt;/h4&gt;

&lt;h3&gt;
  
  
  &lt;center&gt;React Website with Image Slideshow&lt;/center&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/ltk0aNYB_mM"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>webdesign</category>
    </item>
    <item>
      <title>React Parallax Website Design</title>
      <dc:creator>an-object-is-a</dc:creator>
      <pubDate>Fri, 12 Mar 2021 14:37:46 +0000</pubDate>
      <link>https://dev.to/anobjectisa/react-parallax-website-design-23ok</link>
      <guid>https://dev.to/anobjectisa/react-parallax-website-design-23ok</guid>
      <description>&lt;h3&gt;
  
  
  &lt;center&gt;React Parallax Website Design&lt;/center&gt;
&lt;/h3&gt;




&lt;h4&gt;
  
  
  &lt;center&gt;Browse our &lt;a href="http://anobject.teachable.com" rel="noopener noreferrer"&gt;Teachable&lt;/a&gt; courses.&lt;/center&gt;
&lt;/h4&gt;




&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F110365552-29442d80-8013-11eb-8081-e3bcb1253ead.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F110365552-29442d80-8013-11eb-8081-e3bcb1253ead.png" alt="React Parallax Website Design"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  We'll build this webpage in 3 parts.
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Top&lt;/strong&gt; - the greeting for our customer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Middle&lt;/strong&gt; - a place for information about our business' mission&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bottom&lt;/strong&gt; - a sign-up option and footer for information about our business&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  The Top.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  All we're going to do here is set a bunch of images in place and write a greeting.
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className="section1" &amp;gt;
    &amp;lt;img src="./images/space.png" alt="" className="space-background"/&amp;gt;
    &amp;lt;img src="./images/earth.png" alt="" className="earth"/&amp;gt;
    &amp;lt;img src="./images/rocket.png" alt="" className="rocket-ship"/&amp;gt;
    &amp;lt;img src="./images/planet1.png" alt="" className="planet1"/&amp;gt;
    &amp;lt;img src="./images/satellite.png" alt="" className="satellite"/&amp;gt;
    &amp;lt;div className="greeting"&amp;gt;[Welcome]&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's important in the CSS styles for all of these images that we make sure they have a &lt;strong&gt;&lt;em&gt;position of 'fixed'&lt;/em&gt;&lt;/strong&gt; and are positioned using the &lt;strong&gt;&lt;em&gt;'top'&lt;/em&gt;&lt;/strong&gt; property.&lt;/p&gt;

&lt;p&gt;This important for later when we use our &lt;strong&gt;Parallax HOC Wrapper&lt;/strong&gt; to make these elements scroll at different speeds.&lt;/p&gt;

&lt;p&gt;This is our result:&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F107833819-71e52f80-6d62-11eb-8b60-33db57a54dea.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F107833819-71e52f80-6d62-11eb-8b60-33db57a54dea.png" alt="top"&gt;&lt;/a&gt;&lt;/p&gt;






&lt;h3&gt;
  
  
  The Middle.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  For this section we'll create curved borders and split the section into a left and right side.
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className="section2" &amp;gt;
    &amp;lt;svg className="svg_curve_top" xmlns="http://www.w3.org/2000/svg" fill="orange" viewBox="0 0 100 100" preserveAspectRatio="none" &amp;gt;
        &amp;lt;path d="M0,100 C65,93 76,10 100,100" /&amp;gt;
    &amp;lt;/svg&amp;gt;

    &amp;lt;div className="section2_container"&amp;gt;
        &amp;lt;div className="left_side"&amp;gt;
            // text here
        &amp;lt;/div&amp;gt;
        &amp;lt;div className="right_side"&amp;gt;
            // image here
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;

    &amp;lt;svg className="svg_curve_bottom" xmlns="http://www.w3.org/2000/svg" fill="orange" viewBox="0 0 100 100" preserveAspectRatio="none" &amp;gt;
        &amp;lt;path d="M0,0 C65,20 90,5 100,0" /&amp;gt;
    &amp;lt;/svg&amp;gt;
&amp;lt;/div&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;svg&lt;/strong&gt; elements here create a nice curve effect on the top and bottom of this section.&lt;/p&gt;

&lt;p&gt;We used the site &lt;a href="https://sean.brunnock.com/SVG/SVGPathGenerator/" rel="noopener noreferrer"&gt;Cubic Bezier Curve Generator&lt;/a&gt; to help us with the code generation.&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F107834192-8fff5f80-6d63-11eb-9195-6308efd95425.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F107834192-8fff5f80-6d63-11eb-9195-6308efd95425.png" alt="middle"&gt;&lt;/a&gt;&lt;/p&gt;






&lt;h3&gt;
  
  
  The Bottom.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  A simple text input and unordered lists finish our bottom section.
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className="section3" &amp;gt;
    Sign up to receive our newsletter!
    &amp;lt;input className="input_email" type="text" name="email" id="email" /&amp;gt;
    &amp;lt;MyButton text="Sign Up" /&amp;gt;

    &amp;lt;div className="contacts" &amp;gt;
        &amp;lt;section className="contact_section" &amp;gt;
            &amp;lt;ul&amp;gt;
                // your items here
            &amp;lt;/ul&amp;gt;
        &amp;lt;/section&amp;gt;
        &amp;lt;section className="contact_section" &amp;gt;
            &amp;lt;ul&amp;gt;
                // your items here
            &amp;lt;/ul&amp;gt;
        &amp;lt;/section&amp;gt;
        &amp;lt;section className="contact_section" &amp;gt;
            &amp;lt;ul&amp;gt;
                // your items here
            &amp;lt;/ul&amp;gt;
        &amp;lt;/section&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The '&lt;strong&gt;Button&lt;/strong&gt;' is a custom component complete with an animation upon clicking.&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F107834920-baeab300-6d65-11eb-827d-a734c53d1b2b.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F107834920-baeab300-6d65-11eb-827d-a734c53d1b2b.gif" alt="bottom"&gt;&lt;/a&gt;&lt;/p&gt;






&lt;h3&gt;
  
  
  Let's handle Parallaxing.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  We created this HOC Wrapper in another tutorial.
&lt;/h4&gt;

&lt;p&gt;You can find it &lt;a href="https://youtu.be/mehs92oAuYE" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We're simply going to wrap anything we wan to move at a different speed in this wrapper and place the new component into our code.&lt;/p&gt;

&lt;p&gt;For example,&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;this&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;img src="./images/rocket.png" alt="" className="rocket-ship"/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;becomes this&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const RocketShip = JSX_withParallax(&amp;lt;img src="./images/rocket.png" alt="" className="rocket-ship" /&amp;gt;, 0.04);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;and is placed in our code like this&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;





&lt;p&gt;Wrapping everything we want gives us this final effect:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F107835964-62b5b000-6d69-11eb-99bf-fe0ddb23b897.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F107835964-62b5b000-6d69-11eb-99bf-fe0ddb23b897.gif" alt="final"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  There is much more nuance to this project.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Including the code for our custom 'Button' component.
&lt;/h4&gt;

&lt;p&gt;You can view our video tutorial down below.&lt;/p&gt;

&lt;p&gt;You can get the source files &lt;a href="https://github.com/an-object-is-a/react-webpage-01" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;All space imagery was gathered from &lt;a href="https://www.flaticon.com/" rel="noopener noreferrer"&gt;Flat Icon&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;All contact image icons we're gathered from &lt;a href="https://fontawesome.com/" rel="noopener noreferrer"&gt;Font Awesome&lt;/a&gt;.&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;center&gt;If you want a more in-depth guide, check out my full video tutorial on YouTube, &lt;strong&gt;&lt;a href="https://www.youtube.com/c/anobjectisa" rel="noopener noreferrer"&gt;An Object Is A&lt;/a&gt;&lt;/strong&gt;.&lt;/center&gt;
&lt;/h4&gt;

&lt;h3&gt;
  
  
  &lt;center&gt;React Parallax Website Design&lt;/center&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/N0C8pwM5BGc"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>design</category>
    </item>
    <item>
      <title>Copy &amp; Search Chrome Extension</title>
      <dc:creator>an-object-is-a</dc:creator>
      <pubDate>Fri, 05 Mar 2021 15:32:54 +0000</pubDate>
      <link>https://dev.to/anobjectisa/copy-search-chrome-extension-3npj</link>
      <guid>https://dev.to/anobjectisa/copy-search-chrome-extension-3npj</guid>
      <description>&lt;h3&gt;
  
  
  &lt;center&gt;Copy &amp;amp; Search Chrome Extension&lt;/center&gt;
&lt;/h3&gt;




&lt;h3&gt;
  
  
  &lt;center&gt;This tutorial assumes you know how a Chrome Extension works.&lt;/center&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;center&gt;Experienced Web Developer? Check out our fast and free Youtube tutorial.&lt;/center&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/-dhMbVEreII"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F109964208-5d3dec80-7cbb-11eb-9618-4fa514cece87.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F109964208-5d3dec80-7cbb-11eb-9618-4fa514cece87.png" alt="Copy &amp;amp; Search Chrome Extension"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Rundown
&lt;/h3&gt;

&lt;p&gt;We'll have a simple HTML page that allows our user to pick a search engine; this page will be the &lt;strong&gt;popup&lt;/strong&gt; in our Chrome Extension.&lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;foreground&lt;/strong&gt; script we'll listen for when the user copies a piece of text. When they do, we'll get our &lt;strong&gt;background&lt;/strong&gt; script to open a new with the appropriate URL and search parameter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's start.&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Our manifest.json
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Nothing special here.
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "name": "Clipboard Search",
    "manifest_version": 2,
    "description": "Testing clipboard functionality.",
    "version": "0.0.0",
    "background": {
        "scripts":["background.js"]
    },
    "browser_action": {
        "default_popup": "popup.html"
    },
    "permissions": [
        "tabs",
        "&amp;lt;all_urls&amp;gt;"
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;The only permissions we'll need are the &lt;strong&gt;tabs&lt;/strong&gt; so we can inject our &lt;strong&gt;foreground script&lt;/strong&gt; into specific tabs and &lt;strong&gt;&amp;lt;all_urls&amp;gt;&lt;/strong&gt; so we can inject our &lt;strong&gt;foreground script&lt;/strong&gt; into specific webpages.&lt;/p&gt;




&lt;h3&gt;
  
  
  The popup.html
&lt;/h3&gt;

&lt;h4&gt;
  
  
  A simple web page.
&lt;/h4&gt;

&lt;p&gt;Nothing complicated here.&lt;/p&gt;

&lt;p&gt;We have a &lt;strong&gt;select&lt;/strong&gt; with &lt;strong&gt;options&lt;/strong&gt;, a &lt;strong&gt;button&lt;/strong&gt; for submission, and a &lt;strong&gt;div&lt;/strong&gt; to display their search engine of choice.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="container"&amp;gt;
    &amp;lt;div class="section1"&amp;gt;
        &amp;lt;select name="search_engine" id="search_engine"&amp;gt;
            &amp;lt;option value="" disabled selected&amp;gt;Choose a search engine&amp;lt;/option&amp;gt;
            &amp;lt;option value="google"&amp;gt;Google&amp;lt;/option&amp;gt;
            &amp;lt;option value="startpage"&amp;gt;Start Page&amp;lt;/option&amp;gt;
            &amp;lt;option value="duckduckgo"&amp;gt;Duck Duck Go&amp;lt;/option&amp;gt;
            &amp;lt;option value="ecoasia"&amp;gt;Ecoasia&amp;lt;/option&amp;gt;
            &amp;lt;option value="bing"&amp;gt;Bing&amp;lt;/option&amp;gt;
        &amp;lt;/select&amp;gt;
        &amp;lt;button&amp;gt;Select&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div class="section2"&amp;gt;
        &amp;lt;div class="search_engine_choice"&amp;gt;Your Current Search Engine&amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;Here is what we have:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F109962190-e43d9580-7cb8-11eb-8620-1d9924b53050.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F109962190-e43d9580-7cb8-11eb-8620-1d9924b53050.png" alt="popup"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Our foreground script
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Not a lot of code here.
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;document.addEventListener('copy', () =&amp;gt; {
    navigator.clipboard.readText()
        .then(res =&amp;gt; {
            chrome.runtime.sendMessage({
                message: 'search',
                payload: `"${res}"`
            });
        })
        .catch(err =&amp;gt; console.log(err));
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;We create a listener for the &lt;strong&gt;copy&lt;/strong&gt; event. When triggered, we get the copied material from the &lt;strong&gt;clipboard&lt;/strong&gt; using the &lt;strong&gt;readText()&lt;/strong&gt; method.&lt;/p&gt;

&lt;p&gt;We then send the copied text to our &lt;strong&gt;background script&lt;/strong&gt; using the &lt;strong&gt;chrome.runtime.sendMessage()&lt;/strong&gt; method.&lt;/p&gt;




&lt;h3&gt;
  
  
  Our background script
&lt;/h3&gt;

&lt;h4&gt;
  
  
  This is where the bulk of our extension gets written.
&lt;/h4&gt;

&lt;p&gt;Here we have an object that holds all of our search engine strings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const search_engines = {
    google: 'https://www.google.com/search?q=',
    startpage: 'https://www.startpage.com/do/dsearch?query=',
    duckduckgo: 'https://duckduckgo.com/?q=',
    ecoasia: 'https://www.ecosia.org/search?q=',
    bing: 'https://www.bing.com/search?q='
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When our Chrome Extension detects that a user has opened a new tab, we make sure to inject our &lt;strong&gt;foreground script&lt;/strong&gt; into that page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) =&amp;gt; {
    if (/^http/.test(tab.url) &amp;amp;&amp;amp; changeInfo.status === 'complete') {
        chrome.tabs.executeScript(tabId, { file: './scripts/foreground.js' }, () =&amp;gt; {
            console.log('The foreground script has been injected.');
        });
    }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;In the &lt;strong&gt;background&lt;/strong&gt; listener we listen for the message, "&lt;strong&gt;search&lt;/strong&gt;", from our &lt;strong&gt;foreground&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When we receive it, we open up a new tab for our user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chrome.runtime.onMessage.addListener((request, sender, sendResponse) =&amp;gt; {
    if (request.message === 'save_search_engine') {
        current_search_engine = request.payload;
        sendResponse({ message: 'success' });
    } else if (request.message === 'get_current_search_engine') {
        sendResponse({ payload: current_search_engine });
    } else if (request.message === 'search') {
        chrome.tabs.create({
            active: true,
            url: `${search_engines[current_search_engine]}${request.payload}`
        });
    }
});

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

&lt;/div&gt;





&lt;p&gt;Notice how the &lt;strong&gt;url&lt;/strong&gt; property has a value constructed of the &lt;strong&gt;search engine&lt;/strong&gt; of choice plus the search term, the &lt;strong&gt;request.payload&lt;/strong&gt;, amended to the string.&lt;/p&gt;




&lt;h3&gt;
  
  
  That's the basics of how this extension works.
&lt;/h3&gt;

&lt;p&gt;You can get the source files &lt;a href="https://github.com/an-object-is-a/chrome-ext-copy-paste" rel="noopener noreferrer"&gt;here&lt;/a&gt; and/or you can watch a video tutorial down below.&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;center&gt;If you want a more in-depth guide, check out my full video tutorial on YouTube, &lt;strong&gt;&lt;a href="https://www.youtube.com/c/anobjectisa" rel="noopener noreferrer"&gt;An Object Is A&lt;/a&gt;&lt;/strong&gt;.&lt;/center&gt;
&lt;/h4&gt;

&lt;h3&gt;
  
  
  &lt;center&gt;Copy &amp;amp; Search Chrome Extension&lt;/center&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/upFe5i3iSzA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>React Parallax Scrolling Web Design Solution</title>
      <dc:creator>an-object-is-a</dc:creator>
      <pubDate>Mon, 01 Mar 2021 15:08:07 +0000</pubDate>
      <link>https://dev.to/anobjectisa/react-parallax-scrolling-web-design-solution-25h4</link>
      <guid>https://dev.to/anobjectisa/react-parallax-scrolling-web-design-solution-25h4</guid>
      <description>&lt;h3&gt;
  
  
  &lt;center&gt;React Parallax Scrolling Web Design Solution&lt;/center&gt;
&lt;/h3&gt;




&lt;h4&gt;
  
  
  &lt;center&gt;Browse our &lt;a href="http://anobject.teachable.com" rel="noopener noreferrer"&gt;Teachable&lt;/a&gt; courses.&lt;/center&gt;
&lt;/h4&gt;




&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F109092653-ee71f980-76e4-11eb-91b2-61d7f217acec.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F109092653-ee71f980-76e4-11eb-91b2-61d7f217acec.png" alt="React Parallax Scrolling Web Design"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The general solution we're working with is this:
&lt;/h3&gt;

&lt;p&gt;We are going to create an &lt;strong&gt;HOC&lt;/strong&gt; (Higher Order Component).&lt;/p&gt;

&lt;p&gt;It's a function that's going to take a &lt;strong&gt;JSX Element&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;ex. &lt;strong&gt;higherOrderFunction(&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's then going to return a &lt;strong&gt;JSX Component&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;ex. &lt;strong&gt;ParallaxComponent&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We'll then render it to our page like this:&lt;/p&gt;





&lt;h4&gt;
  
  
  The logic for parallaxing is this:
&lt;/h4&gt;

&lt;p&gt;We are going to &lt;strong&gt;fix&lt;/strong&gt; a &lt;strong&gt;JSX element&lt;/strong&gt; to our page (&lt;strong&gt;&lt;em&gt;in this case a DIV shaped like a circle&lt;/em&gt;&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;When we scroll our page &lt;strong&gt;DOWN&lt;/strong&gt;, we'll manually scroll the &lt;strong&gt;JSX element&lt;/strong&gt; &lt;strong&gt;UP&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Since we are manually scrolling our element up, we can control how fast or slow it moves.&lt;/p&gt;

&lt;p&gt;This creates our &lt;strong&gt;parallax effect&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Let's get our JSX on screen.
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;A simple 'div'&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;return (
    &amp;lt;div&amp;gt;
        &amp;lt;img src="./back.png" alt="" /&amp;gt;
        &amp;lt;div style={styles.obj}&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;We'll style it as a circle&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;obj: {
    margin: 0,
    padding: 0,
    height: '200px',
    width: '200px',
    position: 'fixed',
    top: '50%',
    left: '50%',
    transform: 'translate(-50%, -50%)',
    borderRadius: '50%',
    backgroundColor: '#0083FF',
    boxShadow: '0px 0px 20px 10px #0083FF'
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F103606485-83762480-4ee4-11eb-8872-e6bb37c6b936.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F103606485-83762480-4ee4-11eb-8872-e6bb37c6b936.png" alt="parallax-not-complete"&gt;&lt;/a&gt;&lt;/p&gt;






&lt;h3&gt;
  
  
  Let's write our Higher-Order Component.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  We'll need 6 variables to accomplish our parallax animation.
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;JSXElement&lt;/strong&gt; - the JSX element we pass into our HOC&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;start_position&lt;/strong&gt; - where does this element start (&lt;strong&gt;&lt;em&gt;y position&lt;/em&gt;&lt;/strong&gt;) relative to the top of the document/page&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ease&lt;/strong&gt; - we control how fast or slow the JSX element scrolls relative to our page&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;last_offset&lt;/strong&gt; - we keep track of how far, in total, we have scrolled up or down&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;animation_running&lt;/strong&gt; - we use this to get our &lt;strong&gt;requestAnimationFrame() loop&lt;/strong&gt; to start and stop&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  5 main steps.
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create a &lt;strong&gt;ref&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const ref = React.createRef();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Clone the &lt;strong&gt;JSX Element&lt;/strong&gt; while adding that &lt;strong&gt;ref&lt;/strong&gt; into our clone.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const JSXElementWithRef = React.cloneElement(
    JSXElement,
    { ...JSXElement.props, ref: ref },
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Save the new &lt;strong&gt;JSX Component&lt;/strong&gt; in the state of our class component.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;this.setState({
    ease: _weight,
    WrappedJSXElement: JSXElementWithRef
}, () =&amp;gt; {
    this.setState({ start_position: ref.current.offsetTop }, () =&amp;gt; {
        this.wrappedJSXElement = ref;
        document.addEventListener("scroll", this.animate_scroll);
    });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Render our new Component &lt;strong&gt;in the HOC file&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;render() {
    return (
        &amp;lt;Fragment&amp;gt;
            {this.state.WrappedJSXElement}
        &amp;lt;/Fragment&amp;gt;
    )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Build the logic for our animation loop.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Every time we scroll our page, we want to scroll our JSX element(s).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If we scroll 100 clicks of our wheel, we want to make sure we &lt;strong&gt;put in a request to scroll our JSX element(s) 100 times as well&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;animate_scroll = () =&amp;gt; {
    if (!this.animation_running) {
        this.animation_running = true;
        requestAnimationFrame(this.animation_loop);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The actual animation loop...&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;animation_loop = () =&amp;gt; {
    let current_offset = window.pageYOffset;

    let difference = current_offset - this.last_offset;
    difference *= this.state.ease;

    if (Math.abs(difference) &amp;lt; 0.05) {
        this.last_offset = current_offset;
        this.animation_running = false;
        return;
    }

    this.wrappedJSXElement.current.style.top = `${this.state.start_position - this.last_offset}px`;

    this.last_offset += difference;

    requestAnimationFrame(this.animation_loop);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;We do 4 major things here (not in this order).&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Calculate the &lt;strong&gt;difference&lt;/strong&gt; between the current position of our document and the top of our page/document.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Where our page starts.&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;How we calculate the difference.&lt;/strong&gt;&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;Move our &lt;strong&gt;JSX element&lt;/strong&gt; by that &lt;strong&gt;difference&lt;/strong&gt;. (&lt;strong&gt;*the difference is multiplied by our **ease&lt;/strong&gt; to create our parallax effect ***)&lt;/li&gt;
&lt;li&gt;Request another loop for our animation.&lt;/li&gt;
&lt;li&gt;Our &lt;strong&gt;exit clause&lt;/strong&gt; for the animation loop is if the &lt;strong&gt;difference&lt;/strong&gt; is less than &lt;strong&gt;0.05&lt;/strong&gt;. Basically if the &lt;strong&gt;JSX element&lt;/strong&gt; has reached its destination.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F103606363-31350380-4ee4-11eb-95e9-c65b314b1037.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F58220766%2F103606363-31350380-4ee4-11eb-95e9-c65b314b1037.gif" alt="parallax-complete"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  We can use this logic for any type of JSX element.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  DIVs, paragraphs, spans, images...
&lt;/h4&gt;

&lt;p&gt;You can get the source files &lt;a href="https://github.com/an-object-is-a/reactjs-parallax-solution" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;center&gt;If you want a more in-depth guide, check out my full video tutorial on YouTube, &lt;strong&gt;&lt;a href="https://www.youtube.com/c/anobjectisa" rel="noopener noreferrer"&gt;An Object Is A&lt;/a&gt;&lt;/strong&gt;.&lt;/center&gt;
&lt;/h4&gt;

&lt;h3&gt;
  
  
  &lt;center&gt;React Parallax Scrolling Web Design Solution&lt;/center&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/mehs92oAuYE"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>ux</category>
    </item>
    <item>
      <title>ReactJS Pinterest Clone</title>
      <dc:creator>an-object-is-a</dc:creator>
      <pubDate>Fri, 19 Feb 2021 16:10:43 +0000</pubDate>
      <link>https://dev.to/anobjectisa/reactjs-pinterest-clone-509e</link>
      <guid>https://dev.to/anobjectisa/reactjs-pinterest-clone-509e</guid>
      <description>&lt;h4&gt;
  
  
  &lt;center&gt;Browse our &lt;a href="http://anobject.teachable.com"&gt;Teachable&lt;/a&gt; courses.&lt;/center&gt;
&lt;/h4&gt;




&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vkZomLqM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/58220766/106675182-a565d400-6582-11eb-91b4-8335391e8ee8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vkZomLqM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/58220766/106675182-a565d400-6582-11eb-91b4-8335391e8ee8.png" alt="ReactJS Pinterest Clone"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  We'll build our mock-up in steps.
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create a mock-up of a single &lt;strong&gt;Pinterest Pin&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Create a mock-up of the Pinterest "&lt;strong&gt;Add a Pin Screen&lt;/strong&gt;".&lt;/li&gt;
&lt;li&gt;Merge the above; Use the "&lt;strong&gt;Add Pin Screen&lt;/strong&gt;" to generate a single &lt;strong&gt;Pinterest Pin&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Transfer the logic of our merge in &lt;strong&gt;step 3&lt;/strong&gt; into our &lt;strong&gt;Pinterest Layout&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  "Pinterest Pin" Mock-Up
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Each Pin is made up of 3 sections.
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pin title&lt;/strong&gt; - the user won't see this; you can use this on the back-end as a way to store the Pin in a database&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pin modal&lt;/strong&gt; - this is the overlay for each card; this won't be functional for this tutorial, just cosmetic&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A6yP0vkx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/58220766/104537750-8eb60800-55e8-11eb-8e34-33d5426b7ac0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A6yP0vkx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/58220766/104537750-8eb60800-55e8-11eb-8e34-33d5426b7ac0.png" alt="pin modal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pin image&lt;/strong&gt; - the actual image the user uploads&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oQ57xFdG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/58220766/104537888-cd4bc280-55e8-11eb-8645-c1b06f363d8c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oQ57xFdG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/58220766/104537888-cd4bc280-55e8-11eb-8645-c1b06f363d8c.png" alt="pin image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Each pin has a "header" and "footer".
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8gOpfEGf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/58220766/104538216-70044100-55e9-11eb-9361-74887a3b6399.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8gOpfEGf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/58220766/104538216-70044100-55e9-11eb-9361-74887a3b6399.png" alt="head-foot pin"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div&amp;gt;
    &amp;lt;div className="card"&amp;gt;
        &amp;lt;div className="pin_title"&amp;gt;&amp;lt;/div&amp;gt;

        &amp;lt;div className="pin_modal"&amp;gt;&amp;lt;/div&amp;gt;

        &amp;lt;div className="pin_image"&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  "Add a Pin" Modal Mock-Up
&lt;/h3&gt;

&lt;h4&gt;
  
  
  The Modal is made up of 9 sections.
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Modal overlay&lt;/strong&gt; - the transparent black background&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add Pin container&lt;/strong&gt; - the main interface of the screen&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Left side&lt;/strong&gt; - the left half of our interface&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Right side&lt;/strong&gt; - the right half of our interface&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Left side Header&lt;/strong&gt; - a simple button leading to options&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Left side Body&lt;/strong&gt; - the user's image shows up here&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Left side Footer&lt;/strong&gt; - an option to upload an image from the web&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Right side Header&lt;/strong&gt; - select the Pin size (small, med, large)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Right side Body&lt;/strong&gt; - information about the Pin is entered here&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0el-96fm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/58220766/104540570-b8256280-55ed-11eb-9c6c-62513b887a89.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0el-96fm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/58220766/104540570-b8256280-55ed-11eb-9c6c-62513b887a89.png" alt="modal"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className="add_pin_modal"&amp;gt;
    &amp;lt;div className="add_pin_container"&amp;gt;
        &amp;lt;div className="side" id="left_side"&amp;gt;
            &amp;lt;div className="section1"&amp;gt;
            &amp;lt;/div&amp;gt;

            &amp;lt;div className="section2"&amp;gt;
            &amp;lt;/div&amp;gt;

            &amp;lt;div className="section3"&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;div className="side" id="right_side"&amp;gt;
            &amp;lt;div className="section1"&amp;gt;
            &amp;lt;/div&amp;gt;

            &amp;lt;div className="section2"&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Merge our Pin and "Add Pin Screen".
&lt;/h3&gt;

&lt;h4&gt;
  
  
  When we click save, we create a Pin.
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function save_pin(pinDetails, add_pin) {
    const users_data = {
        ...pinDetails,
        author: 'Jack',
        board: 'default',
        title: document.querySelector('#pin_title').value,
        description: document.querySelector('#pin_description').value,
        destination: document.querySelector('#pin_destination').value,
        pin_size: document.querySelector('#pin_size').value,
    }

    add_pin(users_data);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7LfPvyiN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/58220766/104544057-e8bcca80-55f4-11eb-8450-9f269af261c2.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7LfPvyiN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/58220766/104544057-e8bcca80-55f4-11eb-8450-9f269af261c2.gif" alt="merge"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  The Final Pinterest Board
&lt;/h3&gt;

&lt;h4&gt;
  
  
  We'll take our Pinterest Layout from a different tutorial.
&lt;/h4&gt;

&lt;p&gt;In a previous tutorial, we created the Pinterest Layout using CSS Grids.&lt;/p&gt;

&lt;p&gt;We'll import that code and use that layout as our &lt;strong&gt;pin_container&lt;/strong&gt; for this project.&lt;/p&gt;

&lt;p&gt;You can find that tutorial &lt;a href="https://youtu.be/baBvJDmziGQ"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This merge is very simple. There is no new HTML here.&lt;/p&gt;

&lt;p&gt;The major change comes in our CSS and JSX.&lt;/p&gt;

&lt;p&gt;In our CSS, we create three new class definitions; the small, medium, and large Pin options.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.card_small {
    grid-row-end: span 26;
}

.card_medium {
    grid-row-end: span 33;
}

.card_large {
    grid-row-end: span 45;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then based on which &lt;strong&gt;pin size&lt;/strong&gt; the user chooses, we add that class to our &lt;strong&gt;Pin&lt;/strong&gt; component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div className={`card card_${props.pin_size}`}&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MdluSzOz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/58220766/104661101-d2b31680-5695-11eb-9437-13407f64960d.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MdluSzOz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/58220766/104661101-d2b31680-5695-11eb-9437-13407f64960d.gif" alt="final_board"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  There is much more nuance to this project.
&lt;/h3&gt;

&lt;p&gt;You can get the source files &lt;a href="https://github.com/an-object-is-a/reactjs-pinterest-clone"&gt;here&lt;/a&gt; and you can follow the video tutorial down below.&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;center&gt;If you want a more in-depth guide, check out my full video tutorial on YouTube, &lt;strong&gt;&lt;a href="https://www.youtube.com/c/anobjectisa"&gt;An Object Is A&lt;/a&gt;&lt;/strong&gt;.&lt;/center&gt;
&lt;/h4&gt;

&lt;h3&gt;
  
  
  &lt;center&gt;ReactJS Pinterest Clone&lt;/center&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/XvmQbEziy4Y"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>react</category>
      <category>ux</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
