<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Yuichi Nabeshima</title>
    <description>The latest articles on DEV Community by Yuichi Nabeshima (@yuichi_nabeshima_canada).</description>
    <link>https://dev.to/yuichi_nabeshima_canada</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1671428%2F298392e6-c0e9-48b9-975c-34fe0880f2cc.png</url>
      <title>DEV Community: Yuichi Nabeshima</title>
      <link>https://dev.to/yuichi_nabeshima_canada</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yuichi_nabeshima_canada"/>
    <language>en</language>
    <item>
      <title>Building a Full-Stack App with React Router Framework Mode, Batch Jobs, and Email Scheduling</title>
      <dc:creator>Yuichi Nabeshima</dc:creator>
      <pubDate>Tue, 13 May 2025 14:30:03 +0000</pubDate>
      <link>https://dev.to/yuichi_nabeshima_canada/building-a-full-stack-app-with-react-router-framework-mode-batch-jobs-and-email-scheduling-9pj</link>
      <guid>https://dev.to/yuichi_nabeshima_canada/building-a-full-stack-app-with-react-router-framework-mode-batch-jobs-and-email-scheduling-9pj</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I recently released a personal project: a full-stack restaurant reservation app built using React Router Framework Mode and TypeScript. In this article, I will explain the architecture I used to build the application, including how I implemented batch processing and scheduled email delivery to support real-world operational needs.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Live Demo&lt;/strong&gt;: &lt;a href="https://my-booking.tech/" rel="noopener noreferrer"&gt;https://my-booking.tech/&lt;/a&gt;&lt;br&gt;
📂 &lt;strong&gt;Article&lt;/strong&gt;: &lt;a href="https://dev.to/yuichi_nabeshima_canada/bringing-mvc-back-a-full-stack-architecture-with-react-router-frame-work-mode-3c8b"&gt;https://dev.to/yuichi_nabeshima_canada/bringing-mvc-back-a-full-stack-architecture-with-react-router-frame-work-mode-3c8b&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;For this project, the web server is a full-stack application using React Router. The architecture follows a traditional MVC-like structure, where the front-end and back-end servers are not separated but integrated into one. I implemented a custom batch process for handling data updates and other operations, deploying a dedicated batch server separate from the web server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why separate the batch server?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To prevent batch processing from consuming too much memory and impacting the web server's performance.&lt;/li&gt;
&lt;li&gt;To create an environment similar to local development for testing batch processes in production.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I deployed the app on &lt;strong&gt;fly.io&lt;/strong&gt;, which offers free-tier instances that fit within the limits for web, batch, and DB servers (three instances). However, please note that keeping the batch server always running may exceed the $5 free credit.&lt;/p&gt;

&lt;p&gt;The batch processing logic itself is implemented within the same full-stack application, and executed via command-line scripts like &lt;code&gt;npm run batch&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Here's how I defined the batch script in my package.json&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.json&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"batch"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tsx ./app/.server/batch/runBatch.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;For executing batch jobs in production, I access the batch server via &lt;code&gt;fly ssh console&lt;/code&gt; and run the job with &lt;code&gt;npm run batch&lt;/code&gt;. You can find the source code on GitHub at the link below.&lt;br&gt;
【GitHub】&lt;a href="https://github.com/YuichiNabeshima/my-booking" rel="noopener noreferrer"&gt;https://github.com/YuichiNabeshima/my-booking&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The web server is optimized for performance by using a production build before deployment. In contrast, the batch server is deployed without a build step, since it only needs to run command-line scripts and doesn’t serve client assets.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Implementing Scheduled Tasks
&lt;/h2&gt;

&lt;p&gt;With batch jobs in place, I also needed a way to schedule automatic execution at specific times or intervals. Following the recommended method from fly.io, I installed &lt;strong&gt;supercronic&lt;/strong&gt; in the Dockerfile of the batch server and added the execution logic.&lt;/p&gt;

&lt;p&gt;The key advantage here is that by running scheduled tasks at the server level, we avoid accidental execution of unnecessary tasks on development or local servers (such as sending test emails) during testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Batch Server for Email Delivery
&lt;/h2&gt;

&lt;p&gt;For example, I designed the email delivery system to not send emails instantly. Instead, email requests are added to a &lt;strong&gt;Mail Queue&lt;/strong&gt; table. A batch job runs every minute to process and send emails from the queue. The batch job processes each record, removes it from the queue, and logs it in the &lt;strong&gt;Mail Log&lt;/strong&gt; table.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Advantages of this Mail Queue Approach:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Handles bulk email deliveries more effectively by distributing the load&lt;/li&gt;
&lt;li&gt;Makes it easier to manage email logs&lt;/li&gt;
&lt;li&gt;Scalable for larger applications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, this method does have a downside: the system is not real-time, as the batch job runs only once per minute. For larger-scale systems, a job queue system like &lt;strong&gt;BullMQ&lt;/strong&gt; could be a better choice, as it allows delayed job execution, retries, and parallel processing, making the architecture more scalable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, I’ve covered the basic architecture of the app I built and discussed the email delivery system powered by batch processing. I hope this gives you some insights into handling background jobs and building full-stack applications with React Router and TypeScript.&lt;/p&gt;

&lt;p&gt;I will be posting a more detailed breakdown of the batch implementation in a future article.&lt;/p&gt;

&lt;p&gt;If you’re interested in learning more about full-stack architecture, React Router, or background job processing, feel free to reach out!&lt;/p&gt;

&lt;p&gt;Thank you for reading! 😊&lt;/p&gt;

</description>
      <category>react</category>
      <category>typescript</category>
      <category>architecture</category>
      <category>fullstack</category>
    </item>
    <item>
      <title>Bringing MVC Back: A Full-Stack Architecture with React Router Frame Work Mode</title>
      <dc:creator>Yuichi Nabeshima</dc:creator>
      <pubDate>Tue, 06 May 2025 15:52:01 +0000</pubDate>
      <link>https://dev.to/yuichi_nabeshima_canada/bringing-mvc-back-a-full-stack-architecture-with-react-router-frame-work-mode-3c8b</link>
      <guid>https://dev.to/yuichi_nabeshima_canada/bringing-mvc-back-a-full-stack-architecture-with-react-router-frame-work-mode-3c8b</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Recently, I released a full-stack restaurant reservation web app built using React Router in framework mode. In this post, I’ll introduce the architecture with a focus on the backend setup.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Live Demo&lt;/strong&gt;: &lt;a href="https://my-booking.tech/" rel="noopener noreferrer"&gt;https://my-booking.tech/&lt;/a&gt;&lt;br&gt;
📂 &lt;strong&gt;GitHub Repo&lt;/strong&gt;: &lt;a href="https://github.com/YuichiNabeshima/my-booking" rel="noopener noreferrer"&gt;https://github.com/YuichiNabeshima/my-booking&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Overall Goals for the App
&lt;/h2&gt;

&lt;p&gt;In modern web applications, which require rich user experiences and interactivity, adopting a JavaScript framework for the frontend has become the de facto standard.&lt;br&gt;&lt;br&gt;
Commonly, frontend meta-frameworks (such as Next.js, Nuxt, Remix) are used along with backend frameworks like Express.js, NestJS, or Laravel. Alternatively, serverless backend setups (e.g., AWS Lambda) are also popular.&lt;br&gt;&lt;br&gt;
For this web app, I wanted to find a middle ground between simplicity and scalability, ensuring that the architecture could handle even large-scale development while still being fast and easy to implement.&lt;/p&gt;

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

&lt;p&gt;I focused on monolithic architectures like Rails and Laravel, which are still widely used in many development environments. These architectures follow an MVC-like structure and have a class-based design. Inspired by this, I explored how to implement a similar architecture in a React-based framework that would be both simple and scalable.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why React Router?
&lt;/h2&gt;

&lt;p&gt;I chose React Router for this project because it was integrated with Remix last year, carrying forward Remix's philosophy of a web-standard SSR-focused framework. I thought it was a great fit for returning to a more traditional architecture.&lt;br&gt;&lt;br&gt;
React Router also offers flexible directory structures, which made it easier to achieve the goals of this project.&lt;/p&gt;
&lt;h2&gt;
  
  
  Treating the MVC Controller
&lt;/h2&gt;

&lt;p&gt;In React Router, you can write &lt;code&gt;loader&lt;/code&gt; functions (responsible for fetching data) and &lt;code&gt;action&lt;/code&gt; functions (responsible for updating data) in route files (e.g., &lt;code&gt;route.tsx&lt;/code&gt;).&lt;br&gt;&lt;br&gt;
These two server-side functions can be treated as GET and POST requests, with the &lt;code&gt;route.tsx&lt;/code&gt; itself acting as the controller in an MVC architecture. Since &lt;code&gt;route.tsx&lt;/code&gt; is the entry point, it doesn't include the detailed implementation of the UI but instead imports and returns the base &lt;code&gt;Page&lt;/code&gt; component, which serves as the foundation for the UI components.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// routes/top/route.tsx&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Top Page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Main landing page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Fetch server-side data&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;action&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Handle form submissions&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Page&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The directory structure is introduced in this article as well:&lt;br&gt;&lt;br&gt;
&lt;a href="https://dev.to/yuichi_nabeshima_canada/how-i-organized-my-fullstack-react-router-project-using-page-based-colocation-1nig"&gt;How I organized my full-stack React Router project&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture Diagram
&lt;/h2&gt;

&lt;p&gt;The following diagram shows how data flows from the UI to the database and back, using React Router’s loader and action functions as entry points to the backend logic.&lt;/p&gt;

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

&lt;p&gt;To illustrate how this MVC-like architecture is implemented within a single repository, here is a directory-level view of the codebase.&lt;br&gt;&lt;br&gt;
This shows how the UI, controller logic, business logic, and data access layers are all clearly separated, yet co-located in a monorepo-style structure.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Explanation of Each Layer
&lt;/h2&gt;

&lt;h3&gt;
  
  
  UI Layer
&lt;/h3&gt;

&lt;p&gt;The frontend is designed in a simple React way, with a &lt;code&gt;Page&lt;/code&gt; component at the root, from which the components are built in a tree structure.&lt;br&gt;&lt;br&gt;
As shown in the diagram, using &lt;code&gt;useLoaderData()&lt;/code&gt; allows components beneath &lt;code&gt;Page.tsx&lt;/code&gt; to access pre-fetched server-side data, without needing prop-drilling or a global state management system.&lt;br&gt;&lt;br&gt;
Since &lt;code&gt;useLoaderData()&lt;/code&gt; references cached data that has already been fetched, there’s minimal performance overhead.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Controller Layer (route.tsx)
&lt;/h3&gt;

&lt;p&gt;This layer acts as a mediator between the UI layer (pages) and the service layer, responsible for input processing and control logic:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extracting data sent from the UI layer
&lt;/li&gt;
&lt;li&gt;Performing general validations such as required field checks and email format validation
&lt;/li&gt;
&lt;li&gt;Calling the service layer to execute processing with the provided data
&lt;/li&gt;
&lt;li&gt;Handling errors based on the returned values from the service layer
&lt;/li&gt;
&lt;li&gt;Returning the result to the UI layer if no errors occur.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are the main responsibilities of the controller layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Service Layer
&lt;/h3&gt;

&lt;p&gt;The service layer contains the actual business logic.&lt;br&gt;&lt;br&gt;
In most cases, a main service class (e.g., &lt;code&gt;LoaderService&lt;/code&gt; or &lt;code&gt;ActionService&lt;/code&gt;) is called from &lt;code&gt;route.tsx&lt;/code&gt;. Within the service class, other repository layers or service classes are combined to handle the business logic.&lt;br&gt;&lt;br&gt;
For example, &lt;code&gt;loader&lt;/code&gt; calls the &lt;code&gt;LoaderService&lt;/code&gt;, and &lt;code&gt;action&lt;/code&gt; calls the &lt;code&gt;ActionService&lt;/code&gt;.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Repository Layer
&lt;/h3&gt;

&lt;p&gt;The repository layer wraps ORM, such as Prisma, and is called by the service layer.&lt;br&gt;&lt;br&gt;
The advantages of wrapping Prisma in classes instead of using it directly are:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It makes it easier to switch to another ORM in the future.
&lt;/li&gt;
&lt;li&gt;Declarative methods specific to the use case can be written in the wrapper class (e.g., &lt;code&gt;getPublishedArticle()&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;The class can be easily mocked, making it simpler to test.
By using this structure, the service layer can focus on "what to fetch" rather than being coupled to a specific DB implementation, improving maintainability and testability.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This architecture allows me to maintain a modern React UI experience while ensuring a simple, scalable, and robust backend setup.&lt;br&gt;&lt;br&gt;
I hope to dive deeper into topics such as error handling and testing strategies in a future post.  &lt;/p&gt;

&lt;p&gt;Thank you for reading!&lt;br&gt;
As I am currently exploring new career opportunities in the Vancouver area, If you're looking for someone passionate about modern full-stack development and architecture, I’d love to connect and see how I could contribute to your team. Feel free to contact me if you're looking for a developer with a strong passion for web development!&lt;/p&gt;

</description>
      <category>react</category>
      <category>fullstack</category>
      <category>backend</category>
      <category>architecture</category>
    </item>
    <item>
      <title>How I Organized My Fullstack React Router Project Using Page-Based Colocation</title>
      <dc:creator>Yuichi Nabeshima</dc:creator>
      <pubDate>Thu, 01 May 2025 18:48:46 +0000</pubDate>
      <link>https://dev.to/yuichi_nabeshima_canada/how-i-organized-my-fullstack-react-router-project-using-page-based-colocation-1nig</link>
      <guid>https://dev.to/yuichi_nabeshima_canada/how-i-organized-my-fullstack-react-router-project-using-page-based-colocation-1nig</guid>
      <description>&lt;h2&gt;
  
  
  🧩 Organizing Routes with Page-Based Colocation in React Router (Framework Mode)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;I recently built a fullstack restaurant reservation web app using &lt;a href="https://reactrouter.com/start/framework/installation" rel="noopener noreferrer"&gt;React Router framework mode&lt;/a&gt;. One of the most important design decisions was how to organize the project’s file structure.&lt;/p&gt;

&lt;p&gt;React Router allows colocating UI and backend logic per route. I took this idea further by grouping everything related to a single page — components, types, constants, server logic — under one route folder.&lt;/p&gt;

&lt;p&gt;This article shows how that structure looks and why it worked well in practice.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Live Demo:&lt;/strong&gt; &lt;a href="https://my-booking.tech/" rel="noopener noreferrer"&gt;https://my-booking.tech/&lt;/a&gt;&lt;br&gt;
📂 &lt;strong&gt;GitHub Repo:&lt;/strong&gt; &lt;a href="https://github.com/YuichiNabeshima/my-booking" rel="noopener noreferrer"&gt;https://github.com/YuichiNabeshima/my-booking&lt;/a&gt;&lt;br&gt;
👉 &lt;strong&gt;Previous article:&lt;/strong&gt; &lt;a href="https://dev.to/yuichi_nabeshima_canada/building-a-full-stack-web-app-only-with-react-router-1fah"&gt;https://dev.to/yuichi_nabeshima_canada/building-a-full-stack-web-app-only-with-react-router-1fah&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  What Is Colocation?
&lt;/h3&gt;

&lt;p&gt;Colocation means putting related files close together.&lt;/p&gt;

&lt;p&gt;Instead of separating files by type (like all components in one folder, all hooks in another), we group files by &lt;strong&gt;feature or page&lt;/strong&gt;. So everything for &lt;code&gt;/top&lt;/code&gt;, for example, lives under &lt;code&gt;routes/top/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This helps keep responsibilities clear and makes the codebase easier to navigate.&lt;/p&gt;


&lt;h3&gt;
  
  
  Example Directory Structure (with comments)
&lt;/h3&gt;

&lt;p&gt;Here’s an example file structure for a typical page like &lt;code&gt;/top&lt;/code&gt;.&lt;br&gt;
(I’m using &lt;code&gt;top/&lt;/code&gt; here just as a placeholder to keep things simple.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
└── app/
    ├── routes/
    │   ├── top/                          &lt;span class="c"&gt;# Route folder for "/top" page&lt;/span&gt;
    │   │   ├── .server/                  &lt;span class="c"&gt;# Server-only logic (e.g. DB access, API calls)&lt;/span&gt;
    │   │   ├── components/               &lt;span class="c"&gt;# Page-local UI components&lt;/span&gt;
    │   │   │   ├── Page.tsx             &lt;span class="c"&gt;# Top-level page component rendered by route.tsx&lt;/span&gt;
    │   │   │   └── articleList/         &lt;span class="c"&gt;# Nested component group for article list&lt;/span&gt;
    │   │   │       ├── ArticleList.tsx
    │   │   │       ├── useArticles.ts
    │   │   │       └── article/
    │   │   │           └── Article.tsx
    │   │   ├── constants/               &lt;span class="c"&gt;# Page-specific constants&lt;/span&gt;
    │   │   ├── schemas/                 &lt;span class="c"&gt;# Zod schemas for validation&lt;/span&gt;
    │   │   ├── types/                   &lt;span class="c"&gt;# Type definitions (e.g. props)&lt;/span&gt;
    │   │   ├── utils/                   &lt;span class="c"&gt;# Pure helper functions&lt;/span&gt;
    │   │   └── route.tsx                &lt;span class="c"&gt;# Main route file: meta, loader, action&lt;/span&gt;
    │   └── about/
    ├── .server/                         &lt;span class="c"&gt;# Global server logic&lt;/span&gt;
    ├── components/                      &lt;span class="c"&gt;# Shared UI components&lt;/span&gt;
    ├── constants/                       &lt;span class="c"&gt;# Global constants&lt;/span&gt;
    ├── types/                           &lt;span class="c"&gt;# Global types&lt;/span&gt;
    └── utils/                           &lt;span class="c"&gt;# Global utilities&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How Routing Is Set Up
&lt;/h3&gt;

&lt;p&gt;React Router maps URL paths to files in the &lt;code&gt;routes/&lt;/code&gt; directory. Here's a basic route config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;routes/top/route.tsx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;about&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;routes/about/route.tsx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each &lt;code&gt;route.tsx&lt;/code&gt; file typically exports the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;meta()&lt;/code&gt; — Sets the &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt; and description&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;loader()&lt;/code&gt; — Fetches server data&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;action()&lt;/code&gt; — Handles POST or form requests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A default React component — usually rendering &lt;code&gt;Page.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// routes/top/route.tsx&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Top Page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Main landing page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Fetch server-side data&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;action&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Handle form submissions&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Page&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  My Implementation Strategy
&lt;/h3&gt;

&lt;p&gt;When building out pages, I colocate everything related to that route inside the same folder: components, hooks, constants, and even backend logic.&lt;/p&gt;

&lt;p&gt;Here’s the principle I follow:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“Colocate first. Extract later.”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If something is only used by one page, it stays in that page’s folder.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If I realize it’s reusable, I promote it to a shared folder like &lt;code&gt;/components&lt;/code&gt; or &lt;code&gt;/utils&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This helps me avoid overengineering and lets patterns emerge naturally as the app grows.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits and Tradeoffs
&lt;/h3&gt;

&lt;h4&gt;
  
  
  ✅ Benefits
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Easy to understand — All code for a feature is in one place&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simple to scale — You don’t need complex abstractions early&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Great for onboarding — New developers can find everything quickly&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ⚠ Tradeoffs
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Some duplication early on&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Requires discipline to refactor and extract shared code&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But in my experience, these tradeoffs are worth it. The simplicity and clarity really help on real-world teams.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Using page-based colocation with React Router made development more straightforward and intuitive for me. It helps create a clean, scalable, and understandable project layout.&lt;/p&gt;

&lt;p&gt;If you're using React Router for fullstack development, I recommend trying this approach in your next project.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/YuichiNabeshima/my-booking" rel="noopener noreferrer"&gt;See the full source code on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>react</category>
      <category>fullstack</category>
      <category>webdev</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Building a Full-Stack Web App Only with React Router</title>
      <dc:creator>Yuichi Nabeshima</dc:creator>
      <pubDate>Tue, 29 Apr 2025 22:16:31 +0000</pubDate>
      <link>https://dev.to/yuichi_nabeshima_canada/building-a-full-stack-web-app-only-with-react-router-1fah</link>
      <guid>https://dev.to/yuichi_nabeshima_canada/building-a-full-stack-web-app-only-with-react-router-1fah</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;A portfolio project built to land my next software engineering opportunity — and explore how far React Router (Framework Mode) can go.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  🚀 Project Overview
&lt;/h1&gt;

&lt;p&gt;I am building a full-stack restaurant reservation platform as a portfolio project. It features both a public-facing reservation site and an admin dashboard — all built on top of React Router Framework Mode, with a PostgreSQL + Prisma backend and a modern UI stack.&lt;/p&gt;

&lt;p&gt;Although the app uses dummy data, it’s fully functional and architected like a real-world production system.&lt;/p&gt;

&lt;p&gt;🔗 Live Demo: &lt;a href="https://my-booking.tech/" rel="noopener noreferrer"&gt;https://my-booking.tech/&lt;/a&gt;&lt;br&gt;
📂 GitHub Repo: &lt;a href="https://github.com/YuichiNabeshima/my-booking" rel="noopener noreferrer"&gt;https://github.com/YuichiNabeshima/my-booking&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m currently open to software engineering roles — especially full-stack roles involving React, TypeScript, and scalable backend architecture.&lt;/p&gt;

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




&lt;h2&gt;
  
  
  🧠 Why React Router?
&lt;/h2&gt;

&lt;p&gt;React Router inherits the Remix philosophy — staying close to web standards, server-side rendering by default, and minimizing client-side overhead.&lt;br&gt;
This mirrors the traditional web model (routing, form submissions, session-based auth) while still leveraging React’s component-driven architecture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⚙️ The result: a fast, SSR-first app with minimal use of global state or client-side data fetching libraries.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The frontend is built with modern functional React, while the backend follows a more class-based, structured design — a mix that reflects real-world systems I’ve worked on and enjoy building.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧩 Features
&lt;/h2&gt;

&lt;p&gt;📅 Guests can book without creating an account&lt;/p&gt;

&lt;p&gt;🔐 Secure, unique reservation URLs via JWT&lt;/p&gt;

&lt;p&gt;🧑‍💼 Admin dashboard to manage bookings and restaurants&lt;/p&gt;

&lt;p&gt;⚡️ SSR-first architecture with minimal client-side state&lt;/p&gt;

&lt;p&gt;✅ Type-safe forms with full validation&lt;/p&gt;

&lt;h2&gt;
  
  
  🛠️ Tech Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;React Router (Framework Mode) + TypeScript&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PostgreSQL + Prisma&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Redis (Upstash) + Custom session-based auth&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JWT for reservation access&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tailwind CSS + shadcn/ui&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Zod + Conform for form validation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Amazon S3 / SES for file and email handling&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fly.io for hosting&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  👋 I'm Open to Work
&lt;/h2&gt;

&lt;p&gt;I'm currently looking for roles focused on full-stack development — particularly with React, TypeScript, and scalable backend architecture.&lt;/p&gt;

&lt;p&gt;If you’re hiring (or know someone who is), I’d love to connect!&lt;/p&gt;

&lt;p&gt;💬 I’d be happy to answer any questions about the tech choices or structure!&lt;br&gt;
Thanks for reading!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Remix with PostgreSQL and Prisma from Local Environment Setup to Deploy to Fly.io</title>
      <dc:creator>Yuichi Nabeshima</dc:creator>
      <pubDate>Sat, 27 Jul 2024 10:23:29 +0000</pubDate>
      <link>https://dev.to/yuichi_nabeshima_canada/remix-with-postgresql-and-prisma-from-local-environment-setup-to-deploy-to-flyio-5537</link>
      <guid>https://dev.to/yuichi_nabeshima_canada/remix-with-postgresql-and-prisma-from-local-environment-setup-to-deploy-to-flyio-5537</guid>
      <description>&lt;p&gt;Hi there😊&lt;br&gt;
I'm Yuichi, a &lt;a href="https://www.canadianctb.ca/" rel="noopener noreferrer"&gt;CCTB&lt;/a&gt; student and a Frontend developer.&lt;/p&gt;

&lt;p&gt;Remix is ​​a great framework and I'm really into it right now.&lt;/p&gt;

&lt;p&gt;It is &lt;code&gt;React&lt;/code&gt; framework but we can develop backend together, so it is very convenient.&lt;/p&gt;

&lt;p&gt;I am going to introduce to create base of full stack app by the &lt;code&gt;Remix&lt;/code&gt; with &lt;code&gt;PostgreSQL&lt;/code&gt; and &lt;code&gt;Prisma&lt;/code&gt; to deploy on &lt;code&gt;Fly.io&lt;/code&gt;.&lt;br&gt;
And I also try to reach &lt;strong&gt;connecting DBeaver both environment local and production&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Tools
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;macOS Sonoma 14.1.2&lt;/li&gt;
&lt;li&gt;Docker Desktop 4.32.0&lt;/li&gt;
&lt;li&gt;Node 20.16.0&lt;/li&gt;
&lt;li&gt;DBeaver 24.1.3&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Why Fly.io
&lt;/h2&gt;

&lt;p&gt;Fly.io allows you to easily deploy the Remix apps and also provides PostgreSQL.&lt;br&gt;
It has free plan, so it doesn't cost much to deploy a small project.&lt;/p&gt;
&lt;h2&gt;
  
  
  First, Install Remix
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-remix@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Where should we create your new project? =&amp;gt; &lt;strong&gt;./my-remix-app&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Initialize a new git repository? =&amp;gt; &lt;strong&gt;Yes&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Install dependencies with npm? =&amp;gt; &lt;strong&gt;Yes&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ./my-remix-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Create docker-compose.yml
&lt;/h2&gt;

&lt;p&gt;Next, create &lt;code&gt;docker-compose.yml&lt;/code&gt; on the project root for creating the PostgreSQL container for the local environment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.7"&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:latest&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_USER=postgres&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_PASSWORD=postgres&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_DB=postgres&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5432:5432"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./postgres-data:/var/lib/postgresql/data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, start the container.&lt;br&gt;
Please start the Docker Desktop before.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Install Prisma
&lt;/h2&gt;

&lt;p&gt;Install &lt;code&gt;Prisma&lt;/code&gt; to manipulate data of the database from the app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;prisma &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please initialize prisma.&lt;br&gt;
Executing the command below will create a &lt;code&gt;prisma&lt;/code&gt; directory and &lt;code&gt;.env&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx prisma init &lt;span class="nt"&gt;--datasource-provider&lt;/span&gt; postgresql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, Modify value of &lt;code&gt;DATABASE_URL&lt;/code&gt; in &lt;code&gt;.env&lt;/code&gt; to like below for connecting prisma to database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;postgresql://postgres:postgres@localhost:5432/postgres?schema=public&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This string will contain the value set in &lt;code&gt;docker-compose.yml&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;If the user name or password set in &lt;code&gt;docker-compose.yml&lt;/code&gt; are different, please change your &lt;code&gt;DATABASE_URL&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migrate Database
&lt;/h2&gt;

&lt;p&gt;Now that prism and the database are connected let's add a table to the database for testing.&lt;br&gt;
Please edit &lt;code&gt;schema.prisma&lt;/code&gt; under the &lt;code&gt;prisma&lt;/code&gt; like below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;generator client {
&lt;/span&gt;  provider = "prisma-client-js"
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;datasource db {
&lt;/span&gt;  provider = "postgresql"
  url      = env("DATABASE_URL")
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gi"&gt;+ model Post {
+   id      Int      @id @default(autoincrement())
+   name    String?
+   body    String   @db.Text
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gi"&gt;+   @@map("post")
+ }
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;@@map&lt;/code&gt; is the characters you enter here will become the table name.&lt;/p&gt;

&lt;p&gt;Then, execute migration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx prisma migrate dev &lt;span class="nt"&gt;--name&lt;/span&gt; init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can add the table to the database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect local PostgreSQL to DBeaver
&lt;/h2&gt;

&lt;p&gt;Start DBeaver and click the icon on the top left.&lt;/p&gt;

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

&lt;p&gt;Select PostgreSQL.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fitw35mro5kzksvg2wddb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fitw35mro5kzksvg2wddb.png" alt="Image description" width="800" height="643"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter &lt;code&gt;postgres&lt;/code&gt; in the Password of red circle.&lt;br&gt;
This &lt;code&gt;Database&lt;/code&gt;, &lt;code&gt;Username&lt;/code&gt;, and &lt;code&gt;Password&lt;/code&gt; are set in &lt;code&gt;docker-compose.yml&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;It is successful if there are no errors.&lt;/p&gt;

&lt;p&gt;Then, you can make sure the tables of database.&lt;br&gt;
It is successful if the &lt;code&gt;post&lt;/code&gt; table is displayed as shown in the image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdp7my1u91oi02lrng4xa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdp7my1u91oi02lrng4xa.png" alt="Image description" width="369" height="401"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Create sample Data
&lt;/h2&gt;

&lt;p&gt;Create data directly from DBeaver using SQL.&lt;/p&gt;

&lt;p&gt;Right click on the table name &lt;code&gt;post&lt;/code&gt; and select &lt;code&gt;Generate SQL&lt;/code&gt; then select the &lt;code&gt;INSERT&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;Then a modal like the image will open, so please copy the SQL inside.&lt;/p&gt;

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

&lt;p&gt;Click the SQL icon in the top left to open the SQL script and paste the SQL you copied.&lt;/p&gt;

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

&lt;p&gt;Add test text to the copied SQL and execute it using the Execute button on the left.&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;sql&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nextval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'post_id_seq'&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;regclass&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;'Henly'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'I am Henly, it is test post.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creating test data is now complete.&lt;/p&gt;

&lt;h2&gt;
  
  
  Display database data on browser
&lt;/h2&gt;

&lt;p&gt;Let's display the created test data on the screen.&lt;/p&gt;

&lt;p&gt;Please install the &lt;code&gt;@prisma/client&lt;/code&gt; for client.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @prisma/client
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please rewrite &lt;code&gt;/app/routes/_index.tsx&lt;/code&gt; as below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;LoaderFunction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@remix-run/node&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PrismaClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@prisma/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useLoaderData&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@remix-run/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LoaderFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PrismaClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findFirst&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;postData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useLoaderData&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;My app&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;postData&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;postData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;loading...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;postData&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;postData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;loading...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Please start dev server with below command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is now displayed on the screen created data.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Deploy app to Fly.io
&lt;/h2&gt;

&lt;p&gt;Now that the setup in the local environment is complete, it's time to deploy it to the Fly.io.&lt;/p&gt;

&lt;p&gt;First, register with Fly.io and register your credit card.&lt;br&gt;
Select the $0 plan.&lt;/p&gt;

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

&lt;p&gt;Next, install &lt;code&gt;flyctl&lt;/code&gt; to use fly's CLI on your local machine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;flyctl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's deploy it!!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fly launch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following question will be displayed, please select yes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Do you want to tweak these settings before proceeding? =&amp;gt; y&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then, the browser will open, so please configure the app settings.&lt;/p&gt;

&lt;p&gt;Please select the lowest CPU and memory for your web server.&lt;/p&gt;

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

&lt;p&gt;Please select development for &lt;code&gt;PostgreSQL&lt;/code&gt; as well.&lt;/p&gt;

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

&lt;p&gt;Once the browser settings are complete, the command line will start working again.&lt;br&gt;
&lt;strong&gt;The DB information will be displayed during the process, so don't forget to write it down.&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;The deployment has completed so also connect to the DB with DBeaver same as local.&lt;/p&gt;

&lt;p&gt;First, connect to DB by SSH and create new user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fly postgres connect &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;YOUR_DB_APP_NAME]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create new role(user).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;CREATE ROLE dbeaver_user WITH PASSWORD &lt;span class="s1"&gt;'newpassword'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, grant privileges to the created user.&lt;br&gt;
This time, we want to edit the database directly from DBeaver, so we will grant &lt;code&gt;SUPERUSER&lt;/code&gt; permission.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ALTER ROLE dbeaver_user SUPERUSER LOGIN&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use the command below to display a list of DBs and check the DB name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="se"&gt;\l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Terminate the DB ssh connection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When operating from local DBeaver, you need to run a proxy in the terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fly proxy 5432 &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;YOUR_DB_APP_NAME]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a new connection in DBeaver using the database name, username, and password from earlier.&lt;/p&gt;

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

&lt;p&gt;Let's create test data from SQL same as local environment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nextval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'post_id_seq'&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;regclass&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;'Yuichi'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'This is production'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It was displayed successfully!🎉&lt;br&gt;
That's it!&lt;/p&gt;

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

&lt;p&gt;If you want to fix it and deploy it again, you can deploy it with the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fly deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thank you for reading this long article😊&lt;br&gt;
Have a good Remix life!✨&lt;/p&gt;

&lt;h2&gt;
  
  
  I am looking for a job
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;As of July 2024&lt;/strong&gt;, I am looking for a job.&lt;br&gt;
My areas of expertise are React, TypeScript, Remix, Next, PHP, and WordPress.&lt;br&gt;
I'm currently a student, so I'm looking for a part-time position where I can work up to 20 hours a week.&lt;br&gt;
I'm looking for a full-time job starting next August.&lt;/p&gt;

</description>
      <category>remix</category>
      <category>postgres</category>
      <category>prisma</category>
      <category>fly</category>
    </item>
    <item>
      <title>My WordPress Template 2024 made from Vite and TypeScript</title>
      <dc:creator>Yuichi Nabeshima</dc:creator>
      <pubDate>Sat, 20 Jul 2024 20:30:08 +0000</pubDate>
      <link>https://dev.to/yuichi_nabeshima_canada/my-wordpress-template-2024-made-from-vite-and-typescript-4db8</link>
      <guid>https://dev.to/yuichi_nabeshima_canada/my-wordpress-template-2024-made-from-vite-and-typescript-4db8</guid>
      <description>&lt;p&gt;Hi there😊&lt;br&gt;
I'm Yuichi, a &lt;a href="https://www.canadianctb.ca/" rel="noopener noreferrer"&gt;CCTB&lt;/a&gt; student and a Frontend developer.&lt;/p&gt;

&lt;p&gt;I created new WordPress template for practical work.&lt;br&gt;
It is assumed that making WordPress site from scratch.&lt;br&gt;
I will share the template and its idea.&lt;/p&gt;

&lt;p&gt;【Repository】: &lt;a href="https://github.com/YuichiNabeshima/my-wordpress-template" rel="noopener noreferrer"&gt;https://github.com/YuichiNabeshima/my-wordpress-template&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Things I want to do on this template
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Do not use any JavaScript framework, keeping basic usage as WordPress.&lt;/li&gt;
&lt;li&gt;Do not use UI framework for handling various design.&lt;/li&gt;
&lt;li&gt;Each pages load CSS and JavaScript scripts as much as the page needs for reducing file size.&lt;/li&gt;
&lt;li&gt;I want to use &lt;code&gt;Vite&lt;/code&gt; for bundling.&lt;/li&gt;
&lt;li&gt;I want to split JavaScript scripts as a file as each feature.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Directory structure
&lt;/h2&gt;

&lt;p&gt;Main directories are these three.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;public&lt;/code&gt; is put the static files like &lt;code&gt;font&lt;/code&gt; or &lt;code&gt;image&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src&lt;/code&gt; is put the codes needing build and compile, like CSS using post-css or TypeScript.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;wp&lt;/code&gt; is put the production codes. When you deploy, you upload only this directory to  production server.
The assets of &lt;code&gt;public&lt;/code&gt; and &lt;code&gt;src&lt;/code&gt; will be output under the &lt;code&gt;wp/assets/&lt;/code&gt; after build command.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┣━ public ━ img/
┃        ┗━ fonts/
┃
┣━ src ━━━━ css/
┃        ┗━ ts/
┃
┣━ wp ━━━━━ assets/
┃        ┣━ index.php
┃        ┣━ front-page.php
┃        ┗━ ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Local environment
&lt;/h2&gt;

&lt;p&gt;It uses &lt;a href="https://developer.wordpress.org/block-editor/getting-started/devenv/get-started-with-wp-env/" rel="noopener noreferrer"&gt;wp-env&lt;/a&gt; for the local environment.&lt;br&gt;
It is very easy to set up and no configuration.&lt;br&gt;
We can check own site to &lt;code&gt;http://localhost:8888&lt;/code&gt; on web browser.&lt;/p&gt;
&lt;h2&gt;
  
  
  Strategy of entry point
&lt;/h2&gt;

&lt;p&gt;JS and CSS should be loaded as much as necessary for the page in order to reduce the file size as much as possible.&lt;br&gt;
In other words, it is assumed that every page has its own JS and CSS.&lt;br&gt;
Of course, if you can share files between pages, do so (like common.js)&lt;br&gt;
Each file put under the &lt;code&gt;entry_point&lt;/code&gt; directory will be output under &lt;code&gt;/wp/assets/&lt;/code&gt; with the file name unchanged after build.&lt;/p&gt;

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

&lt;p&gt;After build ...&lt;/p&gt;

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

&lt;p&gt;You need to add the arguments of &lt;code&gt;get_header()&lt;/code&gt; and &lt;code&gt;get_footer()&lt;/code&gt; for loading the each builded file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
  &lt;span class="nf"&gt;get_header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'css'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'top'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
  &lt;span class="nf"&gt;get_footer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'js'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'top'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Developing
&lt;/h2&gt;

&lt;p&gt;Since I am using &lt;code&gt;Vite&lt;/code&gt;, I want to use Vite's extremely fast development server.&lt;br&gt;
Therefore, I have devised tags that load CSS and JS.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/wp/header.php&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="no"&gt;WP_DEBUG&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="no"&gt;IS_DEV&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"http://localhost:5173/src/css/entry_point/&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;?=&lt;/span&gt;&lt;span class="nv"&gt;$css&lt;/span&gt;&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;?=&lt;/span&gt;&lt;span class="nf"&gt;get_stylesheet_directory_uri&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;/assets/css/&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;?=&lt;/span&gt;&lt;span class="nv"&gt;$css&lt;/span&gt;&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
  &lt;span class="k"&gt;endif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;/wp/footer.php&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="no"&gt;WP_DEBUG&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="no"&gt;IS_DEV&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"http://localhost:5173/@vite/client"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"http://localhost:5173/src/ts/entry_point/&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;?=&lt;/span&gt;&lt;span class="nv"&gt;$js&lt;/span&gt;&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;.ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;?=&lt;/span&gt;&lt;span class="nf"&gt;get_stylesheet_directory_uri&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;/assets/js/&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;?=&lt;/span&gt;&lt;span class="nv"&gt;$js&lt;/span&gt;&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
  &lt;span class="k"&gt;endif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During developing, we can benefit from Vite's development server by referencing &lt;code&gt;http://localhost:5137&lt;/code&gt;.&lt;br&gt;
When I start the Vite development server, what I see in my browser is &lt;code&gt;http://localhost:8888&lt;/code&gt;.&lt;br&gt;
&lt;strong&gt;&lt;code&gt;http://localhost:5173&lt;/code&gt; shows nothing&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  WP_DEBUG variable
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;WP_DEBUG&lt;/code&gt; variable in if statement is set to &lt;code&gt;true&lt;/code&gt; in &lt;code&gt;wp-env.json&lt;/code&gt;, so even if you accidentally deploy with &lt;code&gt;IS_DEBUG&lt;/code&gt; set to &lt;code&gt;true&lt;/code&gt;, it will not enter debug mode.&lt;/p&gt;
&lt;h3&gt;
  
  
  IS_DEBUG variable
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;IS_DEBUG&lt;/code&gt; variable is a global variable that you manually set in &lt;code&gt;functions.php&lt;/code&gt;.&lt;br&gt;
The default is &lt;code&gt;true&lt;/code&gt;, so the local environment refers to the Vite's development server.&lt;br&gt;
If you want to check the built JS and CSS in the local environment, please set it to &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Styling
&lt;/h2&gt;
&lt;h2&gt;
  
  
  CSS concept
&lt;/h2&gt;

&lt;p&gt;The reason of CSS is difficult is because the scope is always global.&lt;br&gt;
Therefore, I want to propose that you don't have to make CSS commonly, put the CSS codes for each pages.&lt;br&gt;
When the number of common CSS increases, in many cases, you will spend a lot of time searching for a class of common style somewhere when you add new page.&lt;/p&gt;
&lt;h3&gt;
  
  
  CSS directory structure
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┣━　CSS　┯━　common　━━━━━┳━　reset.css
┃ 　　　　　　　　┃　　　　　　　　　　　　　　　　　　　　　　　　　　┣━　base.css
┃　　　　　　　　　　┃　　　　　　　　　　　　　　　　　　　　　　　　　　┗━　variable.css
┃　　　　　　　　　　┃
┃　　　　　　　　　　┣━　entry_point　┳━　top.css
┃　　    ┃　　　　　　　　　　　　　　　　　　　　　　　　　　┗━　about.css
┃　　　　　　　　　　┣━　mixin　━━━━━━━━　media.css
┃　　　　　　　　　　┗━　page　━━━━━━━┳━　top.css
┃　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　┗━　about.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;As mentioned above CSS creates a single file dedicated to each page.&lt;br&gt;
The CSS files under the &lt;code&gt;entry_point&lt;/code&gt; gather all the CSS codes like below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;'../mixin/media.css'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;'../common/reset.css'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;'../common/variable.css'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;'../common/base.css'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;'../page/top.css'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The main styles of the page are put in the CSS file under &lt;code&gt;page&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There are some things you really want to commonly, such as common layouts, headings, and buttons.&lt;br&gt;
In that case, please make an appropriate file under the &lt;code&gt;mixin&lt;/code&gt; directory and import it to &lt;code&gt;entry_point&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┣━　mixin　┯　button.css
┃       ┗　layout.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;/src/css/entry_point/top.css&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;'../mixin/media.css'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;'../mixin/button.css'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="nt"&gt;import&lt;/span&gt; &lt;span class="nt"&gt;here&lt;/span&gt;

&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;'../common/reset.css'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;'../common/variable.css'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;'../common/base.css'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;'../page/top.css'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;/src/css/page/top.css&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.btn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;@mixin&lt;/span&gt; &lt;span class="err"&gt;btn;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  JS
&lt;/h2&gt;

&lt;p&gt;I will explain how to add JS feature in this template.&lt;/p&gt;

&lt;h3&gt;
  
  
  JS directory structure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┣━　ts　┳━　entry_point/　━━　top.ts
┃　　　　　　　　┣━　modules/　━━━━━━　alert.ts
┃　　　　　　　　┗━　register_module.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How to add JS feature
&lt;/h3&gt;

&lt;p&gt;First, add the &lt;code&gt;data-module&lt;/code&gt; attribute to a HTML tag, which is the starting point of the event firing.&lt;br&gt;
The value of &lt;code&gt;data-module&lt;/code&gt; is assigned the function name which you want to add as JS feature(this will be explained later).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt;
  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn"&lt;/span&gt;
  &lt;span class="na"&gt;data-module=&lt;/span&gt;&lt;span class="s"&gt;"alert"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;alert&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, create a ts file for the feature you want to add under &lt;code&gt;/src/ts/modules/&lt;/code&gt; and define the function in it, example is below.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/src/ts/modules/alert.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HTMLElement&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click button!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The argument of the function will be passed the DOM which you assigned the &lt;code&gt;data-module&lt;/code&gt; attribute before, so you can use the DOM for making feature, like add event.&lt;/p&gt;

&lt;p&gt;Finally, register the created function in the file under &lt;code&gt;entry_point&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/src/ts/entry_point/top.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;registerModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../register_module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;alert&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../modules/alert&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;registerModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;That's it! You can use JS feature you created.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pass the value from html
&lt;/h3&gt;

&lt;p&gt;If you want to pass variables from html, pass them in json format to the &lt;code&gt;data-options&lt;/code&gt; attribute.&lt;br&gt;
Anything other than json will result in an error.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/wp/front-page.php&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"alert-btn"&lt;/span&gt;
    &lt;span class="na"&gt;data-module=&lt;/span&gt;&lt;span class="s"&gt;"alert"&lt;/span&gt;
    &lt;span class="na"&gt;data-options=&lt;/span&gt;&lt;span class="s"&gt;'{
      "alertText": "I am from earth."
    }'&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Alert!
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;/src/ts/modules/alert.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Opts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;alertText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HTMLElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Opts&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alertText&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Responsive
&lt;/h3&gt;

&lt;p&gt;If you want to only run the module when device is PC or Smart phone.&lt;br&gt;
You can use &lt;code&gt;data-only&lt;/code&gt; attribute, there are 2 options which &lt;code&gt;pc&lt;/code&gt; or &lt;code&gt;sp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Display width&lt;br&gt;&lt;br&gt;
pc &amp;gt;= 768px&lt;br&gt;&lt;br&gt;
sp &amp;lt;  768px&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"alert-btn"&lt;/span&gt;
    &lt;span class="na"&gt;data-module=&lt;/span&gt;&lt;span class="s"&gt;"alert"&lt;/span&gt;
    &lt;span class="na"&gt;data-options=&lt;/span&gt;&lt;span class="s"&gt;'{
      "alertText": "I am from earth."
    }'&lt;/span&gt;
    &lt;span class="na"&gt;data-only=&lt;/span&gt;&lt;span class="s"&gt;"pc"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Alert PC only!
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you want to put multiple modules on a tag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"alert-btn"&lt;/span&gt;
    &lt;span class="na"&gt;data-module=&lt;/span&gt;&lt;span class="s"&gt;"alert another-alert"&lt;/span&gt;
    &lt;span class="na"&gt;data-options=&lt;/span&gt;&lt;span class="s"&gt;'{
      "alert": {
        "alertText": "message"
      },
      "another-alert": {
        "afterText": "after message"
      }
    }'&lt;/span&gt;
    &lt;span class="na"&gt;data-only=&lt;/span&gt;&lt;span class="s"&gt;'{
      "alert": "pc",
      "another-alert": "sp"
    }'&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Multiple module
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How was my new WordPress template? I would be happy if you could use it and give me feedback if you like!&lt;/p&gt;

&lt;h2&gt;
  
  
  I am looking for a job
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;As of July 2024&lt;/strong&gt;, I am looking for a job.&lt;br&gt;
My areas of expertise are React, TypeScript, Remix, Next, PHP, and WordPress.&lt;br&gt;
I'm currently a student, so I'm looking for a job position which can be a project - based.&lt;br&gt;
I'm looking for a full-time job starting next August.&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>vite</category>
      <category>typescript</category>
      <category>php</category>
    </item>
  </channel>
</rss>
