<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="xx">
    <title></title>
    <link rel="self" type="application/atom+xml" href="https://juanmanzanero.com/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://juanmanzanero.com"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-06-30T00:00:00+00:00</updated>
    <id>https://juanmanzanero.com/atom.xml</id>
    <entry xml:lang="xx">
        <title>Survival Handbook Against the Massive Surveillance</title>
        <published>2026-06-30T00:00:00+00:00</published>
        <updated>2026-06-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Juan Manzanero
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://juanmanzanero.com/blog/survival-handbook-against-the-massive-surveillance/"/>
        <id>https://juanmanzanero.com/blog/survival-handbook-against-the-massive-surveillance/</id>
        
        <content type="html" xml:base="https://juanmanzanero.com/blog/survival-handbook-against-the-massive-surveillance/">&lt;h2 id=&quot;this-cannot-be-stopped&quot;&gt;This Cannot Be Stopped&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: adapted from the original post for people from México&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;It’s not that I’m being pessimistic, but there are different countries that are
focused on being able to identify us by location, whether through using Internet
services or being on the street.&lt;&#x2F;p&gt;
&lt;p&gt;It doesn’t matter who governs, or if we vote for someone who claims to oppose
it, in the end, one way or another, restrictions on these services will be
implemented, since knowing every movement of people is what makes government so
powerful.&lt;&#x2F;p&gt;
&lt;p&gt;Let this be clear: the taxes they steal from us are not used to improve our
quality of life, but to take away our freedom.&lt;&#x2F;p&gt;
&lt;p&gt;With that clear, let’s look at the options.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;mobile-phone&quot;&gt;Mobile Phone&lt;&#x2F;h2&gt;
&lt;p&gt;Google Pixels are the best mobile phones in terms of security, so much so that
it’s the only hardware compatible with GrapheneOS, the most secure and private
Operating System based on Android available for pocket devices.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;mobile-data-access&quot;&gt;Mobile Data Access&lt;&#x2F;h2&gt;
&lt;p&gt;When you don’t have Internet access through Wi-Fi, we use mobile data to connect
to street antennas, paying our phone number provider.&lt;&#x2F;p&gt;
&lt;p&gt;This is usually tied to a SIM (physical chip), but due to its restrictions,
&lt;strong&gt;the solution is an E-SIM&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;An E-SIM allows you to connect to the mobile data network, but not all providers
give you a number to receive or make SMS or calls (I’ll provide solutions for
this later).&lt;&#x2F;p&gt;
&lt;p&gt;I recommend using a provider that at least offers the option to pay with
Monero&#x2F;XMR, to protect your identity with respect to the service you’ll use.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;silent.link&#x2F;&quot;&gt;silent.link&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;communications&quot;&gt;Communications&lt;&#x2F;h2&gt;
&lt;p&gt;SMS and calls using the default apps on mobile phones &lt;em&gt;are not secure&lt;&#x2F;em&gt;, since
they lack encryption.&lt;&#x2F;p&gt;
&lt;p&gt;Your provider can read and listen to your conversations (and believe me, they do
it without discrimination).&lt;&#x2F;p&gt;
&lt;p&gt;Use an app that has end-to-end (E2E) encryption.&lt;&#x2F;p&gt;
&lt;p&gt;It’s also important that it allows you to use it without needing a phone number,
which is why I rule out WhatsApp, Telegram, or Signal.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;simplex.chat&#x2F;es&quot;&gt;SimpleX Chat&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If you have no alternative and must use WhatsApp, Telegram, or Signal, use a
service that allows you to purchase SMS or already-created accounts.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.smspool.net&#x2F;&quot;&gt;SMSPool&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;buynumber.io&#x2F;&quot;&gt;buynumber.io&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;finance&quot;&gt;Finance&lt;&#x2F;h2&gt;
&lt;p&gt;All banks make it mandatory to have a phone number capable of receiving SMS for
authentication tokens, supposedly for security, but in reality it’s so the
government can coerce you if necessary.&lt;&#x2F;p&gt;
&lt;p&gt;There’s no way to avoid needing a SIM to have access to banks, but you can opt
for alternatives.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Cash money&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.getmonero.org&quot;&gt;Monero&#x2F;XMR&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Cash for in-person transactions or physical stores, and Monero for Internet
transactions.&lt;&#x2F;p&gt;
&lt;p&gt;Ideally, of course, is to always use Monero, and there are even businesses that
accept it in person, since it’s a currency completely outside the traditional
system.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;additional-resources&quot;&gt;Additional Resources&lt;&#x2F;h2&gt;
&lt;p&gt;Search for more services that respect your privacy and data.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;monerica.com&quot;&gt;Monerica&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;kycnot.me&quot;&gt;kycnot.me&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="xx">
        <title>Privacy Must Be Taken More Seriously</title>
        <published>2026-04-23T00:00:00+00:00</published>
        <updated>2026-04-23T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Juan Manzanero
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://juanmanzanero.com/blog/privacy-must-be-taken-more-seriously/"/>
        <id>https://juanmanzanero.com/blog/privacy-must-be-taken-more-seriously/</id>
        
        <content type="html" xml:base="https://juanmanzanero.com/blog/privacy-must-be-taken-more-seriously/">&lt;p&gt;Privacy is a fundamental pillar for free speech.&lt;&#x2F;p&gt;
&lt;p&gt;You might found state &lt;em&gt;propaganda&lt;&#x2F;em&gt; on social media, about how “anonymous
individuals&#x2F;groups” are doing crimes, hacking, etc.&lt;&#x2F;p&gt;
&lt;p&gt;Well, as I said, that’s pure &lt;strong&gt;propaganda&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Governments wants to convince you that privacy or anonymity equals crime.&lt;&#x2F;p&gt;
&lt;p&gt;I shouldn’t tell you, but that’s just stupid thinking.&lt;&#x2F;p&gt;
&lt;p&gt;Not because a criminal uses Tor or Monero it means that everyone which uses the
mentioned technologies are criminals.&lt;&#x2F;p&gt;
&lt;p&gt;It’s like saying that if a criminal uses a spoon then everyone who uses a spoon
is also a criminal, yes; that’s how stupid it sounds.&lt;&#x2F;p&gt;
&lt;p&gt;Privacy is a basic right, it guarantees that those in power can be questioned
without them taking down their criticizers, and this is more required as the
censorship keeps incrementing.&lt;&#x2F;p&gt;
&lt;p&gt;Today they might censor bad words, tomorrow memes of the idiot in a chair who
people calls president, in 1 month you can’t talk about anything but good things
about the government.&lt;&#x2F;p&gt;
&lt;p&gt;But as freedom, everyone wants it, but not everyone is going to fight for it, at
least in these days.&lt;&#x2F;p&gt;
&lt;p&gt;Learn about &lt;em&gt;PGP&lt;&#x2F;em&gt;, &lt;em&gt;Tor&lt;&#x2F;em&gt;, &lt;em&gt;Monero&lt;&#x2F;em&gt;, and any other technology that protects you.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="xx">
        <title>Website migrated to Astro</title>
        <published>2024-06-26T00:00:00+00:00</published>
        <updated>2024-06-26T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Juan Manzanero
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://juanmanzanero.com/blog/website-migrated-to-astro/"/>
        <id>https://juanmanzanero.com/blog/website-migrated-to-astro/</id>
        
        <content type="html" xml:base="https://juanmanzanero.com/blog/website-migrated-to-astro/">&lt;p&gt;So yeah, I proved this tool for building static websites, as Vercel has been taking weird decisions about the direction of the development of Next.js.&lt;&#x2F;p&gt;
&lt;p&gt;That, and I realized that I just need a full static website, no need of SSR.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;static-is-the-way-to-go&quot;&gt;Static is the way to go&lt;&#x2F;h2&gt;
&lt;p&gt;At the start of the Internet, websites were just plain HTML, CSS and JS, no need of Single Page Application, Server Side Rendering, etc.&lt;&#x2F;p&gt;
&lt;p&gt;Of course, there are many websites that need these rendering strategies, but for a website like this, just static is better.&lt;&#x2F;p&gt;
&lt;p&gt;Less time building, fast load, cheaper hosting, less JavaScript on the browser.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-cool-thing-about-astro&quot;&gt;The cool thing about Astro&lt;&#x2F;h2&gt;
&lt;p&gt;You can use any component from any framework.&lt;&#x2F;p&gt;
&lt;p&gt;You can use React, Angular, Vue, Svelte components in the same project, as Astro compiles them as HTML&#x2F;CSS&#x2F;JS.&lt;&#x2F;p&gt;
&lt;p&gt;Not only that, but you can use Astro as Next.js too, with the &lt;em&gt;hybrid&lt;&#x2F;em&gt; rendering strategy, you can specify which pages you want to be Server Side Rendered. Obviously, if you’re going this way, you must host your project on a server.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;in-other-things&quot;&gt;In other things…&lt;&#x2F;h3&gt;
&lt;p&gt;I’m planning on making videos for YouTube, talking about topics that I think we need more in the Hispanic community, topics like cybersecurity, privacy, the current status of technology, and more.&lt;&#x2F;p&gt;
&lt;p&gt;There are many YT channels in English talking about that, so that’s why I’m thinking of doing it in Spanish.&lt;&#x2F;p&gt;
&lt;p&gt;I need to improve the banners of these posts, though.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="xx">
        <title>A Better Way for Consuming Content</title>
        <published>2024-04-11T00:00:00+00:00</published>
        <updated>2024-04-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Juan Manzanero
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://juanmanzanero.com/blog/a-better-way-for-consuming-content/"/>
        <id>https://juanmanzanero.com/blog/a-better-way-for-consuming-content/</id>
        
        <content type="html" xml:base="https://juanmanzanero.com/blog/a-better-way-for-consuming-content/">&lt;h2 id=&quot;algorithms-that-dictates-what-you-see&quot;&gt;Algorithms that Dictates What You See&lt;&#x2F;h2&gt;
&lt;p&gt;Social media are not designed for showing you the latest and most important
news, but for showing you content dictated by an algorithm.&lt;&#x2F;p&gt;
&lt;p&gt;And this content is normally viral, and viral doesn’t mean interesting.&lt;&#x2F;p&gt;
&lt;p&gt;Usually this algorithm prioritizes content that get you angry.&lt;&#x2F;p&gt;
&lt;p&gt;Content that promotes negativity gets more clicks rather than those whose
promotes positivity.&lt;&#x2F;p&gt;
&lt;p&gt;That’s the reason why Twitter and Facebook are full of stupid and irrelevant
posts (usually).&lt;&#x2F;p&gt;
&lt;p&gt;Of course, it’s really cool when the algorithm shows you content that you like,
discovering new people and pages, but that’s not usual.&lt;&#x2F;p&gt;
&lt;p&gt;Without mentioning the annoying ads and more stuff that wants you to click it.&lt;&#x2F;p&gt;
&lt;p&gt;Meta (previously Facebook) knows about this, and encourages it in their products
like Instagram and Facebook, and the same for Twitter.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-solution-news-aggregators-rss&quot;&gt;The Solution: News Aggregators (RSS)&lt;&#x2F;h2&gt;
&lt;p&gt;RSS is an acronym for “Really Simple Syndication”.&lt;&#x2F;p&gt;
&lt;p&gt;It’s an ancient technology, not promoted so much by companies.&lt;&#x2F;p&gt;
&lt;p&gt;That’s because when you read a post in an RSS Reader, you don’t need to visit
the website, and the website can’t show advertisements using Google Ads (for
example). You don’t generate traffic; your visits don’t count, at least not if
you don’t open the post link in your RSS Reader.&lt;&#x2F;p&gt;
&lt;p&gt;The good thing is that almost every RSS Reader shows you content sorted by date,
not by a creepy algorithm that wants you to be mad.&lt;&#x2F;p&gt;
&lt;p&gt;For my website I use a Node.js script that takes the &lt;code&gt;.mdx&lt;&#x2F;code&gt; files inside &lt;code&gt;content&#x2F;blog&lt;&#x2F;code&gt; and
&lt;code&gt;content&#x2F;portfolio&lt;&#x2F;code&gt;, then generates the RSS Items, those with the &lt;code&gt;rss: true&lt;&#x2F;code&gt; in
the metadata.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-to-use-an-rss-reader&quot;&gt;How to Use an RSS Reader&lt;&#x2F;h2&gt;
&lt;p&gt;First, you should download one.&lt;&#x2F;p&gt;
&lt;p&gt;There are many options:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;netnewswire.com&#x2F;&quot;&gt;NetNewsWire&lt;&#x2F;a&gt;: a native RSS Reader for macOS and
iOS, free and Open Source, my favorite option as an Apple &lt;del&gt;Sinner&lt;&#x2F;del&gt; user&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;apps.kde.org&#x2F;akregator&quot;&gt;Akregator&lt;&#x2F;a&gt;: from the KDE project for Linux&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;play.google.com&#x2F;store&#x2F;apps&#x2F;details?id=com.nononsenseapps.feeder.play&quot;&gt;Feeder&lt;&#x2F;a&gt;:
for Android&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ravenreader.app&#x2F;&quot;&gt;Raven Reader&lt;&#x2F;a&gt;: desktop cross-platform&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;adding-feeds&quot;&gt;Adding Feeds&lt;&#x2F;h3&gt;
&lt;p&gt;Now you need to search for the RSS URL on your favorite website, like
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;juanmanzanero.com&#x2F;feed.xml&quot;&gt;this one&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;https:&#x2F;&#x2F;juanmanzanero.com&#x2F;rss.xml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you open it, you’ll get a weird page with code similar to HTML.&lt;&#x2F;p&gt;
&lt;p&gt;Once copied, go to your RSS feed and search for “Add feed” or something similar,
and paste the link, and you’re done! Now you’ll get the latest posts from my
website.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;adding-social-media-feeds&quot;&gt;Adding Social Media Feeds&lt;&#x2F;h3&gt;
&lt;p&gt;You can even add feeds from sites like Reddit or YouTube.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;reddit&quot;&gt;Reddit&lt;&#x2F;h4&gt;
&lt;p&gt;Just change &lt;code&gt;[SUBREDDIT]&lt;&#x2F;code&gt; for the name of your subreddit to add:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;https:&#x2F;&#x2F;reddit.com&#x2F;r&#x2F;[SUBREDDIT]&#x2F;new&#x2F;.rss&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h4 id=&quot;youtube&quot;&gt;YouTube&lt;&#x2F;h4&gt;
&lt;p&gt;Go to the channel to add, then go to the &lt;strong&gt;About&lt;&#x2F;strong&gt; tab, then click on &lt;strong&gt;Share &amp;gt;
Copy channel ID&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now just change &lt;code&gt;[CHANNEL ID]&lt;&#x2F;code&gt; for the copied one:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;https:&#x2F;&#x2F;youtube.com&#x2F;feeds&#x2F;videos.xml?channel_id=[CHANNEL ID]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;my-favorite-feeds&quot;&gt;My Favorite Feeds&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;juanmanzanero.com&#x2F;feed.xml&quot;&gt;juanmanzanero.com (obviously!)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;apod.com&#x2F;feed.rss&quot;&gt;Astronomic Picture of the Day (apod)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;feeds2.feedburner.com&#x2F;EarthSciencePictureoftheDay&quot;&gt;Earth Science Picture of the Day (epod)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ericmurphy.xyz&#x2F;index.xml&quot;&gt;Erick Murphy (cool guy)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;lukesmith.xyz&#x2F;index.xml&quot;&gt;Luke Smith&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;more-about-rss&quot;&gt;More About RSS&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.privacytools.io&#x2F;privacy-rss-feed-readers&quot;&gt;Privacy Tools - RSS Feed Readers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.privacyguides.org&#x2F;en&#x2F;news-aggregators&#x2F;&quot;&gt;Privacy Guides - News Aggregators&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="xx">
        <title>Build a fullstack web app</title>
        <published>2024-01-18T00:00:00+00:00</published>
        <updated>2024-01-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Juan Manzanero
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://juanmanzanero.com/blog/build-a-fullstack-app/"/>
        <id>https://juanmanzanero.com/blog/build-a-fullstack-app/</id>
        
        <content type="html" xml:base="https://juanmanzanero.com/blog/build-a-fullstack-app/">&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;juanmanzanero-com&#x2F;fullstack-app&quot;&gt;GitHub repo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;1-introduction&quot;&gt;1. Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;In this tutorial, we will develop a fullstack web app with the following tech
stack:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;nextjs.org&#x2F;&quot;&gt;Next.js&lt;&#x2F;a&gt; as meta-framework&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;tailwindcss.com&#x2F;&quot;&gt;TailwindCSS&lt;&#x2F;a&gt; for styling&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ui.shadcn.com&#x2F;&quot;&gt;shadcn&#x2F;ui&lt;&#x2F;a&gt; for UI components&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.prisma.io&#x2F;&quot;&gt;Prisma&lt;&#x2F;a&gt; as ORM&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.postgresql.org&#x2F;&quot;&gt;PostgreSQL&lt;&#x2F;a&gt; as database&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;authjs.dev&#x2F;&quot;&gt;Auth.js&lt;&#x2F;a&gt; for authentication&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.docker.com&#x2F;&quot;&gt;Docker&lt;&#x2F;a&gt; for creating an intance of a PostgreSQL
database locally&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;We’ll learn some of the fundamentals of this tech stack, like using &lt;strong&gt;server
components&lt;&#x2F;strong&gt; in Next.js, or creating &lt;strong&gt;API endpoints&lt;&#x2F;strong&gt; using the &lt;strong&gt;app router&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2-initial-setup&quot;&gt;2. Initial setup&lt;&#x2F;h2&gt;
&lt;p&gt;Let’s start creating a new Next.js project, in your &lt;strong&gt;terminal&lt;&#x2F;strong&gt; run:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-bash-title=&quot;&quot;Terminal&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;npx create-next-app@latest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Make sure to mark &lt;strong&gt;Yes&lt;&#x2F;strong&gt; the following options:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Would you like to use &lt;strong&gt;TypeScript&lt;&#x2F;strong&gt;?&lt;&#x2F;li&gt;
&lt;li&gt;Would you like to use &lt;strong&gt;ESLint&lt;&#x2F;strong&gt;?&lt;&#x2F;li&gt;
&lt;li&gt;Would you like to use &lt;strong&gt;Tailwind CSS&lt;&#x2F;strong&gt;?&lt;&#x2F;li&gt;
&lt;li&gt;Would you like to use &lt;strong&gt;‘src&#x2F;’ directory&lt;&#x2F;strong&gt;?&lt;&#x2F;li&gt;
&lt;li&gt;Would you like to use &lt;strong&gt;App Router&lt;&#x2F;strong&gt;? (recommended)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-bash-title=&quot;&quot;Terminal&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; What is your project named? fullstack-app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; Would you like to use TypeScript? No &#x2F; Yes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; Would you like to use ESLint? No &#x2F; Yes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; Would you like to use Tailwind CSS? No &#x2F; Yes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; Would you like to use `src&#x2F;` directory? No &#x2F; Yes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; Would you like to use App Router? (recommended) No &#x2F; Yes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; Would you like to customize the default import alias (@&#x2F;*)? No &#x2F; Yes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; What import alias would you like configured? @&#x2F;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Wait until the dependencies installation is completed, then access to the
project directory:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-bash-title=&quot;&quot;Terminal&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cd fullstack-app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Open your code editor of your preference.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-1-install-shadcn-ui&quot;&gt;2.1 Install shadcn&#x2F;ui&lt;&#x2F;h3&gt;
&lt;p&gt;This components will help us a lot building the &lt;strong&gt;UI&lt;&#x2F;strong&gt; along with TailwindCSS.&lt;&#x2F;p&gt;
&lt;p&gt;First, initialize shadcn&#x2F;ui:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-bash-title=&quot;&quot;Terminal&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;npx shadcn-ui@latest init&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Make sure to config shadcn&#x2F;ui according your project configuration.&lt;&#x2F;p&gt;
&lt;p&gt;You can check the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ui.shadcn.com&#x2F;docs&quot;&gt;shadcn&#x2F;ui docs&lt;&#x2F;a&gt; for every
component that you could need, each components is installed individually.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-2-create-a-db-using-docker&quot;&gt;2.2 Create a db using Docker&lt;&#x2F;h3&gt;
&lt;p&gt;Make sure to have &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.docker.com&#x2F;&quot;&gt;Docker&lt;&#x2F;a&gt; installed in your machine.&lt;&#x2F;p&gt;
&lt;p&gt;First you need to pull a PostgreSQL image from Docker Hub:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-bash-title=&quot;&quot;Terminal&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;docker pull postgres&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, create a container with the image:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-bash-title=&quot;&quot;Terminal&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;docker run --name my-postgres -e POSTGRES_PASSWORD=password -p 5432:5432 -d postgres&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;2-3-install-prisma&quot;&gt;2.3 Install Prisma&lt;&#x2F;h3&gt;
&lt;p&gt;Install Prisma using your dependency manager, in this case &lt;strong&gt;npm&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-bash-title=&quot;&quot;Terminal&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;npm install prisma -D&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now initialize Prisma:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-bash-title=&quot;&quot;Terminal&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;npx prisma init&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A new &lt;code&gt;.&#x2F;prisma&lt;&#x2F;code&gt; direcotry will be created in the root of your project, with a
schema.prisma file.&lt;&#x2F;p&gt;
&lt;p&gt;You’ll create your schemas in this file.&lt;&#x2F;p&gt;
&lt;p&gt;Add this model as an example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-prisma-title=&quot;&quot;prisma&#x2F;schema.prisma&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;model User {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  id        Int      @id @default(autoincrement())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  createdAt DateTime @default(now())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  email     String   @unique&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  name      String?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Update your &lt;code&gt;.env&lt;&#x2F;code&gt; file with the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-env-title=&quot;&quot;.env&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;DATABASE_URL=&amp;quot;postgresql:&#x2F;&#x2F;postgres:password@localhost:5432&#x2F;postgres?schema=public&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In the URL is your username (by default is postgres), your password (in this
case password), the host (by default is localhost), the port (by default is
5432), the database name (by default is postgres) and the schema (by default is
public).&lt;&#x2F;p&gt;
&lt;p&gt;Create your first migration to test if Prisma can connect to your local
database:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-bash-title=&quot;&quot;Terminal&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;npx prisma migrate dev --name init&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If everything is ok, you’ll see a new &#x2F;migrations directory with a new file
inside.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you have an error, make sure you can connect to your local DB. Delete, and
create the container again if necessary.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;2-4-config-auth-js&quot;&gt;2.4 Config Auth.js&lt;&#x2F;h3&gt;
&lt;p&gt;Add this models to your &lt;strong&gt;prisma schema&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-prisma-title=&quot;&quot;prisma&#x2F;schema.prisma&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;model Account {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  id                String  @id @default(cuid())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  userId            String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  type              String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  provider          String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  providerAccountId String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  refresh_token     String? @db.Text&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  access_token      String? @db.Text&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  expires_at        Int?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  token_type        String?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  scope             String?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  id_token          String? @db.Text&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  session_state     String?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  user User @relation(fields: [userId], references: [id], onDelete: Cascade)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  @@unique([provider, providerAccountId])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;model Session {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  id           String   @id @default(cuid())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  sessionToken String   @unique&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  userId       String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  expires      DateTime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  user         User     @relation(fields: [userId], references: [id], onDelete: Cascade)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;model User {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  id            String    @id @default(cuid())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  name          String?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  email         String?   @unique&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  emailVerified DateTime?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  image         String?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  accounts      Account[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  sessions      Session[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;model VerificationToken {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  identifier String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  token      String   @unique&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  expires    DateTime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  @@unique([identifier, token])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;These models are for &lt;strong&gt;Auth.js&lt;&#x2F;strong&gt;, now we can install it with the prisma adapter:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-bash-title=&quot;&quot;Terminal&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;npm install @prisma&#x2F;client @auth&#x2F;prisma-adapter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Instal nodemailer too, as we’ll use magic links for authentication:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-bash-title=&quot;&quot;Terminal&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;npm install nodemailer -D&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now create a &lt;code&gt;src&#x2F;utils&#x2F;db.ts&lt;&#x2F;code&gt; and initialize &lt;strong&gt;prisma&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-ts-title=&quot;&quot;src&#x2F;utils&#x2F;db.ts&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { PrismaClient } from &amp;quot;@prisma&#x2F;client&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;const prismaClientSingleton = () =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  return new PrismaClient();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;declare global {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  var prisma: undefined | ReturnType&amp;lt;typeof prismaClientSingleton&amp;gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;const prisma = globalThis.prisma ?? prismaClientSingleton();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export default prisma;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;if (process.env.NODE_ENV !== &amp;quot;production&amp;quot;) globalThis.prisma = prisma;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, create a &lt;code&gt;src&#x2F;utils&#x2F;auth.ts&lt;&#x2F;code&gt; file to config &lt;strong&gt;Auth.js&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-ts-title=&quot;&quot;src&#x2F;utils&#x2F;auth.ts&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import type { NextAuthOptions } from &amp;quot;next-auth&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { PrismaAdapter } from &amp;quot;@auth&#x2F;prisma-adapter&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import EmailProvider from &amp;quot;next-auth&#x2F;providers&#x2F;email&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import prisma from &amp;quot;@&#x2F;libs&#x2F;db&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { Adapter } from &amp;quot;next-auth&#x2F;adapters&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export const authOptions = {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  adapter: PrismaAdapter(prisma) as Adapter,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  providers: [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    EmailProvider({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      server: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        host: process.env.EMAIL_SERVER_HOST,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        port: process.env.EMAIL_SERVER_PORT,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        auth: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          user: process.env.EMAIL_SERVER_USER,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          pass: process.env.EMAIL_SERVER_PASSWORD,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      from: process.env.EMAIL_FROM,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  callbacks: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    session: async ({ session, user }) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      return {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ...session,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        user: user,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;} satisfies NextAuthOptions;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This config is for using an email provider, for this project we’ll use
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;resend.com&#x2F;&quot;&gt;Resend&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Create an account and get the next credentials in your .env file:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;EMAIL_SERVER_HOST: smtp.resend.com&lt;&#x2F;li&gt;
&lt;li&gt;EMAIL_SERVER_PORT: 465&lt;&#x2F;li&gt;
&lt;li&gt;EMAIL_SERVER_USER: resend&lt;&#x2F;li&gt;
&lt;li&gt;EMAIL_FROM: onboarding@resend(dot)dev&lt;&#x2F;li&gt;
&lt;li&gt;EMAIL_SERVER_PASSWORD: yor api key&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Now, create a &lt;code&gt;src&#x2F;app&#x2F;api&#x2F;auth&#x2F;[...nextauth]&#x2F;route.ts&lt;&#x2F;code&gt; file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-ts-title=&quot;&quot;src&#x2F;app&#x2F;api&#x2F;auth&#x2F;[...nextauth]&#x2F;route.ts&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { authOptions } from &amp;quot;@&#x2F;libs&#x2F;auth&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import NextAuth from &amp;quot;next-auth&#x2F;next&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;const handler = NextAuth(authOptions);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export { handler as GET, handler as POST };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This file is for handling the authentication in our app.&lt;&#x2F;p&gt;
&lt;p&gt;You can now authenticate users with a magic link sent by email.&lt;&#x2F;p&gt;
&lt;p&gt;Create a &lt;code&gt;src&#x2F;app&#x2F;auth&#x2F;signin-form.tsx&lt;&#x2F;code&gt; file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-tsx-title=&quot;&quot;src&#x2F;app&#x2F;auth&#x2F;signin-form.tsx&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot;use client&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { useState } from &amp;quot;react&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { signIn } from &amp;quot;next-auth&#x2F;react&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export default function SigninForm() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const [email, setEmail] = useState&amp;lt;null | string&amp;gt;(null);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  async function handleSubmit() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    await signIn(&amp;quot;email&amp;quot;, {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      email,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      callbackUrl: `${window.location.origin}`,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  return (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;form className=&amp;quot;mt-5 space-y-4&amp;quot; action={handleSubmit}&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;section className=&amp;quot;flex flex-col gap-2&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;label htmlFor=&amp;quot;email&amp;quot;&amp;gt;Email&amp;lt;&#x2F;label&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;input&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          id=&amp;quot;email&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          type=&amp;quot;email&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          name=&amp;quot;email&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          onChange={(e) =&amp;gt; setEmail(e.target.value)}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          className=&amp;quot;w-max p-1 border border-slate-400&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&#x2F;section&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;button type=&amp;quot;submit&amp;quot;&amp;gt;Sign in&amp;lt;&#x2F;button&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&#x2F;form&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Import it to your &lt;code&gt;src&#x2F;app&#x2F;auth&#x2F;page.tsx&lt;&#x2F;code&gt; file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-tsx-title=&quot;&quot;src&#x2F;app&#x2F;auth&#x2F;page.tsx&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { authOptions } from &amp;quot;@&#x2F;libs&#x2F;auth&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { getServerSession } from &amp;quot;next-auth&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { redirect } from &amp;quot;next&#x2F;navigation&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import SigninForm from &amp;quot;.&#x2F;form&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export default async function Signin() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const session = await getServerSession(authOptions);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  if (session) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    return redirect(&amp;quot;&#x2F;&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  return (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;h1&amp;gt;Sign in&amp;lt;&#x2F;h1&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;SigninForm &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As you can see, you can redirect users if they’re not authenticated getting the
session with &lt;strong&gt;getServerSession&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;3-improve-your-ui&quot;&gt;3. Improve your UI&lt;&#x2F;h2&gt;
&lt;p&gt;Let’s create a short posts like app.&lt;&#x2F;p&gt;
&lt;p&gt;First, add some shadcn&#x2F;ui components and update your components, we’ll create
new components too:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-bash-title=&quot;&quot;Terminal&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;npx shadcn-ui@latest add button&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-bash-title=&quot;&quot;Terminal&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;npx shadcn-ui@latest add dialog&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-bash-title=&quot;&quot;Terminal&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;npx shadcn-ui@latest add input&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-bash-title=&quot;&quot;Terminal&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;npx shadcn-ui@latest add textarea&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-bash-title=&quot;&quot;Terminal&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;npx shadcn-ui@latest add form&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-bash-title=&quot;&quot;Terminal&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;npx shadcn-ui@latest add label&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-bash-title=&quot;&quot;Terminal&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;npx shadcn-ui@latest add sonner&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We’ll add the endpoints URL for these components, but we’ll create them later.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;src&#x2F;app&#x2F;auth&#x2F;signin-form.tsx&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Here we’ll update the UI and add form validation.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-tsx-title=&quot;&quot;src&#x2F;app&#x2F;auth&#x2F;signin-form.tsx&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot;use client&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { signIn } from &amp;quot;next-auth&#x2F;react&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { Button } from &amp;quot;@&#x2F;components&#x2F;ui&#x2F;button&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Form,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  FormControl,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  FormField,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  FormItem,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  FormLabel,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  FormMessage,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;} from &amp;quot;@&#x2F;components&#x2F;ui&#x2F;form&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { Input } from &amp;quot;@&#x2F;components&#x2F;ui&#x2F;input&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { Textarea } from &amp;quot;@&#x2F;components&#x2F;ui&#x2F;textarea&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { useForm } from &amp;quot;react-hook-form&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import * as z from &amp;quot;zod&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { zodResolver } from &amp;quot;@hookform&#x2F;resolvers&#x2F;zod&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;const formSchema = z.object({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  email: z.string().email(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;});&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export default function SigninForm() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const form = useForm&amp;lt;z.infer&amp;lt;typeof formSchema&amp;gt;&amp;gt;({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    resolver: zodResolver(formSchema),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    defaultValues: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      email: &amp;quot;&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  async function onSubmit({ email }: z.infer&amp;lt;typeof formSchema&amp;gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    await signIn(&amp;quot;email&amp;quot;, {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      email,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      callbackUrl: `${window.location.origin}`,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  return (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;Form {...form}&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;form className=&amp;quot;space-y-4&amp;quot; onSubmit={form.handleSubmit(onSubmit)}&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;FormField&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          control={form.control}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          name=&amp;quot;email&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          render={({ field }) =&amp;gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;FormItem&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              &amp;lt;FormLabel&amp;gt;Email&amp;lt;&#x2F;FormLabel&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              &amp;lt;FormControl&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                &amp;lt;Input placeholder=&amp;quot;address@example.com&amp;quot; {...field} &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              &amp;lt;&#x2F;FormControl&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              &amp;lt;FormMessage &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;&#x2F;FormItem&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          )}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;Button className=&amp;quot;w-full&amp;quot; type=&amp;quot;submit&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          Send magic link&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;&#x2F;Button&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&#x2F;form&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&#x2F;Form&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;src&#x2F;components&#x2F;post&#x2F;create.tsx&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Update UI components and form validation.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-tsx-title=&quot;&quot;src&#x2F;components&#x2F;post&#x2F;create.tsx&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot;use client&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { useState } from &amp;quot;react&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Dialog,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  DialogContent,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  DialogDescription,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  DialogHeader,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  DialogTitle,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  DialogTrigger,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;} from &amp;quot;@&#x2F;components&#x2F;ui&#x2F;dialog&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { Button } from &amp;quot;@&#x2F;components&#x2F;ui&#x2F;button&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Form,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  FormControl,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  FormField,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  FormItem,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  FormLabel,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  FormMessage,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;} from &amp;quot;@&#x2F;components&#x2F;ui&#x2F;form&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { Input } from &amp;quot;@&#x2F;components&#x2F;ui&#x2F;input&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { Textarea } from &amp;quot;@&#x2F;components&#x2F;ui&#x2F;textarea&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { useForm } from &amp;quot;react-hook-form&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import * as z from &amp;quot;zod&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { zodResolver } from &amp;quot;@hookform&#x2F;resolvers&#x2F;zod&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { useRouter } from &amp;quot;next&#x2F;navigation&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { toast } from &amp;quot;sonner&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { SessionProps } from &amp;quot;.&#x2F;types&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;const formSchema = z.object({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  title: z.string().min(1).max(100),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  content: z.string().min(1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;});&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export default function CreatePost(props: SessionProps) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const [open, setOpen] = useState(false);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const router = useRouter();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const form = useForm&amp;lt;z.infer&amp;lt;typeof formSchema&amp;gt;&amp;gt;({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    resolver: zodResolver(formSchema),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    defaultValues: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      title: &amp;quot;&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      content: &amp;quot;&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  async function onSubmit(values: z.infer&amp;lt;typeof formSchema&amp;gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    try {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      const res = await fetch(&amp;quot;&#x2F;api&#x2F;posts&amp;quot;, {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        method: &amp;quot;POST&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        headers: { &amp;quot;Content-Type&amp;quot;: &amp;quot;application&#x2F;json&amp;quot; },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        body: JSON.stringify({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          ...values,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          authorId: props.session.user?.id,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      const json = await res.json();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      if (!res.ok) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        toast(json.message);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        return;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      toast(&amp;quot;Post created!&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      form.reset();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      setOpen(false);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      router.refresh();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    } catch (error) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      console.error(error);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  return (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;Dialog open={open} onOpenChange={setOpen}&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;DialogTrigger asChild&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;Button&amp;gt;Create post&amp;lt;&#x2F;Button&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&#x2F;DialogTrigger&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;DialogContent className=&amp;quot;max-w-[300px]&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;DialogHeader className=&amp;quot;text-left&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;DialogTitle&amp;gt;Create post&amp;lt;&#x2F;DialogTitle&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;DialogDescription&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            Please &amp;lt;strong&amp;gt;do not&amp;lt;&#x2F;strong&amp;gt; post &amp;lt;strong&amp;gt;NSFW&amp;lt;&#x2F;strong&amp;gt; content.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;&#x2F;DialogDescription&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;&#x2F;DialogHeader&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;Form {...form}&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;form className=&amp;quot;space-y-4&amp;quot; onSubmit={form.handleSubmit(onSubmit)}&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;FormField&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              control={form.control}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              name=&amp;quot;title&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              render={({ field }) =&amp;gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                &amp;lt;FormItem&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  &amp;lt;FormLabel&amp;gt;Title&amp;lt;&#x2F;FormLabel&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  &amp;lt;FormControl&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    &amp;lt;Input placeholder=&amp;quot;Hi there!&amp;quot; {...field} &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  &amp;lt;&#x2F;FormControl&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  &amp;lt;FormMessage &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                &amp;lt;&#x2F;FormItem&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              )}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;FormField&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              control={form.control}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              name=&amp;quot;content&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              render={({ field }) =&amp;gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                &amp;lt;FormItem&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  &amp;lt;FormLabel&amp;gt;Content&amp;lt;&#x2F;FormLabel&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  &amp;lt;FormControl&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    &amp;lt;Textarea&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      placeholder=&amp;quot;Testing this great app!&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      {...field}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  &amp;lt;&#x2F;FormControl&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  &amp;lt;FormMessage &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                &amp;lt;&#x2F;FormItem&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              )}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;Button className=&amp;quot;w-full&amp;quot; type=&amp;quot;submit&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              Post&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;&#x2F;Button&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;&#x2F;form&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;&#x2F;Form&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&#x2F;DialogContent&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&#x2F;Dialog&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;src&#x2F;app&#x2F;page.tsx&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Fetch data from Prisma, as this page is a server component, we can fetch it
directly.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-tsx-title=&quot;&quot;src&#x2F;app&#x2F;page.tsx&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { authOptions } from &amp;quot;@&#x2F;libs&#x2F;auth&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { getServerSession } from &amp;quot;next-auth&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import prisma from &amp;quot;@&#x2F;libs&#x2F;db&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import CreatePost from &amp;quot;@&#x2F;components&#x2F;post&#x2F;create&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import Post from &amp;quot;@&#x2F;components&#x2F;post&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export default async function Home() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const session = await getServerSession(authOptions);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &#x2F;&#x2F; You can fetch data to Prisma in server components&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const posts = await prisma.post.findMany({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    include: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      author: true,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  return (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;h1 className=&amp;quot;mb-5 font-bold text-xl&amp;quot;&amp;gt;Home&amp;lt;&#x2F;h1&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      {session ? (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;CreatePost session={session} &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      ) : (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;p&amp;gt;You are not logged in&amp;lt;&#x2F;p&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      )}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;h3 className=&amp;quot;text-lg font-semibold mt-10&amp;quot;&amp;gt;Posts&amp;lt;&#x2F;h3&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;ul className=&amp;quot;mt-5 space-y-2.5&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        {posts.length &amp;gt; 0 ? (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          posts.map((post) =&amp;gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;li key={post.id}&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              &amp;lt;Post {...post} session={session} &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;&#x2F;li&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          ))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ) : (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;p&amp;gt;No posts&amp;lt;&#x2F;p&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&#x2F;ul&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;src&#x2F;components&#x2F;post&#x2F;item.tsx&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-tsx-title=&quot;&quot;src&#x2F;components&#x2F;post&#x2F;item.tsx&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot;use client&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import DeletePost from &amp;quot;.&#x2F;delete&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import EditPost from &amp;quot;.&#x2F;edit&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { TPostProps } from &amp;quot;.&#x2F;types&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export default function PostItem(props: TPostProps) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  return (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;article className=&amp;quot;w-max p-2 border border-slate-500 rounded-md&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;header className=&amp;quot;flex justify-between items-center&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;h2 className=&amp;quot;font-bold text-lg&amp;quot;&amp;gt;{props.title}&amp;lt;&#x2F;h2&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        {props.session?.user?.id === props.authorId &amp;amp;&amp;amp; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;section className=&amp;quot;space-x-2&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;EditPost {...props} &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;DeletePost {...props} &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;&#x2F;section&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&#x2F;header&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;p&amp;gt;{props.content}&amp;lt;&#x2F;p&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;span className=&amp;quot;text-sm&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        Posted by {props.author?.email || &amp;quot;anon&amp;quot;} at{&amp;quot; &amp;quot;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        {new Date(props.createdAt).toLocaleString()}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&#x2F;span&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&#x2F;article&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;src&#x2F;components&#x2F;post&#x2F;edit.tsx&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Create a button icon for opening a dialog rendering the post data for editing,
add validation and fetch to the API endpoint.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-tsx-title=&quot;&quot;src&#x2F;components&#x2F;post&#x2F;edit.tsx&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot;use client&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { useState } from &amp;quot;react&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { Edit } from &amp;quot;lucide-react&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Dialog,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  DialogClose,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  DialogContent,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  DialogDescription,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  DialogHeader,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  DialogTitle,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  DialogTrigger,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;} from &amp;quot;@&#x2F;components&#x2F;ui&#x2F;dialog&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Form,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  FormControl,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  FormField,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  FormItem,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  FormLabel,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  FormMessage,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;} from &amp;quot;@&#x2F;components&#x2F;ui&#x2F;form&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { Input } from &amp;quot;@&#x2F;components&#x2F;ui&#x2F;input&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { Textarea } from &amp;quot;@&#x2F;components&#x2F;ui&#x2F;textarea&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { useForm } from &amp;quot;react-hook-form&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import * as z from &amp;quot;zod&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { zodResolver } from &amp;quot;@hookform&#x2F;resolvers&#x2F;zod&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { useRouter } from &amp;quot;next&#x2F;navigation&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { toast } from &amp;quot;sonner&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { Button } from &amp;quot;@&#x2F;components&#x2F;ui&#x2F;button&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { TPostProps } from &amp;quot;.&#x2F;types&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;const formSchema = z.object({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  title: z.string().min(1).max(100),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  content: z.string().min(1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;});&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export default function EditPost(props: TPostProps) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const [open, setOpen] = useState(false);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const router = useRouter();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const form = useForm&amp;lt;z.infer&amp;lt;typeof formSchema&amp;gt;&amp;gt;({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    resolver: zodResolver(formSchema),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    defaultValues: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      title: props.title,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      content: props.content,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  async function onSubmit(values: z.infer&amp;lt;typeof formSchema&amp;gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    try {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      const res = await fetch(&amp;quot;&#x2F;api&#x2F;posts&amp;quot;, {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        method: &amp;quot;PUT&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        headers: { &amp;quot;Content-Type&amp;quot;: &amp;quot;application&#x2F;json&amp;quot; },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        body: JSON.stringify({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          ...values,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          id: props.id,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      const json = await res.json();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      if (!res.ok) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        toast(json.message);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        return;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      toast(&amp;quot;Post edited!&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      form.reset();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      setOpen(false);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      router.refresh();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    } catch (error) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      console.error(error);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  return (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;Dialog open={open} onOpenChange={setOpen}&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;DialogTrigger asChild&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;Button variant=&amp;quot;secondary&amp;quot; size=&amp;quot;icon&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;Edit &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;&#x2F;Button&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&#x2F;DialogTrigger&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;DialogContent className=&amp;quot;max-w-[300px]&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;DialogHeader className=&amp;quot;text-left&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;DialogTitle&amp;gt;Edit post&amp;lt;&#x2F;DialogTitle&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;DialogDescription&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            Please &amp;lt;strong&amp;gt;do not&amp;lt;&#x2F;strong&amp;gt; post &amp;lt;strong&amp;gt;NSFW&amp;lt;&#x2F;strong&amp;gt; content.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;&#x2F;DialogDescription&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;&#x2F;DialogHeader&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;Form {...form}&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;form className=&amp;quot;space-y-4&amp;quot; onSubmit={form.handleSubmit(onSubmit)}&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;FormField&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              control={form.control}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              name=&amp;quot;title&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              render={({ field }) =&amp;gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                &amp;lt;FormItem&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  &amp;lt;FormLabel&amp;gt;Title&amp;lt;&#x2F;FormLabel&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  &amp;lt;FormControl&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    &amp;lt;Input placeholder=&amp;quot;Hi there!&amp;quot; {...field} &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  &amp;lt;&#x2F;FormControl&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  &amp;lt;FormMessage &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                &amp;lt;&#x2F;FormItem&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              )}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;FormField&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              control={form.control}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              name=&amp;quot;content&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              render={({ field }) =&amp;gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                &amp;lt;FormItem&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  &amp;lt;FormLabel&amp;gt;Content&amp;lt;&#x2F;FormLabel&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  &amp;lt;FormControl&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    &amp;lt;Textarea&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      placeholder=&amp;quot;Testing this great app!&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      {...field}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  &amp;lt;&#x2F;FormControl&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  &amp;lt;FormMessage &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                &amp;lt;&#x2F;FormItem&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              )}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;DialogClose asChild&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              &amp;lt;Button className=&amp;quot;w-full&amp;quot; type=&amp;quot;submit&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                Edit post&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              &amp;lt;&#x2F;Button&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;&#x2F;DialogClose&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;&#x2F;form&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;&#x2F;Form&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&#x2F;DialogContent&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&#x2F;Dialog&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;src&#x2F;components&#x2F;post&#x2F;delete.tsx&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Create a button icon for opening a dialog for deleting the post, add validation
and fetch to the API endpoint.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-tsx-title=&quot;&quot;src&#x2F;components&#x2F;post&#x2F;delete.tsx&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot;use client&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { LucideTrash2 } from &amp;quot;lucide-react&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { Button } from &amp;quot;@&#x2F;components&#x2F;ui&#x2F;button&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Dialog,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  DialogClose,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  DialogContent,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  DialogDescription,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  DialogHeader,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  DialogTitle,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  DialogTrigger,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;} from &amp;quot;@&#x2F;components&#x2F;ui&#x2F;dialog&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { useRouter } from &amp;quot;next&#x2F;navigation&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { toast } from &amp;quot;sonner&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { TPostProps } from &amp;quot;.&#x2F;types&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export default function DeletePost(props: TPostProps) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const router = useRouter();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  async function handleDelete() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    try {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      const res = await fetch(&amp;quot;&#x2F;api&#x2F;posts&amp;quot;, {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        method: &amp;quot;DELETE&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        headers: { &amp;quot;Content-Type&amp;quot;: &amp;quot;application&#x2F;json&amp;quot; },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        body: JSON.stringify({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          id: props.id,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      const json = await res.json();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      if (!res.ok) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        toast(json.message);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        return;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      toast(&amp;quot;Post deleted!&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      router.refresh();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    } catch (error) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      console.error(error);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  return (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;Dialog&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;DialogTrigger asChild&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;Button variant=&amp;quot;destructive&amp;quot; size=&amp;quot;icon&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;LucideTrash2 &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;&#x2F;Button&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&#x2F;DialogTrigger&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;DialogContent className=&amp;quot;max-w-[300px]&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;DialogHeader className=&amp;quot;text-left&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;DialogTitle&amp;gt;Delete post&amp;lt;&#x2F;DialogTitle&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;DialogDescription&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            Are you sure you want to &amp;lt;strong&amp;gt;delete&amp;lt;&#x2F;strong&amp;gt; this post? This&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            action cannot be undone.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;&#x2F;DialogDescription&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;&#x2F;DialogHeader&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;footer className=&amp;quot;flex flex-col gap-2&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;DialogClose asChild&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;Button variant=&amp;quot;secondary&amp;quot; className=&amp;quot;w-full&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              No, keep post&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;&#x2F;Button&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;&#x2F;DialogClose&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;DialogClose asChild&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;Button&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              onClick={handleDelete}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              variant=&amp;quot;destructive&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              className=&amp;quot;w-full&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              Yes, delete post&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;&#x2F;Button&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;&#x2F;DialogClose&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;&#x2F;footer&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&#x2F;DialogContent&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&#x2F;Dialog&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;src&#x2F;components&#x2F;post&#x2F;types.ts&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-ts-title=&quot;&quot;src&#x2F;components&#x2F;post&#x2F;types.ts&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;type SessionProps = {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  session: any;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;type TPostProps = {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  author: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    id: string;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    name: string | null;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    email: string | null;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    emailVerified: Date | null;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    image: string | null;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  } | null;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  id: string;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  createdAt: Date;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  updatedAt: Date;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  title: string;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  content: string;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  authorId: string | null;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  session: any;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export type { SessionProps, TPostProps };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;src&#x2F;components&#x2F;sign-out.tsx&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A simple sign out button.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-tsx-title=&quot;&quot;src&#x2F;components&#x2F;sign-out.tsx&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot;use client&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { signOut } from &amp;quot;next-auth&#x2F;react&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { Button } from &amp;quot;.&#x2F;ui&#x2F;button&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export default function SignOut() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  return &amp;lt;Button onClick={() =&amp;gt; signOut()}&amp;gt;Sign out&amp;lt;&#x2F;Button&amp;gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;src&#x2F;components&#x2F;navbar.tsx&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Render the sign out or sign in button depending if the user is logged in or not.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-tsx-title=&quot;&quot;src&#x2F;components&#x2F;navbar.tsx&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import Link from &amp;quot;next&#x2F;link&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { Button } from &amp;quot;.&#x2F;ui&#x2F;button&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { getServerSession } from &amp;quot;next-auth&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { authOptions } from &amp;quot;@&#x2F;libs&#x2F;auth&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import SignOut from &amp;quot;.&#x2F;sign-out&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export default async function Navbar() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const session = await getServerSession(authOptions);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  return (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;nav className=&amp;quot;w-full p-4 border-b flex justify-between items-center&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;section&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;Button variant=&amp;quot;link&amp;quot; className=&amp;quot;px-0 font-semibold text-lg&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;Link href=&amp;quot;&#x2F;&amp;quot;&amp;gt;Fullstack app&amp;lt;&#x2F;Link&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;&#x2F;Button&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&#x2F;section&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;section&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        {session ? (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;SignOut &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ) : (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;Button asChild&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;Link href=&amp;quot;&#x2F;auth&amp;quot;&amp;gt;Sign in&amp;lt;&#x2F;Link&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;&#x2F;Button&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&#x2F;section&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&#x2F;nav&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;src&#x2F;app&#x2F;layout.tsx&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Add your &lt;strong&gt;Navbar&lt;&#x2F;strong&gt; and &lt;strong&gt;Toaster&lt;&#x2F;strong&gt; components and some styles.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-tsx-title=&quot;&quot;src&#x2F;app&#x2F;layout.tsx&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { Inter } from &amp;quot;next&#x2F;font&#x2F;google&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import Navbar from &amp;quot;@&#x2F;components&#x2F;navbar&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { Toaster } from &amp;quot;@&#x2F;components&#x2F;ui&#x2F;sonner&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import &amp;quot;.&#x2F;globals.css&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;const inter = Inter({ subsets: [&amp;quot;latin&amp;quot;] });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;interface Props extends React.PropsWithChildren {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export default function RootLayout(props: Props) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  return (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;body className={inter.className}&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;Navbar &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;main className=&amp;quot;px-4 py-8&amp;quot;&amp;gt;{props.children}&amp;lt;&#x2F;main&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;Toaster &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&#x2F;body&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&#x2F;html&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;4-add-crud-functionality&quot;&gt;4. Add CRUD functionality&lt;&#x2F;h2&gt;
&lt;p&gt;Now we can add Create, Read, Update and Delete functionality to our app.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;prisma&#x2F;schema.prisma&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Update your Prisma schema adding to User model a relationship with Post model:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-prisma-title=&quot;&quot;prisma&#x2F;schema.prisma&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;generator client {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  provider = &amp;quot;prisma-client-js&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;datasource db {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  provider = &amp;quot;postgresql&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  url      = env(&amp;quot;DATABASE_URL&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;model Account {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  id                String  @id @default(cuid())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  userId            String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  type              String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  provider          String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  providerAccountId String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  refresh_token     String? @db.Text&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  access_token      String? @db.Text&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  expires_at        Int?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  token_type        String?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  scope             String?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  id_token          String? @db.Text&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  session_state     String?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  user User @relation(fields: [userId], references: [id], onDelete: Cascade)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  @@unique([provider, providerAccountId])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;model Session {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  id           String   @id @default(cuid())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  sessionToken String   @unique&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  userId       String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  expires      DateTime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  user         User     @relation(fields: [userId], references: [id], onDelete: Cascade)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;model User {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  id            String    @id @default(cuid())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  name          String?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  email         String?   @unique&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  emailVerified DateTime?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  image         String?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  accounts      Account[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  sessions      Session[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  posts         Post[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;model VerificationToken {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  identifier String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  token      String   @unique&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  expires    DateTime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  @@unique([identifier, token])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;model Post {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  id        String   @id @default(cuid())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  createdAt DateTime @default(now())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  updatedAt DateTime @updatedAt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  title     String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  content   String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  author    User     @relation(fields: [authorId], references: [id])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  authorId  String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Generate a new Prisma migration:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-bash-title=&quot;&quot;Terminal&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;npx prisma migrate dev --name add-posts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, create a &lt;code&gt;src&#x2F;app&#x2F;api&#x2F;posts&#x2F;route.ts&lt;&#x2F;code&gt; file with a &lt;strong&gt;POST&lt;&#x2F;strong&gt;, &lt;strong&gt;PUT&lt;&#x2F;strong&gt; and
&lt;strong&gt;DELETE&lt;&#x2F;strong&gt; async functions:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-ts-title=&quot;&quot;src&#x2F;app&#x2F;api&#x2F;posts&#x2F;route.ts&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import prisma from &amp;quot;@&#x2F;libs&#x2F;db&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { NextRequest, NextResponse } from &amp;quot;next&#x2F;server&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export async function POST(req: Request) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  try {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    if (!req.body) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      return NextResponse.json({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ok: false,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        status: 400,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        message: &amp;quot;Data required&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    const json = await req.json();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    const res = await prisma.post.create({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      data: json,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    return NextResponse.json({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      ok: true,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      status: 201,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      data: res,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  } catch (error) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    if (error instanceof Error) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      return NextResponse.json({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ok: false,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        status: 500,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        message: error.message,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    return NextResponse.json({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      ok: false,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      status: 500,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      message: &amp;quot;Internal server error&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export async function PUT(req: NextRequest) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  try {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    const body = await req.json();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    const res = await prisma.post.update({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      where: { id: body.id },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      data: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        title: body.title,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        content: body.content,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    return NextResponse.json({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      ok: true,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      status: 200,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      data: res,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  } catch (error) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    if (error instanceof Error) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      return NextResponse.json({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ok: false,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        status: 500,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        message: error.message,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    return NextResponse.json({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      ok: false,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      status: 500,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      message: &amp;quot;Internal server error&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export async function DELETE(req: NextRequest) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  try {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    const body = await req.json();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    const res = await prisma.post.delete({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      where: { id: body.id },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    return NextResponse.json({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      ok: true,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      status: 200,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      data: res,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  } catch (error) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    if (error instanceof Error) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      return NextResponse.json({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ok: false,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        status: 500,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        message: error.message,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    return NextResponse.json({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      ok: false,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      status: 500,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      message: &amp;quot;Internal server error&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Try creating a post in the home.&lt;&#x2F;p&gt;
&lt;p&gt;The page will refresh and you’ll see the post, as you created it, only you can
edit or delete it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;5-conclusion&quot;&gt;5. Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;As you can see, create a fullstack app with Next.js and Prisma is really easy.&lt;&#x2F;p&gt;
&lt;p&gt;Of course, it could be improved, adding server side validation for inputs,
adding pagination for posts in the home, etc.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="xx">
        <title>Next Intl Blog Template</title>
        <published>2023-12-18T00:00:00+00:00</published>
        <updated>2023-12-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Juan Manzanero
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://juanmanzanero.com/blog/next-intl-blog-template/"/>
        <id>https://juanmanzanero.com/blog/next-intl-blog-template/</id>
        
        <content type="html" xml:base="https://juanmanzanero.com/blog/next-intl-blog-template/">&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;juanmanzanero-com&#x2F;next-intl-blog-template&quot;&gt;GitHub&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;&#x2F;h2&gt;
&lt;p&gt;Recently I update this website, and as you may know, is an &lt;strong&gt;English and Spanish
content website&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I’m not using a translation plugin, instead I write every work in both English
and Spanish.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks to Next.js and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;next-intl-docs.vercel.app&#x2F;&quot;&gt;next-intl&lt;&#x2F;a&gt; I can
achieve this, rendering routes for each language in the website, accessing a
dictionary that contains the content translated by me.&lt;&#x2F;p&gt;
&lt;p&gt;For the .mdx files, I created a directory for each language, and inside of those
directories it contains the content in both languages too.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-to-use&quot;&gt;How to use&lt;&#x2F;h2&gt;
&lt;p&gt;This template is an extension of
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;next-intl-docs.vercel.app&#x2F;&quot;&gt;next-intl&lt;&#x2F;a&gt;, chek the
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;next-intl-docs.vercel.app&#x2F;docs&#x2F;getting-started&quot;&gt;getting started&lt;&#x2F;a&gt; to
learn the basics, the purpouse of the template is to create a simple layout for
future customization.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;add-or-remove-locales&quot;&gt;Add or remove locales&lt;&#x2F;h3&gt;
&lt;p&gt;You can add or remove locales in the &lt;code&gt;src&#x2F;lang&#x2F;locales.ts&lt;&#x2F;code&gt; file.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-ts-title=&quot;&quot;src&#x2F;lang&#x2F;locales.ts&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export type locales = &amp;quot;en&amp;quot; | &amp;quot;es&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export const localesList: locales[] = [&amp;quot;en&amp;quot;, &amp;quot;es&amp;quot;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Just add or remove a locale from the &lt;code&gt;locales&lt;&#x2F;code&gt; const, and add or remove it from
the list.&lt;&#x2F;p&gt;
&lt;p&gt;The first item in the &lt;code&gt;localesList&lt;&#x2F;code&gt; must be the default locale.&lt;&#x2F;p&gt;
&lt;p&gt;The list is used for static generation of the routes in
&lt;code&gt;src&#x2F;app&#x2F;[locale]&#x2F;layout.tsx&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-ts-title=&quot;&quot;src&#x2F;app&#x2F;[locale]&#x2F;layout.tsx&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { localesList } from &amp;quot;@&#x2F;lang&#x2F;locales&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export function generateStaticParams() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  return localesList.map((locale) =&amp;gt; ({ locale }));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Remember to update the matcher in &lt;code&gt;src&#x2F;middleware.ts&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-ts-title=&quot;&quot;src&#x2F;middleware.ts&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&#x2F;&#x2F;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export const config = {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  matcher: [&amp;quot;&#x2F;&amp;quot;, &amp;quot;&#x2F;(en|es)&#x2F;:path*&amp;quot;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And of course, update your &lt;code&gt;src&#x2F;lang&#x2F;[locale].json&lt;&#x2F;code&gt; files.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;content-creation&quot;&gt;Content creation&lt;&#x2F;h3&gt;
&lt;p&gt;Use &lt;code&gt;src&#x2F;content&#x2F;[locale]&lt;&#x2F;code&gt; for create content, in the &lt;code&gt;&#x2F;[locale]&#x2F;&lt;&#x2F;code&gt; directory
ceate the directory for each purpouse, for example: &lt;code&gt;&#x2F;[locale]&#x2F;blog&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Inside create the .mdx file with an unique name, the name will be used as the
slug for create the static page for that post.&lt;&#x2F;p&gt;
&lt;p&gt;For create a blog section, you’ll use the &lt;em&gt;getAllContent&lt;&#x2F;em&gt; function in your
route, for example: &lt;code&gt;src&#x2F;app&#x2F;[locale]&#x2F;blog&#x2F;[slug]&#x2F;page.tsx&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-tsx-title=&quot;&quot;src&#x2F;app&#x2F;[locale]&#x2F;blog&#x2F;[slug]&#x2F;page.tsx&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { Mdx } from &amp;quot;@&#x2F;components&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { TParamsLocale, TPage, TSlugLang } from &amp;quot;@&#x2F;types&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { Metadata } from &amp;quot;next&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { getAllContent, getContent } from &amp;quot;@&#x2F;utils&#x2F;getContent&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export async function generateStaticParams(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  props: TParamsLocale,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;): Promise&amp;lt;TSlugLang[]&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const blogs = await getAllContent(props.params.locale, &amp;quot;blog&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  if (!blogs) return [];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  return blogs.map((blog) =&amp;gt; ({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    slug: blog.slug,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    locale: props.params.locale,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&#x2F;&#x2F;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will create each static page for each blog post.&lt;&#x2F;p&gt;
&lt;p&gt;You can get the metadata of the &lt;code&gt;.mdx&lt;&#x2F;code&gt; file too.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-tsx-title=&quot;&quot;src&#x2F;app&#x2F;[locale]&#x2F;blog&#x2F;[slug]&#x2F;page.tsx&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&#x2F;&#x2F;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export async function generateMetadata(props: TPage): Promise&amp;lt;Metadata&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const blog = await getContent(props.params.locale, &amp;quot;blog&amp;quot;, props.params.slug);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  if (!blog) return {};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  return {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    title: blog.title,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &#x2F;&#x2F;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&#x2F;&#x2F;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, render the content using the &lt;em&gt;Mdx&lt;&#x2F;em&gt; component.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #A9B1D6; background-color: #1A1B26;&quot;&gt;&lt;code data-lang=&quot;plain&quot; data-tsx-title=&quot;&quot;src&#x2F;app&#x2F;[locale]&#x2F;blog&#x2F;[slug]&#x2F;page.tsx&quot;&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&#x2F;&#x2F;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export default async function Page(props: TPage) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const post = await getContent(props.params.locale, &amp;quot;blog&amp;quot;, props.params.slug);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  if (!post) return null;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  return &amp;lt;Mdx code={post.body.code} &#x2F;&amp;gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;juanmanzanero-com&#x2F;next-intl-blog-template&quot;&gt;You can fork this template here&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="xx">
        <title>Rewind 2023 and future plans</title>
        <published>2023-12-16T00:00:00+00:00</published>
        <updated>2023-12-16T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Juan Manzanero
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://juanmanzanero.com/blog/rewind-2023-and-future-plans/"/>
        <id>https://juanmanzanero.com/blog/rewind-2023-and-future-plans/</id>
        
        <content type="html" xml:base="https://juanmanzanero.com/blog/rewind-2023-and-future-plans/">&lt;p&gt;My rewind for 2023 and my plans for 2024 and beyond.&lt;&#x2F;p&gt;
&lt;p&gt;I hope you are having a good time this holiday.&lt;&#x2F;p&gt;
&lt;p&gt;Life is a succession of choices, and in retrospect, I’m happy that this year I
made the right ones.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;in-retrospect-about-my-career-this-2023&quot;&gt;In retrospect about my career this 2023&lt;&#x2F;h2&gt;
&lt;p&gt;I grew up drastically as a Full Stack Developer, learning new libraries and
establishing my tech stack.&lt;&#x2F;p&gt;
&lt;p&gt;I even started hacking (not the thing you hear in the news), creating side
projects looking to create solutions.&lt;&#x2F;p&gt;
&lt;p&gt;I updated this website, creating new functionalities for content creation.&lt;&#x2F;p&gt;
&lt;p&gt;Now I have more confidence in my skills, ready to keep growing up and taking on
new challenges.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;futures-plans-for-my-career-this-2024&quot;&gt;Futures plans for my career this 2024&lt;&#x2F;h2&gt;
&lt;p&gt;I want to start freelancing, I’ll be creating templates and demo projects for
selling my services as a Frontend Developer mainly, but I’ll keep learning about
Backend and Cloud, as well as keep practicing my English to enter the USA or
European markets.&lt;&#x2F;p&gt;
&lt;p&gt;Maybe I’ll not achieve this in 2024, but I must keep growing, as each year
passes, I’ll be more prepared.&lt;&#x2F;p&gt;
&lt;p&gt;I’ll check if I could contribute to an Open Source project, as almost every tool
that I use is an Open Source one, I couldn’t be here without if not with the
help of Open Source projects.&lt;&#x2F;p&gt;
&lt;p&gt;Honestly, my true wish is to work full time in a Software as a Service startup,
or any startup with a focus on Software.&lt;&#x2F;p&gt;
&lt;p&gt;The good thing that is I keep growing professionally, and I expect (and will)
the next year I’ll reach more milestones.&lt;&#x2F;p&gt;
&lt;p&gt;And of course, I’ll continue hacking (in a creative way, not stealing info or
criminal things) with side projects, creating an extra incoming source will be
great for my finances.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;retrospect-of-2023-personally-and-more&quot;&gt;Retrospect of 2023 personally and more&lt;&#x2F;h2&gt;
&lt;p&gt;This year I rediscovered the hobby of reading, and I really enjoy it.&lt;&#x2F;p&gt;
&lt;p&gt;I discovered my new favorite book, &lt;strong&gt;Ready Player One&lt;&#x2F;strong&gt;, it was a really
exciting and great lecture, the next year I’ll read the sequel.&lt;&#x2F;p&gt;
&lt;p&gt;I also started reading &lt;strong&gt;Ikigai&lt;&#x2F;strong&gt;, to keep acquiring good habits for a long and
happy life, and seek a purpose in life.&lt;&#x2F;p&gt;
&lt;p&gt;Another book I started reading is &lt;strong&gt;The Little Book of Common Sense Investing&lt;&#x2F;strong&gt;,
as I already had a good habit of saving, but I want my money to keep growing
more for a dignified retirement.&lt;&#x2F;p&gt;
&lt;p&gt;I’m spending less time on social media,
&lt;a href=&quot;&#x2F;blog&#x2F;the-monotony-of-social-media&quot;&gt;even I wrote an article about this&lt;&#x2F;a&gt;,
doing things that &lt;strong&gt;I really want to do&lt;&#x2F;strong&gt; instead.&lt;&#x2F;p&gt;
&lt;p&gt;Is really horrible how much time social media steals from us, keeping us away
from doing things that we really enjoy.&lt;&#x2F;p&gt;
&lt;p&gt;I’m doing moderate exercise, but indoors, I want to go outdoors too, I need more
solar light.&lt;&#x2F;p&gt;
&lt;p&gt;I’m happy spending my time with my family, even if the majority of the time I’m
working or studying, I keep contact with my loved ones, and continue doing it,
clearly.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;future-plans-for-2024-personally-and-more&quot;&gt;Future plans for 2024 personally and more&lt;&#x2F;h2&gt;
&lt;p&gt;I’ll keep reading, I’ll write more on this website.&lt;&#x2F;p&gt;
&lt;p&gt;I want to acquire new habits, like pixel art.&lt;&#x2F;p&gt;
&lt;p&gt;And I’m retaking an old hobby, &lt;strong&gt;GameDev&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;As Unity is doing questionable things, I’ll be using
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;godotengine.org&#x2F;&quot;&gt;Godot&lt;&#x2F;a&gt; instead.&lt;&#x2F;p&gt;
&lt;p&gt;I don’t have in mind a big project or something like that, just retake to
develop simple videogames demos, it would be great to launch a little videogame,
but a complete one.&lt;&#x2F;p&gt;
&lt;p&gt;Trust me, is really, &lt;strong&gt;REALLY&lt;&#x2F;strong&gt; challenging to develop videogames, so instead of
overwhelming myself, I’ll keep my &lt;strong&gt;ambitions simple&lt;&#x2F;strong&gt;, but &lt;strong&gt;constant&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;happy-holidays&quot;&gt;Happy holidays!&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;juanmanzanero.com&#x2F;blog&#x2F;rewind-2023-and-future-plans&#x2F;2023-complete!.png&quot; alt=&quot;2023 complete image!&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="xx">
        <title>I participated in a Hackathon</title>
        <published>2023-08-16T00:00:00+00:00</published>
        <updated>2023-08-16T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Juan Manzanero
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://juanmanzanero.com/blog/i-participated-in-a-hackathon/"/>
        <id>https://juanmanzanero.com/blog/i-participated-in-a-hackathon/</id>
        
        <content type="html" xml:base="https://juanmanzanero.com/blog/i-participated-in-a-hackathon/">&lt;p&gt;I recently participated in a Supabase Hackathon, forming a team with people from other countries.&lt;&#x2F;p&gt;
&lt;p&gt;The Hackathon thematic was free, the only main rule is to use Supabase for any
feature, like authentication, as a PostgreSQL database or using vectors for AI,
with 10 days to build a product using any technology and upload it in a GitHub
repository.&lt;&#x2F;p&gt;
&lt;p&gt;We developed an e-commerce app with a Walmart products model, implementing
vectors for better search results.&lt;&#x2F;p&gt;
&lt;p&gt;Using Supabase we implemented auth and protected routes so the user needs to log
in to see recommendations and more.&lt;&#x2F;p&gt;
&lt;p&gt;The user can add products to the shopping cart and check their items for saved
it and see recommendations and which items are frequently bought.&lt;&#x2F;p&gt;
&lt;p&gt;My main role was focused on creating the UI using the Next.js 13 app router,
protecting routes only for authenticated users, and create reusable components
such as product cards, and of course, making the layout responsive for mobile
and desktop.&lt;&#x2F;p&gt;
&lt;p&gt;We used &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ui.shadcn.com&#x2F;&quot;&gt;Shadcn&#x2F;UI&lt;&#x2F;a&gt; as those components are already
implemented functionalities with accessibility like modals or sidebars, like the
sidebar that appears when you’re on a mobile device and open the button in the
header, with a smooth animation.&lt;&#x2F;p&gt;
&lt;p&gt;We submitted the project on time and waiting for the results, and this is my
first time participating in a Hackathon, I really enjoy it and hope to continue
contributing to the project on GitHub.&lt;&#x2F;p&gt;
&lt;p&gt;It’s amazing work with people from other countries, using English even if is not
our native language, but with a purpose in common, create a great product.&lt;&#x2F;p&gt;
&lt;p&gt;I’ll keep looking to participate in more Hackathons in the future and contribute
to open source projects on Github because I really enjoy the feeling of
developing something big with more people.&lt;&#x2F;p&gt;
&lt;p&gt;I learned too much in these few days, like integrating Next.js with Supabase for
authentication and protected routes, using the Supabase docs as a guide, and
using it for the first time Shadcn&#x2F;UI, and looking forward to keep using it.&lt;&#x2F;p&gt;
&lt;p&gt;It took me so long to participate in a Hackathon, as before I hesitated about my
experience, but the reality is we’ll never be ready for new challenges because
if you’re already ready it means that’s too late.&lt;&#x2F;p&gt;
&lt;p&gt;I want to learn more about using vectors for AI, so I’ll investigate more about
the topic, as the tech tends to go that way, who knows what would be the next
big tech trend or when.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;groce-wise.vercel.app&#x2F;&quot;&gt;You can see the project: Grocewise here&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="xx">
        <title>The Monotony of Social Media</title>
        <published>2023-07-17T00:00:00+00:00</published>
        <updated>2023-07-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Juan Manzanero
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://juanmanzanero.com/blog/the-monotony-of-social-media/"/>
        <id>https://juanmanzanero.com/blog/the-monotony-of-social-media/</id>
        
        <content type="html" xml:base="https://juanmanzanero.com/blog/the-monotony-of-social-media/">&lt;p&gt;Abstracting human interaction using software has caused many problems that
didn’t exist before.&lt;&#x2F;p&gt;
&lt;p&gt;It’s obvious, a lot of interactions on the Internet occurs through social media,
letting you send friend requests, chat, or share memes and photos. However,
abstracting human interaction using software has caused many problems that
didn’t exist before.&lt;&#x2F;p&gt;
&lt;p&gt;When the Internet started, many people created their own websites because that’s
was the thing you must have if you want to be cool, and a lot of these websites
was just blogpost-like where the users shares their hobbies like movies, sports,
books, videogames, etc. This motivation made more unique and human websites,
where you can meet someone and their likes or dislikes.&lt;&#x2F;p&gt;
&lt;p&gt;Now, with the boom of social media in the middle of 2000’s, people prefer to
connect just searching for a name or looking the friends of their friends, and
send friend requests to try and connect. That was cool at the start, as anything
new, but the problems started when companies like Facebook (now Meta) or Google
(with YouTube) needed to monetize their platforms, mostly with Ads.&lt;&#x2F;p&gt;
&lt;p&gt;And of course, that means that they needed to suppress, censor or ban anything
that could be harmful for society, like hate speeches or stupid challenges that
could risk people’s lives.&lt;&#x2F;p&gt;
&lt;p&gt;But, the bat thing about this, is that they homogenize almost everyone, forcing
them to act as the algorithms keeps recommending users with likes and comments,
guiding the people to act like someone else, and so.&lt;&#x2F;p&gt;
&lt;p&gt;Now almost everyone does mainly two things, post photos about their “perfect”
lives or share memes, and don’t get me wrong, it’s ok to enter to social media
and try to disconnect for your job or problems, but using this every day as
instant escape instead of confronting your own problems could be harmful in the
long term, isolating you from the need of socialize in real life, with real
people, and thinking that everyone has a perfect life.&lt;&#x2F;p&gt;
&lt;p&gt;No, EVERYONE has problems in their lives, even more than yours, but social media
algorithms promotes mainly “positive vibes only” and all that shit that in big
dose is hamrful for our minds.&lt;&#x2F;p&gt;
&lt;p&gt;And don’t mention the censorship and shadow-banning if you post something
controversial, it could be something that should not be tolerated like incite
hate to a group, or it could be something that don’t everyone agrees but it
could be useful think a little about it, but still being controversial.&lt;&#x2F;p&gt;
&lt;p&gt;Should everyone can tell what they thinks? Yeah, always if doesn’t promotes hate
or hurt other people or animals.&lt;&#x2F;p&gt;
&lt;p&gt;They’re reports like Twitter promotes hate in the algorithm, and Meta knows that
Instagram increases anxiety and depression on young people, and actually;
promotes it… as all negative feelings keeps you on the social media
interacting with others, as that’s what those companies sell, your data and time
to advertisers.&lt;&#x2F;p&gt;
&lt;p&gt;I recently heard a video talking about this topic, and that would be cool if we
go back as the starts of the Internet where people created content as a hobby,
instead of looking for validation through likes and comments, being more
authentic persons instead of products.&lt;&#x2F;p&gt;
&lt;p&gt;Should software solutions replace human interactions? I think not, but it’s too
late for almost everyone, but if you’re reading this, start changing your life
first if you want to be honest with yourself.&lt;&#x2F;p&gt;
&lt;p&gt;Blog inspired by “Why does every personal website look like this now?” by Eric
Murphy on YouTube.&lt;&#x2F;p&gt;
&lt;p&gt;Source Video:&lt;&#x2F;p&gt;
&lt;iframe
  width=&#x27;100%&#x27;
  height=&#x27;320&#x27;
  className=&#x27;rounded-md&#x27;
  src=&#x27;https:&#x2F;&#x2F;www.youtube-nocookie.com&#x2F;embed&#x2F;_x6SCSz7g5I&#x27;
  title=&#x27;YouTube video player&#x27;
  allow=&#x27;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#x27;
  allowFullScreen
&gt;&lt;&#x2F;iframe&gt;
</content>
        
    </entry>
    <entry xml:lang="xx">
        <title>How Computers Works</title>
        <published>2023-05-29T00:00:00+00:00</published>
        <updated>2023-05-29T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Juan Manzanero
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://juanmanzanero.com/blog/how-computers-works/"/>
        <id>https://juanmanzanero.com/blog/how-computers-works/</id>
        
        <content type="html" xml:base="https://juanmanzanero.com/blog/how-computers-works/">&lt;p&gt;Today we use, in some way, the computer in almost every activity in our lives, it could be for work or just fun, but if we think carefully, computers are an invention from the previous century, and have changed our lives.&lt;&#x2F;p&gt;
&lt;p&gt;New works have appeared, new careers to study, and new problems to be solved.&lt;&#x2F;p&gt;
&lt;p&gt;However, do we know how computers penetrated our lives? Do we know how a
computer works? How does the Internet work?&lt;&#x2F;p&gt;
&lt;p&gt;Many people use their smartphones to communicate with family and friends and to
share their lives, but they don’t know how all this is possible.&lt;&#x2F;p&gt;
&lt;p&gt;I’m not saying that everyone needs to be a Software Engineer or IT Expert, but
knowing about this could be outstanding knowledge.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-power-of-computers&quot;&gt;The power of computers&lt;&#x2F;h2&gt;
&lt;p&gt;Computers can expand our brains, such things like sends messages to people from
the other side of the Earth, to create an app that speeds up delivery.&lt;&#x2F;p&gt;
&lt;p&gt;All these things are possible by flipping 0’s and 1’s, but how is this possible?&lt;&#x2F;p&gt;
&lt;p&gt;If you’ve watched The Imitation Code, maybe you know this story.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;computing-fundaments&quot;&gt;Computing Fundaments&lt;&#x2F;h3&gt;
&lt;p&gt;Alan Turing was the inventor of the Turing Machine, a simple but powerful
machine that can receive instructions to move along a long tape, changing the
state of each slot. This three things, a head, a long tape and a set of
instructions are the bases for the modern computers.&lt;&#x2F;p&gt;
&lt;p&gt;The head is the Central Processing Unit (CPU), a piece of hardware that can be
used for general purposes, receiving instructions (Algorithm) whose are
transformed to electric pulses, understanding if electricity pass trough or not,
if it’s true or false, 1 or 0. All these instructions are saved in a Random
Access Memory (RAM) for a quick access of the work that needs to be
accomplished, and using a Read-Only Memory (ROM) to store persistent data that
needs to be saved even if the computer shuts down.&lt;&#x2F;p&gt;
&lt;p&gt;An algorithm’s like a recipe, declaring ingredients (variables) and the steps to
follow to achieve the result (functions).&lt;&#x2F;p&gt;
&lt;p&gt;A variable is an identifier that points to a slot of memory in the RAM, storing
a value that can be a number, a text (known as “string”), a boolean (true or
false), or an object (a set of multiple variables and functions that can be
instanced), etc.&lt;&#x2F;p&gt;
&lt;p&gt;Functions are blocks of instructions that achieve a task, like obtaining your
current location or sending a message.&lt;&#x2F;p&gt;
&lt;p&gt;And maybe you are asking, how do I tell a computer how to do what I want?&lt;&#x2F;p&gt;
&lt;h3 id=&quot;programming-languages&quot;&gt;Programming languages&lt;&#x2F;h3&gt;
&lt;p&gt;If you try to speak with someone who doesn’t speak the same language as you, you
try to use a translator or use gestures, something that you know that both can
in some way understand, the same is for computers.&lt;&#x2F;p&gt;
&lt;p&gt;Computers are powerful, but they need someone to tell them what to do, this is
work for humans, and to achieve it we use programming languages. With a
programming language you use a specific syntax to tell a computer your desired
task, then you compile that file where you type all your instructions, when a
file compiles, is transformed to a computer nature language (1’s and 0’s) and
then the computer executes the task.&lt;&#x2F;p&gt;
&lt;p&gt;There are different programming languages, and all of them are designed to
achieve specific needs, like the programming languages C and C++, both are
low-level languages, which means that are close to how a computer “speaks” and
are used to control and administrate memory in high-efficient apps, or to
illuminate the screen of your computer.&lt;&#x2F;p&gt;
&lt;p&gt;There is Java, is a language that can create an environment when is compiled,
meaning that can be used on almost every computer.&lt;&#x2F;p&gt;
&lt;p&gt;JavaScript (is NOT Java or something like that) is a language that our browsers
understands, with the help of JavaScript, we can access to a web page and see
nice interactions when we click a button, login with a username and password,
and more.&lt;&#x2F;p&gt;
&lt;p&gt;JavaScript is a high-level language, that is easiest to learn than Java or C,
but not that is worse or better, just resolves a different need.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-browser&quot;&gt;The Browser&lt;&#x2F;h3&gt;
&lt;p&gt;A powerful software that can access other computers using the Hyper Text
Transfer Protocol (HTTP), it means that thanks to this protocol different
computers can send and receive information to communicate, even if they’re far
away. The browsers receive data in the form of a file, mainly three:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Hyper Text Markup Language (HTML)&lt;&#x2F;li&gt;
&lt;li&gt;Cascading Styles Sheet (CSS)&lt;&#x2F;li&gt;
&lt;li&gt;JavaScript&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;html&quot;&gt;HTML&lt;&#x2F;h3&gt;
&lt;p&gt;Helps the browser to structure data like texts or images, using a markup
language (tags). The browser can know where to put an input to type your email
or a button to subscribe to your favorite artist.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;css&quot;&gt;CSS&lt;&#x2F;h3&gt;
&lt;p&gt;It gives colors and forms to the HTML tags using selectors. It can be used to
change page’s background color, change button’s rounded borders, modify text
color, and everything your creativity can give.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;javascript&quot;&gt;JavaScript&lt;&#x2F;h3&gt;
&lt;p&gt;Combining HTML and CSS with JavaScript creates an interactive web site, or web
app (like this one). You can for example, add a button that changes the theme to
dark&#x2F;light, or store items in a shopping cart and show a number of items you
have.&lt;&#x2F;p&gt;
&lt;p&gt;For all this you need to store your files somewhere, letting people access a
computer to download all these files using their browsers, that’s the
functionality of servers.&lt;&#x2F;p&gt;
&lt;p&gt;Servers are computers that are connected to the Internet, and store files that
can be downloaded or uploaded using protocols and security rules. Some companies
like Google or Microsoft have multiple centers with many servers in different
regions of the planet, called Data Centers, and can be used with a fee for
storing your web app, these multiple Data Centers are called Cloud.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-cloud&quot;&gt;The Cloud&lt;&#x2F;h3&gt;
&lt;p&gt;Administrating a powerful computer can be difficult, but if you know how to use
it, you can save a lot of money instead of maintaining local computers that need
to be turned on 24&#x2F;7. Thanks to the cloud we can deliver the fastest apps, and
we can have a 24&#x2F;7 service for our customers with a marginal cost.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;computers-changed-humanity&quot;&gt;Computers Changed Humanity&lt;&#x2F;h2&gt;
&lt;p&gt;Computers simplifies our daily tasks, software can be easy replicated and
distributed without need of logistics like a tangible product. You just need an
Internet connection to reach someone’s project.&lt;&#x2F;p&gt;
&lt;p&gt;You don’t need a factory or natural resources like wood to produce paper, you
need a group of engineers, UX&#x2F;UI designers, digital marketers, and more IT
people to reach billions of customers.&lt;&#x2F;p&gt;
&lt;p&gt;The reason that computers are too powerful is that the marginal cost is minimal,
you don’t need to extract something from the earth to build an app, you need a
group of talented persons that uses their brains to create solutions.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="xx">
        <title>The Reason to Create a Version 2.0 of my Website</title>
        <published>2023-04-07T00:00:00+00:00</published>
        <updated>2023-04-07T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Juan Manzanero
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://juanmanzanero.com/blog/website-2-0/"/>
        <id>https://juanmanzanero.com/blog/website-2-0/</id>
        
        <content type="html" xml:base="https://juanmanzanero.com/blog/website-2-0/">&lt;p&gt;I commited some errors when creating the first version of my website, here I will share what I have learned.&lt;&#x2F;p&gt;
&lt;p&gt;The first version of my website was one of my biggest projects so fat, but
&lt;strong&gt;now&lt;&#x2F;strong&gt; as I’ve &lt;strong&gt;more&lt;&#x2F;strong&gt; &lt;strong&gt;experience&lt;&#x2F;strong&gt; as a &lt;strong&gt;Frontend&lt;&#x2F;strong&gt; Engineer, I realize I
&lt;strong&gt;didn’t&lt;&#x2F;strong&gt; do &lt;strong&gt;enough&lt;&#x2F;strong&gt; &lt;strong&gt;research&lt;&#x2F;strong&gt; into &lt;strong&gt;creating&lt;&#x2F;strong&gt; a &lt;strong&gt;web&lt;&#x2F;strong&gt; site with a
&lt;strong&gt;blog&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;client-side-rendering-csr-vs-server-side-rendering-ssr-vs-static-generation-sg&quot;&gt;Client Side Rendering (CSR) vs Server Side Rendering (SSR) vs Static Generation (SG)&lt;&#x2F;h2&gt;
&lt;p&gt;When developing a &lt;strong&gt;web&lt;&#x2F;strong&gt; &lt;strong&gt;application&lt;&#x2F;strong&gt;, you should &lt;strong&gt;think&lt;&#x2F;strong&gt; &lt;strong&gt;about&lt;&#x2F;strong&gt; the
type of &lt;strong&gt;rendering&lt;&#x2F;strong&gt; to use, while &lt;strong&gt;considering&lt;&#x2F;strong&gt; the &lt;strong&gt;requirements&lt;&#x2F;strong&gt; of the
&lt;strong&gt;problems&lt;&#x2F;strong&gt; you want to &lt;strong&gt;solve&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;client-side-rendering-csr&quot;&gt;Client Side Rendering (CSR)&lt;&#x2F;h3&gt;
&lt;p&gt;For example, a web &lt;strong&gt;application&lt;&#x2F;strong&gt; like a &lt;strong&gt;SaaS&lt;&#x2F;strong&gt; to create tasks and manage
people will have &lt;strong&gt;dynamic&lt;&#x2F;strong&gt; &lt;strong&gt;pages&lt;&#x2F;strong&gt; to show the tasks, update the cards when
is edited or deleted, show notifications, etc. In this situation, a &lt;strong&gt;CSR&lt;&#x2F;strong&gt;
would be &lt;strong&gt;better&lt;&#x2F;strong&gt;, to &lt;strong&gt;render&lt;&#x2F;strong&gt; the page &lt;strong&gt;each&lt;&#x2F;strong&gt; time the user &lt;strong&gt;request&lt;&#x2F;strong&gt;
access will &lt;strong&gt;keep&lt;&#x2F;strong&gt; the data &lt;strong&gt;updated&lt;&#x2F;strong&gt;. However, a &lt;strong&gt;CSR&lt;&#x2F;strong&gt; needs to
&lt;strong&gt;hydrate&lt;&#x2F;strong&gt; the page when is &lt;strong&gt;requested&lt;&#x2F;strong&gt;, this causes a &lt;strong&gt;slow&lt;&#x2F;strong&gt; &lt;strong&gt;first&lt;&#x2F;strong&gt;
&lt;strong&gt;load&lt;&#x2F;strong&gt;, and uses &lt;strong&gt;more&lt;&#x2F;strong&gt; &lt;strong&gt;resources&lt;&#x2F;strong&gt; of the user’s PC.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;server-side-rendering-ssr&quot;&gt;Server Side Rendering (SSR)&lt;&#x2F;h3&gt;
&lt;p&gt;This could be solved using &lt;strong&gt;SSR&lt;&#x2F;strong&gt;, this consist in &lt;strong&gt;generate&lt;&#x2F;strong&gt; the page in the
&lt;strong&gt;Server&lt;&#x2F;strong&gt; where the web app is hosted &lt;strong&gt;using&lt;&#x2F;strong&gt; all the &lt;strong&gt;power&lt;&#x2F;strong&gt; that a
&lt;strong&gt;server&lt;&#x2F;strong&gt; can provide. The problem is that a &lt;strong&gt;server&lt;&#x2F;strong&gt; is &lt;strong&gt;required&lt;&#x2F;strong&gt;, Google
Cloud provides with serverless options like App Engine or Cloud Run, but you’ll
need to learn about this services and how to deploy the project, so the
&lt;strong&gt;technical&lt;&#x2F;strong&gt; &lt;strong&gt;knowledge&lt;&#x2F;strong&gt; is &lt;strong&gt;high&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;strong&gt;disadvantage&lt;&#x2F;strong&gt; of &lt;strong&gt;CSG&lt;&#x2F;strong&gt; and &lt;strong&gt;SSR&lt;&#x2F;strong&gt; is that because &lt;strong&gt;each&lt;&#x2F;strong&gt; &lt;strong&gt;page&lt;&#x2F;strong&gt;
&lt;strong&gt;must&lt;&#x2F;strong&gt; be &lt;strong&gt;rendered&lt;&#x2F;strong&gt; on each &lt;strong&gt;request&lt;&#x2F;strong&gt;, &lt;strong&gt;web&lt;&#x2F;strong&gt; &lt;strong&gt;crawlers&lt;&#x2F;strong&gt; and
&lt;strong&gt;search&lt;&#x2F;strong&gt; &lt;strong&gt;engines&lt;&#x2F;strong&gt; such as Google’s will take &lt;strong&gt;longer&lt;&#x2F;strong&gt; to &lt;strong&gt;obtain&lt;&#x2F;strong&gt;
&lt;strong&gt;information&lt;&#x2F;strong&gt; about your page, resulting in a &lt;strong&gt;low&lt;&#x2F;strong&gt; &lt;strong&gt;SEO&lt;&#x2F;strong&gt; priority.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;static-generation-sg&quot;&gt;Static Generation (SG)&lt;&#x2F;h3&gt;
&lt;p&gt;Well, if a &lt;strong&gt;page&lt;&#x2F;strong&gt; &lt;strong&gt;doesn’t&lt;&#x2F;strong&gt; require &lt;strong&gt;fetch&lt;&#x2F;strong&gt; &lt;strong&gt;data&lt;&#x2F;strong&gt; for &lt;strong&gt;each&lt;&#x2F;strong&gt;
&lt;strong&gt;request&lt;&#x2F;strong&gt;, then you could use &lt;strong&gt;SG&lt;&#x2F;strong&gt;, this means that the &lt;strong&gt;page&lt;&#x2F;strong&gt; is
&lt;strong&gt;generated&lt;&#x2F;strong&gt; when you &lt;strong&gt;build&lt;&#x2F;strong&gt; the &lt;strong&gt;production&lt;&#x2F;strong&gt; directory &lt;strong&gt;before&lt;&#x2F;strong&gt; you
&lt;strong&gt;deploy&lt;&#x2F;strong&gt; it. The page will be generated into a HTML&#x2F;CSS&#x2F;JS one time, and if
you need to &lt;strong&gt;update&lt;&#x2F;strong&gt; the &lt;strong&gt;data&lt;&#x2F;strong&gt; in that page you’ll need to do the
&lt;strong&gt;changes&lt;&#x2F;strong&gt; and &lt;strong&gt;deploy&lt;&#x2F;strong&gt; the project. Yes, you’ll need to be more cautious
when reviewing the changes before deploying, but as the page is already
generated, &lt;strong&gt;web&lt;&#x2F;strong&gt; &lt;strong&gt;crawlers&lt;&#x2F;strong&gt; and the Google’s &lt;strong&gt;search&lt;&#x2F;strong&gt; &lt;strong&gt;engine&lt;&#x2F;strong&gt; will get
the &lt;strong&gt;info&lt;&#x2F;strong&gt; in your page &lt;strong&gt;faster&lt;&#x2F;strong&gt;, &lt;strong&gt;improving&lt;&#x2F;strong&gt; your &lt;strong&gt;SEO&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-cool-thing-about-next-js&quot;&gt;The cool thing about Next.js&lt;&#x2F;h2&gt;
&lt;p&gt;In the &lt;strong&gt;past&lt;&#x2F;strong&gt; you will require to &lt;strong&gt;think&lt;&#x2F;strong&gt; if go &lt;strong&gt;full&lt;&#x2F;strong&gt; CSR, SSR or SG,
linking your web to their respecting sections, like the app, blog, etc.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;nextjs.org&#x2F;&quot;&gt;Next.js&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; is a &lt;strong&gt;Node.js&lt;&#x2F;strong&gt; &lt;strong&gt;meta-framework&lt;&#x2F;strong&gt; that uses
&lt;strong&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;react.dev&#x2F;&quot;&gt;React.js&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; to build the UI, and provides with CSR, SSR,
SG and more, so you can generate SG fetching async data, allowing you to don’t
&lt;strong&gt;need&lt;&#x2F;strong&gt; to &lt;strong&gt;create&lt;&#x2F;strong&gt; &lt;strong&gt;every&lt;&#x2F;strong&gt; &lt;strong&gt;static&lt;&#x2F;strong&gt; &lt;strong&gt;page&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Is that the &lt;strong&gt;approach&lt;&#x2F;strong&gt; &lt;strong&gt;used&lt;&#x2F;strong&gt; for &lt;strong&gt;this&lt;&#x2F;strong&gt; &lt;strong&gt;web&lt;&#x2F;strong&gt; site, &lt;strong&gt;instead&lt;&#x2F;strong&gt; of
&lt;strong&gt;fetch&lt;&#x2F;strong&gt; the data on &lt;strong&gt;each&lt;&#x2F;strong&gt; &lt;strong&gt;request&lt;&#x2F;strong&gt;, I only &lt;strong&gt;fetch&lt;&#x2F;strong&gt; data &lt;strong&gt;when&lt;&#x2F;strong&gt; I
&lt;strong&gt;create&lt;&#x2F;strong&gt; the &lt;strong&gt;build&lt;&#x2F;strong&gt; of the project.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Each&lt;&#x2F;strong&gt; &lt;strong&gt;article&lt;&#x2F;strong&gt; is a SG page, but I use a &lt;strong&gt;template&lt;&#x2F;strong&gt; to keep every blog
similar, using &lt;strong&gt;markdown&lt;&#x2F;strong&gt; syntax for the content of the blog, and with an
&lt;strong&gt;extension&lt;&#x2F;strong&gt; of &lt;strong&gt;TailwindCSS&lt;&#x2F;strong&gt; I keep the styles consistent.&lt;&#x2F;p&gt;
&lt;p&gt;So, &lt;strong&gt;Next.js&lt;&#x2F;strong&gt; allows you to &lt;strong&gt;choose&lt;&#x2F;strong&gt; the &lt;strong&gt;rendering&lt;&#x2F;strong&gt; method for &lt;strong&gt;each&lt;&#x2F;strong&gt;
&lt;strong&gt;page&lt;&#x2F;strong&gt; in your web, this feature permits to create amazing websites in the
same project, keeping consistence and with fast load times, Next.js even lazy
loads each page and start loading when you hover a link like Home, Contact, etc.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I’ll explain in more detail the architecture of this project in the future!&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;tailwindcss-vs-mui&quot;&gt;TailwindCSS vs MUI&lt;&#x2F;h2&gt;
&lt;p&gt;I choose to use &lt;strong&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;tailwindcss.com&#x2F;&quot;&gt;TailwindCSS&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; to learn about this
CSS library, and I’m impressed the &lt;strong&gt;faster&lt;&#x2F;strong&gt; that makes the development of the
styles of a web project. &lt;strong&gt;MUI&lt;&#x2F;strong&gt; &lt;strong&gt;provides&lt;&#x2F;strong&gt; &lt;strong&gt;functionalities&lt;&#x2F;strong&gt;, but sometimes
&lt;strong&gt;gives&lt;&#x2F;strong&gt; &lt;strong&gt;problems&lt;&#x2F;strong&gt; with &lt;strong&gt;hydration&lt;&#x2F;strong&gt; like in my previous website, when you
&lt;strong&gt;first&lt;&#x2F;strong&gt; &lt;strong&gt;load&lt;&#x2F;strong&gt; the page it takes a &lt;strong&gt;time&lt;&#x2F;strong&gt; to &lt;strong&gt;show&lt;&#x2F;strong&gt; all the &lt;strong&gt;styles&lt;&#x2F;strong&gt;,
now it no longer occurs because TailwindCSS is pure CSS and the pages are
static.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;deploying-on-vercel&quot;&gt;Deploying on Vercel&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;vercel.com&quot;&gt;Vercel&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; is the company behind Next.js, and they
provides with &lt;strong&gt;hosting&lt;&#x2F;strong&gt; services &lt;strong&gt;optimized&lt;&#x2F;strong&gt; for &lt;strong&gt;Node.js&lt;&#x2F;strong&gt; apps, and as
I’m learning about Cloud Development maybe I could try to host this web like my
previous web into a Cloud Service like Cloud Run, but this time I choose to use
&lt;strong&gt;Vercel&lt;&#x2F;strong&gt; to get the &lt;strong&gt;analytics&lt;&#x2F;strong&gt; that are very useful, and as the &lt;strong&gt;hobby
plan&lt;&#x2F;strong&gt; gives me free hosting for small projects.&lt;&#x2F;p&gt;
&lt;p&gt;To deploy I use the &lt;strong&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;vercel.com&#x2F;docs&#x2F;cli&quot;&gt;Vercel CLI&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;, pretty simple
and straightforward.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;more-content-coming-soon&quot;&gt;More content coming soon!&lt;&#x2F;h2&gt;
&lt;p&gt;I’ll keep updating with posts, features and more content to share my experience,
and know I’m writing this paragraph, I think the next feature it would be a
newsletter to notify people when I create a new post. Time to work!&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
