<?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: khoinguyenkc</title>
    <description>The latest articles on DEV Community by khoinguyenkc (@khoinguyenkc).</description>
    <link>https://dev.to/khoinguyenkc</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%2F677901%2F0171cd2d-2186-46a8-9d65-7705818e305d.png</url>
      <title>DEV Community: khoinguyenkc</title>
      <link>https://dev.to/khoinguyenkc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/khoinguyenkc"/>
    <language>en</language>
    <item>
      <title>How to: implement selected/highlighted buttons/boxes</title>
      <dc:creator>khoinguyenkc</dc:creator>
      <pubDate>Fri, 22 Oct 2021 06:51:54 +0000</pubDate>
      <link>https://dev.to/khoinguyenkc/how-to-implement-selectedhighlighted-buttonsboxes-3mfj</link>
      <guid>https://dev.to/khoinguyenkc/how-to-implement-selectedhighlighted-buttonsboxes-3mfj</guid>
      <description>&lt;p&gt;This is one of those features that seems simple in hindsight but it's actually not easy to come up with a clean solution. Here's a clean solution. &lt;/p&gt;

&lt;p&gt;Define the problem:&lt;br&gt;
Basically you have a bunch of elements, only one of them can be selected/highlighted at any given time.&lt;/p&gt;

&lt;p&gt;The key insights are &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You must have a state OUTSIDE of all of these elements &lt;/li&gt;
&lt;li&gt;And all these elements have READ access to that state&lt;/li&gt;
&lt;li&gt;All elements have WRITE access to that state&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This example uses functional component.&lt;/p&gt;

&lt;p&gt;We initialize a state like this:&lt;br&gt;
const [ clickedBox, setClickBox ] = "";&lt;/p&gt;

&lt;p&gt;Then we assign each component 2 things:&lt;/p&gt;

&lt;p&gt;&amp;lt;&lt;br&gt;
Box &lt;br&gt;
active={clickedBox == "box1"} &lt;br&gt;
onClick={ (event) =&amp;gt; setClickBox("box1")&lt;br&gt;
}&lt;br&gt;
/&amp;gt;&lt;/p&gt;

&lt;p&gt;&amp;lt;&lt;br&gt;
Box &lt;br&gt;
active={clickedBox == "box2"} &lt;br&gt;
onClick={ (event) =&amp;gt; setClickBox("box2")}&lt;br&gt;
/&amp;gt;&lt;/p&gt;

&lt;p&gt;&amp;lt;&lt;br&gt;
Box &lt;br&gt;
active={clickedBox == "box3"} &lt;br&gt;
onClick={ (event) =&amp;gt; setClickBox("box3")&lt;br&gt;
}&lt;br&gt;
/&amp;gt;&lt;/p&gt;

&lt;p&gt;We give each component an attribute named "active", its value will be true or false. &lt;br&gt;
We also give each component a callback function that gets called if the box is clicked. &lt;/p&gt;

&lt;p&gt;Inside the Box component, you can use the active attribute's true/false status to conditionally display each box as selected/highlighted.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>JWT: JsonWebToken demystified</title>
      <dc:creator>khoinguyenkc</dc:creator>
      <pubDate>Wed, 04 Aug 2021 03:00:32 +0000</pubDate>
      <link>https://dev.to/khoinguyenkc/jwt-jsonwebtoken-demystified-3dc6</link>
      <guid>https://dev.to/khoinguyenkc/jwt-jsonwebtoken-demystified-3dc6</guid>
      <description>&lt;p&gt;Warning: This is not a how-to, but a what-is. Somebody already wrote a really nice how-to here: &lt;a href="https://medium.com/@nick.hartunian/knock-jwt-auth-for-rails-api-create-react-app-6765192e295a"&gt;https://medium.com/@nick.hartunian/knock-jwt-auth-for-rails-api-create-react-app-6765192e295a&lt;/a&gt;&lt;br&gt;
But I think it can be broken down to even simpler terms. We'll learn how you can use JWT in your backend and frontend. You'll learn it's rather simple. So read this guide before following the technical set-up guide above.  &lt;/p&gt;



&lt;p&gt;WHAT'S A TOKEN?&lt;/p&gt;

&lt;p&gt;First off, before we even learn how these things work, let's get the big scary guy out of the way. We'll learn what a token is. It's not as scary as it looks. A token is just a piece of gibberish like "asdfqwertyjkl123". That's it. When we're carrying tokens it means we're carrying that piece of gibberish. And that piece of gibberish might translate to "username: brucewiththeboots, email: &lt;a href="mailto:brucespringsteen2014@gmail.com"&gt;brucespringsteen2014@gmail.com&lt;/a&gt;".  &lt;/p&gt;

&lt;p&gt;The key thing is: you and I can't understand that. Nobody does besides JWT. JWT wrote that piece of gibberish and only JWT can understand it. Ahhhh.. So it's like a secret language. The secrecy of the language makes the piece of gibberish trustworthy. Whoever composed this "asdfghqwertyjkl123" - he must've been one of us. That's how JWT thinks. So JWT believes the content of the message. &lt;/p&gt;



&lt;p&gt;Now that you have a concrete picture in your mind what a token is, hopefully you're more confident to dive in further and learn how we actually obtain such a token and what are they good for. We're gonna learn what the conveyer belt looks like. This is also not very complicated. But there will be several moving pieces. To see the big picture you need to look at them as a whole, at the same time. So my best advice to you is slow down. Slow way down. Take notes in physical paper and explain it to yourself aloud. It seems like overkill but it might just be the quickest and smoothest way to learn this. &lt;/p&gt;

&lt;p&gt;Before we begin, keep in mind these 3 things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Don't question "how is this secure?". It's not. Nothing is 100% secure. You can evaluate how secure it is later. Also, don't be curious of the mechanism that churns out these gibberish code. You can find out on your own later. We've already got too much on our plate.
&lt;/li&gt;
&lt;li&gt;Check your assumptions. You probably already have unconscious assumptions in your mind what an auth system look like. And when you learn about this new auth system, you instinctively assume this system also has these characteristics. But it might not. Which can lead to a wrong impression. So be cautious. Don't be that smug kid who thinks he knows what the teacher's going to say next. &lt;/li&gt;
&lt;li&gt;Don't take the metaphors too far. Metaphors help put a concrete image in your mind, but they're not perfect representations. If I say a lime is kind of like a lemon because they both are so and so, don't start extrapolating and thinking it's just like a lemon. Sounds silly, but we do it all the time.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Alright, time to dive in. Again, go slowly!&lt;/p&gt;

&lt;p&gt;So our app will have the backend and the frontend.&lt;/p&gt;

&lt;p&gt;We'll look at the backend first.&lt;/p&gt;

&lt;p&gt;Before we begin, remember this: the backend does not keep track of sessions. It does not "log people in". It does not keep track which user is logged in. It is much more simple than you think. Now we're finally beginning for real.&lt;/p&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EPPsd9dN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/42nz605lckjp2qyf3k7d.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EPPsd9dN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/42nz605lckjp2qyf3k7d.jpg" alt="Diagram Flow Illustration"&gt;&lt;/a&gt;&lt;br&gt;
BACKEND&lt;/p&gt;

&lt;p&gt;Our backend consists of just 2 things: the auth booth and the vending machine. &lt;/p&gt;

&lt;p&gt;1.auth booth&lt;/p&gt;

&lt;p&gt;The auth booth is kind of like a booth that you check in as you attend a conference. Then they might give you a lanyard with your name and picture on it.  Similarly, the auth booth issues a token to the front end as you login. The frontend might send data like {username: "brucewiththeboots," password: "drowssap"} to mywebsite.com/api/auth, the auth booth will verify those credentials are correct. If correct, the auth booth delivers a token like "asdfqwertyjkl123" to the frontend.&lt;/p&gt;

&lt;p&gt;The name on the lanyard is a trustworthy ID card. why? if you have a lanyard, it indicates you signed in at the booth. The guy working at the booth verified you paid your tickets and wrote your name down before giving it to you. It means the name on your lanyard  is indeed your name (If we assume the lanyard is impossible to fake and hard to steal from other someone else). Your token "asdfqwertyjkl123" is your lanyard. It's also trustworthy like the lanyard because it's impossible to fake and hard to steal. The difference is, the lanyard can be read by anybody, whereas the token is a secret language. So it's definitely not a perfect metaphor. &lt;/p&gt;

&lt;p&gt;summary: auth booth takes username and password, send token down&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;vending machine&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Our backend will be an api.  And what are api's anyway? They're essentially json vending machines. For example, the backend receives a request likes animalphotos.com/api/q?type=cat&amp;amp;amount=35. It delivers a json that includes data to 35 cat pictures.&lt;/p&gt;

&lt;p&gt;An api that uses JWT will also receive a request with the url like animalphotos.com/api/q?type=cat&amp;amp;amount=35, but that request will also include a token like "asdfghqwertyjkl123". &lt;/p&gt;

&lt;p&gt;Our backend will  relay this request to the vending machine. The vending machine read this request , translate the secret language and realize the token says it's brucewiththeboots and he wants 35 cat pictures. It can then decide whether to send him 35 cat pictures. Perhaps he already requested 300 pictures earlier and reached his daily limit. So it won't send down any cat pictures. Or perhaps he's getting more cats. &lt;/p&gt;

&lt;p&gt;Or, another example, facebook receiving a request with url facebook.com/api/q?datatype=photos&amp;amp;id=19834872323 with a token asdfghqwertyjkl123. That means brucewiththeboots wants access to a certain picture. The api can decide whether he's granted access. He might be authorized to see it or he might not. &lt;/p&gt;

&lt;p&gt;To extend the lanyard-at-a-conference metaphor: the lanyard means you're allowed to attend the lecture from the speaker. You're entitled to the free drinks and lunch offered. You're allowed to use their spotless restroom. Our vending machine also checks your token/lanyard to determine whether to serve you cat pictures. &lt;/p&gt;

&lt;p&gt;And that is basically what the vending machine does. It uses the token to find out who's requesting. It verifies if this person is authorized to receive the photos. Then it delivers accordingly. A request that doesn't come with a token will be rejected. Nothing will get delivered. &lt;/p&gt;





&lt;p&gt;FRONTEND&lt;br&gt;
I just sketched a rough picture of what the backend looks like. You only need these two parts to make it work!  From here, you can vaguely imagine the role of the frontend.&lt;/p&gt;

&lt;p&gt;Let's visualize the flow of the frontend:&lt;/p&gt;

&lt;p&gt;It simply sends up your username and password, receives a token, and then keeps that token somewhere. For example, in localStorage. And how does it keep track of a session? It does not not need to keep track of the username at all. Instead, it just keeps the token! The presence of a token indicates the user is logged in.  That token will be all that the frontend needs! &lt;/p&gt;

&lt;p&gt;Your frontend will use that token on every single fetch request to the backend. For example,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fetch( animalphotos.com/api/q?type=cat&amp;amp;amount=35, { 
        method: "GET",
        headers: {
          "Content-Type": "application/json",
          "timerange": "recent",
          Authorization: `Bearer asdfghqwertyjkl123`
        }
      }
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The backend reads the token, realizes it's brucewiththeboots, and decides if Bruce is authorized to access that particular content. &lt;/p&gt;

&lt;p&gt;As long as you stay logged in, it will keep that token. &lt;/p&gt;

&lt;p&gt;As you log out, it will delete the token. Next time you log in, it will use your username and password to get a brand new token. it won't say "asdfqwertyjkl123". it will be "oawifsdaklfsdafsd237842" for example, but that message also translates to "brucewiththeboots"&lt;/p&gt;




&lt;p&gt;And those are all the parts ! Nothing insane. But takes a while for everything to sink in. Just stare at the picture for a bit. Redraw them without looking and start teaching yourself aloud like a crazy person. And suddenly, things will click.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>JS syntax made easy: literal object vs. class syntax</title>
      <dc:creator>khoinguyenkc</dc:creator>
      <pubDate>Mon, 02 Aug 2021 21:55:35 +0000</pubDate>
      <link>https://dev.to/khoinguyenkc/js-syntax-made-easy-literal-object-vs-class-syntax-1f19</link>
      <guid>https://dev.to/khoinguyenkc/js-syntax-made-easy-literal-object-vs-class-syntax-1f19</guid>
      <description>&lt;p&gt;There are so many ways to define a method inside a class or a literal object. They are similar enough that you will mix them up. But they're not the same. Just because a class is a kind of object doesn't mean they'll behave the same! The rules aren't so intuitive. As a solution to that problem, you can copy and paste syntax that works, but it's nice to be able to understand the methods behind the madness. When you understand the rules, things get exponentially easier. I've spent some considerable time testing out what works and what doesn't, as well as the pattern behind these rules. Here I make them as easy to understand as possible for you .&lt;/p&gt;

&lt;p&gt;I outlined all the different ways you could do them. If you print them out and compare them side-to-side, you start seeing the similarities and the few key differences. They will start to not seem so intimidating.&lt;/p&gt;




&lt;p&gt;LITERAL OBJECTS&lt;br&gt;
Literal objects does not use equal signs! &lt;br&gt;
You define the method as if the method is any other property in the object, ( aka with the colon :) &lt;br&gt;
(Shorthand is an exception)&lt;/p&gt;

&lt;p&gt;Longhand, non-arrow&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let myObj = {
property1: "foo",
property2: "bar",
methodNameHere: function(arg){ return `hi ${arg}` }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Longhand, arrow&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let myObj = { 
property1: "foo",
property2: "bar",
methodNameHere: (arg) =&amp;gt; { return `hi ${arg}` }
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Shorthand, only available for non-arrow methods&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let myObj = { 
property1: "foo",
property2: "bar",
methodNameHere(arg) { return `hi ${arg}` } 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To test:&lt;br&gt;
Define the object with one of the object syntaxes above&lt;br&gt;
Then,&lt;br&gt;
myObj.methodNameHere("Steve")&lt;/p&gt;



&lt;p&gt;CLASS&lt;br&gt;
Class does not use any colon, instead you will be using the equal sign =&lt;br&gt;
There are two ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Inside the constructor function, or &lt;/li&gt;
&lt;li&gt;Outside the constructor,  a modern JS feature, the most familiar way we do methods &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Inside constructor, Long hand, non-arrow&lt;br&gt;
&lt;/p&gt;

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

constructor() {
        this.property1 = "foo";
        this.property2 = "bar";
        this.methodNameHere = function(arg) { return `hi ${arg}` } 
    }
}

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

&lt;/div&gt;



&lt;p&gt;Inside constructor, Long hand, arrow&lt;br&gt;
&lt;/p&gt;

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

    constructor() { 
    this.property1 = "foo";
    this.property2 = "bar";
    this. methodNameHere = (arg) =&amp;gt; { return `hi ${arg}`}
    }
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside constructor approach has no shorthand, it seems.&lt;/p&gt;

&lt;p&gt;Outside constructor, Long hand, non-arrow&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Classnamehere {
    property1 = "foo";
    property2 = "bar";
    methodNameHere = function(arg) { return `hi ${arg}`} 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Outside constructor, Long hand, arrow&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Classnamehere {
    property1 = "foo";
    property2 = "bar";
    methodNameHere = (arg) =&amp;gt; { return `hi ${arg}`} 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Outside constructor, Shorthand , for non-arrow only&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Classnamehere {
    property1 = "foo";
    property2 = "bar";
    methodNameHere(arg)  { return `hi ${arg}`} 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To test:&lt;br&gt;
Define the class with one of the class syntaxes above&lt;br&gt;
Then,&lt;br&gt;
Let aClassInstance = new Classnamehere()&lt;br&gt;
Then,&lt;br&gt;
aClassInstance.methodNameHere("Steve")&lt;br&gt;
Repeat these 3 steps in this exact order every time you try a new class syntax. don't skip.&lt;/p&gt;




&lt;p&gt;If you could only remember 3 things:&lt;br&gt;
Literal objects use colon, &lt;br&gt;
Classes use equal sign&lt;br&gt;
Shorthand uses neither and does not allow arrow functions.&lt;/p&gt;

&lt;p&gt;A note on React class-based components:&lt;br&gt;
It seems react class syntax works like regular class syntax when it comes to what is VALID syntax that wont cause error&lt;br&gt;
BUT, the "this" variable behaves differently. That's why people tend to use arrow functions to define methods in React class-based components. (Except for constructor, render, lifecycle methods, etc...)&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>syntax</category>
      <category>guide</category>
      <category>howto</category>
    </item>
    <item>
      <title>React project - 4 lessons learned</title>
      <dc:creator>khoinguyenkc</dc:creator>
      <pubDate>Sun, 01 Aug 2021 06:32:25 +0000</pubDate>
      <link>https://dev.to/khoinguyenkc/react-project-4-lessons-learned-30n0</link>
      <guid>https://dev.to/khoinguyenkc/react-project-4-lessons-learned-30n0</guid>
      <description>&lt;p&gt;These are the 4 things that I would have done differently. I would have... &lt;/p&gt;

&lt;p&gt;[1] ...built out the routes first.&lt;/p&gt;

&lt;p&gt;It is true that generally you want to get off the ground fast, and build your app feature by feature, but routes might just be an exception. Since they are confusing, unless you are deeply familiar, you should try to get them done all at once asap. &lt;/p&gt;




&lt;p&gt;[2] ...set up authentication first. &lt;/p&gt;

&lt;p&gt;Why? Without authentication, you'll be building your app without login guards etc... Building your app without that check is very smooth. It gives a false sense of progress. Once you have authentication, suddenly things start breaking left and right and you're in chaos trying to contain the damage. It's like a dam broke and water flooded in. You suddenly have to postpone everything and work out these problems, fixing one bug after another, trying to determine which line of code caused the situation. Figuring one out doesn't guarantee you figured the rest out! &lt;br&gt;
Building an app is is generally an iterative process, but for certain things you have to do it right from the get go, since other things depend on it. This might just be one of these things. &lt;br&gt;
So build out authentication and write your code in a way that accounts for both states of having access and no access early on.. Why? If you just assume the user always has access, then you'll have to fix that code, and not merely adding more code to address the second situation. &lt;/p&gt;




&lt;p&gt;[3] ...learned the conventional way of doing features. &lt;br&gt;
As I mentioned above, authentication is complicated. There are many decisions to make, many of them will work, but how likely are that they work WELL? Login is so universal that theres no excuse not to really master its best practices.&lt;/p&gt;

&lt;p&gt;Learning coding patterns and best practices cannot be overemphasized. As a naive deer in the headlight, I liked to challenge myself to write my code without much reference and only look up solutions when stuck. I didn't want to look at similar apps' code. They seem like copying and cheating. But in retrospect, this is a mistake. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a) trying to reinvent the wheel on anything other than a mini-project is not appropriate. It introduces too much risk of delay and overwhelm. Even if it works, it might be a very bad way that causes more headaches down the road, and possibly dead ends.&lt;/li&gt;
&lt;li&gt;b) best practices and conventional practices are good in ways you don't completely understand. It's beyond your ability to understand for now. They help prevent the headaches and dead-ends I just mentioned above. Thus, as a newbie, you should trust them more than your own solution. It is critical that you do research on similar apps and stick to these conventions. This might seem like you are not learning much, your project won't be a copy and paste exercise. There will be slight differences where you have to use your brain. There will be plenty of learning along the way! &lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;[4] ...controlled my ambitions &lt;br&gt;
WHY&lt;br&gt;
The way to accomplish any big goal is to break it down to digestible chunks. If your goal is to be a good programmer, what are the digestible chunks? You should aim to a) build projects that are, not too easy, not too hard b) build them frequently. &lt;br&gt;
I believe consistent efforts like this are more sustainable than occasional heroic bursts of hustles that ultimately induce burnout.&lt;/p&gt;

&lt;p&gt;HOW&lt;br&gt;
Big projects is a time ripe for overwhelm and time delay. All projects have these risks, but you should aim to minimize them. Thus, at the level of building a big complicated app, you want to be ultra-conservative with, well, essentially everything. Don't reach for the moon, as poetic as it sounds. You don't want to fall in love with a house without considering your budget. Your budget in this case is time and ability. &lt;/p&gt;

&lt;p&gt;Specifically, what should you do instead? Do something you already know how to do. And follow best practices. If all you got is a hammer, find some nails. Make the app fit your abilities. Don't do a project that you know explicitly has so and so features that you have no idea how to do yet. &lt;/p&gt;




&lt;p&gt;Summary&lt;br&gt;
Don't be wild. Have a process. Stick to it. Do things in the right order. Show restraint.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
