<?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>Forem: EneasLari</title>
    <description>The latest articles on Forem by EneasLari (@eneaslari).</description>
    <link>https://forem.com/eneaslari</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%2F338774%2F2826988a-be5b-4f6b-9c86-dba259621fdb.jpg</url>
      <title>Forem: EneasLari</title>
      <link>https://forem.com/eneaslari</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/eneaslari"/>
    <language>en</language>
    <item>
      <title>🐳 The Complete Guide to Dockerizing a Node.js + Express App with Database &amp; File Uploads</title>
      <dc:creator>EneasLari</dc:creator>
      <pubDate>Wed, 13 Aug 2025 19:55:50 +0000</pubDate>
      <link>https://forem.com/eneaslari/the-complete-guide-to-dockerizing-a-nodejs-express-app-with-database-file-uploads-1nck</link>
      <guid>https://forem.com/eneaslari/the-complete-guide-to-dockerizing-a-nodejs-express-app-with-database-file-uploads-1nck</guid>
      <description>&lt;p&gt;This guide explains &lt;strong&gt;how to build, run, and persist&lt;/strong&gt; a Node.js + Express application inside Docker — with support for &lt;strong&gt;MongoDB&lt;/strong&gt;, &lt;strong&gt;PostgreSQL&lt;/strong&gt;, and &lt;strong&gt;file uploads&lt;/strong&gt; — and also clarifies the relationship between &lt;strong&gt;images&lt;/strong&gt;, &lt;strong&gt;containers&lt;/strong&gt;, and &lt;strong&gt;volumes&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;1. Big Picture: Images → Containers → Volumes&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If Docker was a kitchen:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Docker Concept&lt;/th&gt;
&lt;th&gt;Kitchen Analogy&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Image&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Recipe&lt;/td&gt;
&lt;td&gt;Instructions + ingredients for your app&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Container&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Prepared Meal&lt;/td&gt;
&lt;td&gt;A running instance of the recipe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Volume&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fridge/Pantry&lt;/td&gt;
&lt;td&gt;Where persistent ingredients are kept&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Key rules:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Images&lt;/strong&gt; are &lt;strong&gt;read-only&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Containers&lt;/strong&gt; are &lt;strong&gt;ephemeral&lt;/strong&gt; — delete them, data is gone unless stored in a volume.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Volumes&lt;/strong&gt; survive container restarts and recreate.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Diagram: How They Work Together
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   Image: my-node-app          Image: mongo:6            Image: postgres:16
+----------------------+  +---------------------+  +---------------------+
| code + deps          |  | mongo binary + init |  | postgres binary + init|
+----------------------+  +---------------------+  +---------------------+
         |                         |                         |
         v                         v                         v
Container: app            Container: mongo          Container: postgres
(ephemeral FS)            (/data/db)                (/var/lib/postgresql)
         |                         |                         |
         v                         v                         v
  Volume: uploads          Volume: mongo_data       Volume: pg_data
 (user files)              (MongoDB storage)        (Postgres storage)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;2. Why Use Docker for Node.js Apps&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Consistent environment for development, testing, and production.&lt;/li&gt;
&lt;li&gt;No "works on my machine" headaches.&lt;/li&gt;
&lt;li&gt;Easy to ship and run anywhere.&lt;/li&gt;
&lt;li&gt;Built-in isolation between services (app, DB, admin tools).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;3. Project Structure Example&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;myapp/
  src/
    index.js
    routes/
  package.json
  Dockerfile
  docker-compose.yml
  .env
  uploads/          # Will be mounted to a volume in production
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;4. Dockerfile for Node.js + Express&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:20-alpine&lt;/span&gt;

&lt;span class="c"&gt;# Create app directory&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="c"&gt;# Install dependencies first (layer caching)&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm ci &lt;span class="nt"&gt;--omit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dev

&lt;span class="c"&gt;# Copy app code&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="c"&gt;# Environment variables&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; NODE_ENV=production&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; PORT=3000&lt;/span&gt;

&lt;span class="c"&gt;# Create uploads folder and fix permissions&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /app/uploads &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; node:node /app
&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; node&lt;/span&gt;

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["node", "src/index.js"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;5. docker-compose.yml with MongoDB, PostgreSQL &amp;amp; File Uploads&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.env&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;3000:3000"&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;uploads:/app/uploads&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mongo&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;postgres&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;unless-stopped&lt;/span&gt;

  &lt;span class="na"&gt;mongo&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;mongo:6&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;mongo_data:/data/db&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;unless-stopped&lt;/span&gt;

  &lt;span class="na"&gt;mongo-express&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;mongo-express:1&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;8081:8081"&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;ME_CONFIG_MONGODB_SERVER=mongo&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ME_CONFIG_BASICAUTH=false&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mongo&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:16&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_DB=mydb&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_USER=app&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_PASSWORD=app&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;pg_data:/var/lib/postgresql/data&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;unless-stopped&lt;/span&gt;

  &lt;span class="na"&gt;pgadmin&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;dpage/pgadmin4:8&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;8082:80"&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;PGADMIN_DEFAULT_EMAIL=admin@example.com&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;PGADMIN_DEFAULT_PASSWORD=secret&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&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&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;uploads&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;mongo_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pg_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;6. Environment File Example (.env)&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NODE_ENV=production
PORT=3000

DB_CLIENT=mongo
MONGO_URI=mongodb://mongo:27017/mydb

# PostgreSQL alternative
POSTGRES_URI=postgres://app:app@postgres:5432/mydb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;7. How to Run&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Build and start all services&lt;/span&gt;
docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--build&lt;/span&gt;

&lt;span class="c"&gt;# Stop everything&lt;/span&gt;
docker compose down

&lt;span class="c"&gt;# View logs&lt;/span&gt;
docker compose logs &lt;span class="nt"&gt;-f&lt;/span&gt; app

&lt;span class="c"&gt;# Enter app container&lt;/span&gt;
docker compose &lt;span class="nb"&gt;exec &lt;/span&gt;app sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;8. Volumes in Practice&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;uploads&lt;/strong&gt; → holds all user-uploaded files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;mongo_data&lt;/strong&gt; → stores MongoDB’s database files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;pg_data&lt;/strong&gt; → stores PostgreSQL’s database files.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even if you run:&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 down
docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your DB data and uploaded files remain intact because they’re in &lt;strong&gt;named volumes&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;9. Security Tips&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Never commit &lt;code&gt;.env&lt;/code&gt; files with passwords to Git.&lt;/li&gt;
&lt;li&gt;Do not expose DB ports to the internet in production.&lt;/li&gt;
&lt;li&gt;Use specific image versions (&lt;code&gt;mongo:6.0.13&lt;/code&gt;, not just &lt;code&gt;mongo:latest&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Run app as a non-root user in Dockerfile.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;10. Final Takeaways&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Image&lt;/strong&gt; = blueprint for your app.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Container&lt;/strong&gt; = running copy of that blueprint.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Volume&lt;/strong&gt; = persistent storage for data that must survive restarts.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;docker-compose&lt;/strong&gt; to orchestrate app + DB + admin tools.&lt;/li&gt;
&lt;li&gt;Always separate dev and prod configs.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  121 Docker Commands (with Explanations)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Build the image&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; myapp &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-t myapp&lt;/code&gt; → tags the image name.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Run a container&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; myapp-container &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:3000 myapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-d&lt;/code&gt; → detached mode.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-p 3000:3000&lt;/code&gt; → map port 3000 host → container.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;List containers&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Stop a container&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker stop myapp-container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Remove a container&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;rm &lt;/span&gt;myapp-container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;List images&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker images
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Remove an image&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker rmi myapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;List volumes&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Inspect a volume&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume inspect uploads
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Remove a volume&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume &lt;span class="nb"&gt;rm &lt;/span&gt;uploads
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  12. Running with Docker Compose
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Start all services&lt;/strong&gt;&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;span class="nt"&gt;--build&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Stop all services&lt;/strong&gt;&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 down
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Stop and remove with volumes&lt;/strong&gt;&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 down &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Check logs&lt;/strong&gt;&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 logs &lt;span class="nt"&gt;-f&lt;/span&gt; app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  13. Migrating to Another Server
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Backup volumes&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; uploads:/data &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nv"&gt;$PWD&lt;/span&gt;:/backup alpine &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-czf&lt;/span&gt; /backup/uploads.tar.gz &lt;span class="nt"&gt;-C&lt;/span&gt; /data &lt;span class="nb"&gt;.&lt;/span&gt;

docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; mongo_data:/data &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nv"&gt;$PWD&lt;/span&gt;:/backup alpine &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-czf&lt;/span&gt; /backup/mongo_data.tar.gz &lt;span class="nt"&gt;-C&lt;/span&gt; /data &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Restore volumes&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; uploads:/data &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nv"&gt;$PWD&lt;/span&gt;:/backup alpine &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-xzf&lt;/span&gt; /backup/uploads.tar.gz &lt;span class="nt"&gt;-C&lt;/span&gt; /data

docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; mongo_data:/data &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nv"&gt;$PWD&lt;/span&gt;:/backup alpine &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-xzf&lt;/span&gt; /backup/mongo_data.tar.gz &lt;span class="nt"&gt;-C&lt;/span&gt; /data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  14. Summary of Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;named volumes&lt;/strong&gt; for persistence (DB, uploads).&lt;/li&gt;
&lt;li&gt;Separate &lt;strong&gt;app&lt;/strong&gt;, &lt;strong&gt;DB&lt;/strong&gt;, and &lt;strong&gt;admin&lt;/strong&gt; into their own containers.&lt;/li&gt;
&lt;li&gt;Keep sensitive data in &lt;code&gt;.env&lt;/code&gt;, not in code.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;docker-compose.yml&lt;/code&gt; for multi-service orchestration.&lt;/li&gt;
&lt;li&gt;Always &lt;code&gt;.dockerignore&lt;/code&gt; &lt;code&gt;node_modules&lt;/code&gt; if installing inside the container.&lt;/li&gt;
&lt;li&gt;Avoid running containers as &lt;code&gt;root&lt;/code&gt; in production.&lt;/li&gt;
&lt;li&gt;Use lightweight base images (&lt;code&gt;node:alpine&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>docker</category>
    </item>
    <item>
      <title>From Burnout to Balance: Rediscovering Energy in Game Dev, Fitness, and Life</title>
      <dc:creator>EneasLari</dc:creator>
      <pubDate>Fri, 07 Feb 2025 11:40:23 +0000</pubDate>
      <link>https://forem.com/eneaslari/from-burnout-to-balance-rediscovering-energy-in-game-dev-fitness-and-life-12o</link>
      <guid>https://forem.com/eneaslari/from-burnout-to-balance-rediscovering-energy-in-game-dev-fitness-and-life-12o</guid>
      <description>&lt;p&gt;The start of 2025 didn’t go as I had hoped. On New Year’s Eve, I caught COVID, and I was down with a fever for a whole week. It completely drained my energy and threw me off track. I had big plans to kick off the year strong, but instead, I spent the first days of 2025 feeling exhausted and unmotivated. It’s been tough trying to get back into my routine after that. &lt;/p&gt;

&lt;p&gt;Around this time last year, I was juggling everything—working full-time as a programmer, developing my game, taking saxophone lessons, hitting the gym twice a day, and even keeping up with my personal blog, posting every week. Somehow, I managed to do it all at once, and I felt unstoppable. It was like I had endless energy, constantly moving from one thing to the next without slowing down.  &lt;/p&gt;

&lt;p&gt;But looking back, I can see that I was burning out without even realizing it. I was caught up in the momentum, pushing forward because it felt good to be productive. I didn’t notice how much I was draining myself because I was too busy chasing progress. Now that I’ve hit a wall, I can finally see that I wasn’t invincible—I was just running on borrowed energy.&lt;/p&gt;

&lt;p&gt;Being sick and losing some of my physical energy made me want to rest for a few days—which I thought was completely fine. But without realizing it, those few days of rest slowly turned into a lack of motivation. The more I stayed inactive, the harder it became to start again.  &lt;/p&gt;

&lt;p&gt;I’ve come to realize that even rest needs discipline. It’s like walking downhill—if you’re not careful, you can pick up too much speed and end up at the bottom before you even notice. Rest is necessary, but if you don’t set some limits, it can easily turn into stagnation. Finding the balance between recovery and getting stuck is still something I’m trying to figure out.  &lt;/p&gt;

&lt;p&gt;Pushing myself to the limit last year felt amazing. I was making progress in so many areas—getting stronger, improving my skills, and feeling productive every single day. It was rewarding to see how much I could handle and how far I could push myself. But as great as it felt, it wasn’t something I could keep up forever. I was running on pure momentum, not realizing that I was slowly wearing myself down. At the time, I didn’t see it, but now I understand that going all-in without proper balance eventually catches up with you.&lt;/p&gt;

&lt;p&gt;Lately, as I’ve been refactoring my space match-three game, I’ve realized I need to do the same with my life. Just like cleaning up messy code makes a game run smoother, adjusting my habits and expectations can help me regain balance. In coding, you optimize performance by removing unnecessary processes—just like in life, where cutting out what drains you can help restore energy. That’s why, for now, I’ve stopped saxophone lessons, work out mostly once a day instead of twice, and allow myself some time to relax by watching series or reading—things I hadn’t done in years. But this isn’t permanent. Eventually, I want my busy schedule back, but I don’t want to rush into everything at once. Instead, I’m focusing on rebuilding my habits one by one, making sure they’re sustainable this time. Just like in game development, small, careful improvements lead to long-term success.&lt;/p&gt;

&lt;p&gt;Burning myself out didn’t just drain my energy—it also made my thinking foggy and unorganized. When you’re constantly moving from one thing to the next without a break, your mind never gets the chance to slow down and process everything. I’ve realized that this lack of clarity is one of the biggest things I need to fix because it adds unnecessary stress and takes away the feeling of accomplishment. When your thoughts are scattered, you don’t have time to step back, recognize your progress, or even enjoy the things you’ve worked so hard for. Instead, it all blurs together into a cycle of doing more without feeling more. Getting back to a clear, focused mindset is just as important as rebuilding my habits—it’s what will help me move forward without feeling lost in the process. &lt;/p&gt;

&lt;p&gt;So, after pushing myself to the limit, burning out, and then accidentally slipping into full-on rest mode, I’m now trying to find a balance. I know I can’t just snap my fingers and get all my energy and motivation back overnight, but I also don’t want to stay stuck in this sluggish state.  &lt;/p&gt;

&lt;p&gt;The plan? Take things one step at a time. Rebuild my habits slowly, give myself room to breathe, and actually enjoy the process instead of just rushing through it. I still want to be productive, but I also don’t want to end up back where I started—feeling exhausted and running on fumes.  &lt;/p&gt;

&lt;p&gt;And if I ever start slipping again? Well, I’ll just remind myself that even the best games need a reset once in a while.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>How to Open Doors Like a Gentleman in Unity</title>
      <dc:creator>EneasLari</dc:creator>
      <pubDate>Tue, 27 Aug 2024 17:24:39 +0000</pubDate>
      <link>https://forem.com/eneaslari/how-to-open-doors-like-a-gentleman-in-unity-4c8k</link>
      <guid>https://forem.com/eneaslari/how-to-open-doors-like-a-gentleman-in-unity-4c8k</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Doors are essential elements in many games, allowing players to navigate between different areas. Today, I’ll show you how to create a simple, yet functional, door that opens and closes when the player approaches and interacts with it. This easy-to-follow tutorial is perfect for beginners looking to add more interactivity to their Unity projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unity 2020.3.0f1 or later.&lt;/li&gt;
&lt;li&gt;Basic understanding of C# scripting.&lt;/li&gt;
&lt;li&gt;A simple 3D model of a door (In this tutorial we will use ProBuilder).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Crate a new Unity Project&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a new Unity project.&lt;/li&gt;
&lt;/ul&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%2Feneaslari.com%2F43c7d6a9-5cdd-4597-901e-51bdfeeab9d4.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%2Feneaslari.com%2F43c7d6a9-5cdd-4597-901e-51bdfeeab9d4.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Download StarterAssets - First Person Pack&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Visit &lt;a href="https://assetstore.unity.com/packages/essentials/starterassets-firstperson-updates-in-new-charactercontroller-pac-196525" rel="noopener noreferrer"&gt;StarterAssets - First Person&lt;/a&gt; .&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click Add to my Assets and then Open in Unity&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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%2Feneaslari.com%2F62830641-0510-462f-8c92-e4ce4e579940.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%2Feneaslari.com%2F62830641-0510-462f-8c92-e4ce4e579940.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download and import to your project&lt;/li&gt;
&lt;/ul&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%2Feneaslari.com%2F0115f55e-bd99-425c-9dad-96cd98e37519.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%2Feneaslari.com%2F0115f55e-bd99-425c-9dad-96cd98e37519.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now open the playground scene from the Starter Pack ( Assets &amp;gt; StarterAssets &amp;gt; FirstPersonController &amp;gt; Scenes)&lt;/li&gt;
&lt;li&gt;If you Press Play you can roam through scene in FPS&lt;/li&gt;
&lt;/ul&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%2Feneaslari.com%2Fce6092aa-f6b5-4ac3-94cd-aa77dde469f8.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%2Feneaslari.com%2Fce6092aa-f6b5-4ac3-94cd-aa77dde469f8.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&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%2Feneaslari.com%2F7e51ea54-1bc9-49b1-94ee-5eab85dc3280.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%2Feneaslari.com%2F7e51ea54-1bc9-49b1-94ee-5eab85dc3280.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Create a door with ProBuilder&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Next we need ProBuilder to make a simple door. Or you can download a door model from Asset store.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In order to download Probuilder &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on Window &amp;gt; Package Manager &amp;gt; In packages select Unity Registry then search for probuilder&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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%2Feneaslari.com%2F9c40a888-4f57-4c47-a382-40c558615ce1.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%2Feneaslari.com%2F9c40a888-4f57-4c47-a382-40c558615ce1.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lets create a simple door with ProBuilder:&lt;/li&gt;
&lt;/ul&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%2Feneaslari.com%2F56e3625f-4711-480a-bece-8ec71967f4c4.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%2Feneaslari.com%2F56e3625f-4711-480a-bece-8ec71967f4c4.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&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%2Feneaslari.com%2Fa63c9a4b-f475-4fc7-b4db-8841ae64bb73.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%2Feneaslari.com%2Fa63c9a4b-f475-4fc7-b4db-8841ae64bb73.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As you can see from the image above you need two different object to make a door , frame and the actual door&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the auto opening and close door you will need an trigger also&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%2Feneaslari.com%2Fab9bbc4c-88e8-445e-8bde-59395e685237.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%2Feneaslari.com%2Fab9bbc4c-88e8-445e-8bde-59395e685237.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&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%2Feneaslari.com%2F3328b151-b935-465f-94ff-ab29fb70b5e1.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%2Feneaslari.com%2F3328b151-b935-465f-94ff-ab29fb70b5e1.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make mesh collider &lt;code&gt;IsTrigger = true&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%2Feneaslari.com%2F286fdb82-961b-44a7-a197-ac7f700046ef.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%2Feneaslari.com%2F286fdb82-961b-44a7-a197-ac7f700046ef.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Lets add some scripts&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We will need three scripts 

&lt;ul&gt;
&lt;li&gt;Door.cs&lt;/li&gt;
&lt;li&gt;PlayerActions.cs&lt;/li&gt;
&lt;li&gt;DoorTrigger.cs&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lets Create them on by one: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; Door.cs:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEngine&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Door&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MonoBehaviour&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;IsOpen&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SerializeField&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;IsRotatingDoor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SerializeField&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;Speed&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Rotation Configs"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SerializeField&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;RotationAmount&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;90f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SerializeField&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;ForwardDirection&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sliding Configs"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SerializeField&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;Vector3&lt;/span&gt; &lt;span class="n"&gt;SlideDirection&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Vector3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;back&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SerializeField&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;SlideAmount&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1.9f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;Vector3&lt;/span&gt; &lt;span class="n"&gt;StartRotation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;Vector3&lt;/span&gt; &lt;span class="n"&gt;StartPosition&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;Vector3&lt;/span&gt; &lt;span class="n"&gt;Forward&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;Coroutine&lt;/span&gt; &lt;span class="n"&gt;AnimationCoroutine&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Awake&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;StartRotation&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rotation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eulerAngles&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="c1"&gt;// Since "Forward" actually is pointing into the door frame, choose a direction to think about as "forward" &lt;/span&gt;
        &lt;span class="n"&gt;Forward&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;StartPosition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Vector3&lt;/span&gt; &lt;span class="n"&gt;UserPosition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;IsOpen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AnimationCoroutine&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;StopCoroutine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AnimationCoroutine&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IsRotatingDoor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;dot&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Vector3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Forward&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UserPosition&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;normalized&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Dot: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"N3"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;AnimationCoroutine&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;StartCoroutine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;DoRotationOpen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;AnimationCoroutine&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;StartCoroutine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;DoSlidingOpen&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="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;IEnumerator&lt;/span&gt; &lt;span class="nf"&gt;DoRotationOpen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;ForwardAmount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Quaternion&lt;/span&gt; &lt;span class="n"&gt;startRotation&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rotation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Quaternion&lt;/span&gt; &lt;span class="n"&gt;endRotation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ForwardAmount&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;ForwardDirection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;endRotation&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Quaternion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Euler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Vector3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;StartRotation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;RotationAmount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;endRotation&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Quaternion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Euler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Vector3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;StartRotation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;RotationAmount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;IsOpen&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rotation&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Quaternion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Slerp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;startRotation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;endRotation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deltaTime&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Speed&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;private&lt;/span&gt; &lt;span class="n"&gt;IEnumerator&lt;/span&gt; &lt;span class="nf"&gt;DoSlidingOpen&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Vector3&lt;/span&gt; &lt;span class="n"&gt;endPosition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StartPosition&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;SlideAmount&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SlideDirection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Vector3&lt;/span&gt; &lt;span class="n"&gt;startPosition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;IsOpen&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Vector3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Lerp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;startPosition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;endPosition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deltaTime&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Speed&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;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IsOpen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AnimationCoroutine&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;StopCoroutine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AnimationCoroutine&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IsRotatingDoor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;AnimationCoroutine&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;StartCoroutine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;DoRotationClose&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;AnimationCoroutine&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;StartCoroutine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;DoSlidingClose&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="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;IEnumerator&lt;/span&gt; &lt;span class="nf"&gt;DoRotationClose&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Quaternion&lt;/span&gt; &lt;span class="n"&gt;startRotation&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rotation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Quaternion&lt;/span&gt; &lt;span class="n"&gt;endRotation&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Quaternion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Euler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;StartRotation&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;IsOpen&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rotation&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Quaternion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Slerp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;startRotation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;endRotation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deltaTime&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Speed&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This script handles the logic for a door that can either rotate or slide when opened or closed. The door's behavior is determined by the IsRotatingDoor flag, and the animation is controlled by coroutines to smoothly transition between states. The Open and Close methods can be triggered by other scripts or events in your game, such as player input or triggers.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PlayerActions.cs:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEngine&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PlayerActions&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MonoBehaviour&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SerializeField&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;Transform&lt;/span&gt; &lt;span class="n"&gt;Camera&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SerializeField&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;MaxUseDistance&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;5f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SerializeField&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;LayerMask&lt;/span&gt; &lt;span class="n"&gt;UseLayers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnUse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Physics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Raycast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Camera&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Camera&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;RaycastHit&lt;/span&gt; &lt;span class="n"&gt;hit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MaxUseDistance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;UseLayers&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;collider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TryGetComponent&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Door&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;Door&lt;/span&gt; &lt;span class="n"&gt;door&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;door&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsOpen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;door&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="k"&gt;else&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;door&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&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="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;This script allows a player to interact with doors in the game by checking if a door is within a certain distance and then opening or closing it based on its current state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEngine&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DoorTrigger&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MonoBehaviour&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SerializeField&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;Door&lt;/span&gt; &lt;span class="n"&gt;Door&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnTriggerEnter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Collider&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TryGetComponent&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CharacterController&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;CharacterController&lt;/span&gt; &lt;span class="n"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;Door&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsOpen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Door&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&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="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnTriggerExit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Collider&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TryGetComponent&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CharacterController&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;CharacterController&lt;/span&gt; &lt;span class="n"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Door&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsOpen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Door&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Close&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="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;This script uses a trigger collider to automatically open and close a door when a character enters or exits the trigger zone. The &lt;code&gt;OnTriggerEnter&lt;/code&gt; method opens the door when the character enters the trigger, and the &lt;code&gt;OnTriggerExit&lt;/code&gt; method closes the door when the character leaves the trigger.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Attach the scripts&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;Lets Attach the scripts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Attach the Door.cs script to the Door GameObject&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&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%2Feneaslari.com%2F7d576f55-a0a5-4755-8a54-13fa3b97aab4.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%2Feneaslari.com%2F7d576f55-a0a5-4755-8a54-13fa3b97aab4.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see from the inspector there is a flag IsRotatingDoor which if its true the door will open rotating if it's false it will slide.&lt;/p&gt;

&lt;p&gt;After there are configuration variables for rotation and for sliding. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The RotationAmount variable sets the angle that the door will open&lt;/li&gt;
&lt;li&gt;The ForwardDirection variable sets the direction that the door will open.&lt;/li&gt;
&lt;li&gt;The SlideDirection variable sets the axis and the direction of the sliding. In the picture the door will open in the z axis and it will slide in the opposite direction.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The SlideAmount sets the amount of sliding. Here it will move in the z direction by 1.9&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Attach the PlayerAction.cs script to the PlayerCapsule GameObject and set the Inspector as seen in the picture bellow.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set camera to MainCamera&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create Layer Usable and set the new layer in the inspector of PlayerActions&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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%2Feneaslari.com%2Fa529dd40-7ef2-4456-b980-8856aba0b163.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%2Feneaslari.com%2Fa529dd40-7ef2-4456-b980-8856aba0b163.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In order to make the OnUse function you have to map the Action to the input system. Click on StarterAssets(Input Actions Asset) and open the asset&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%2Feneaslari.com%2F6e7e931e-7e8a-49a7-a601-012eb3d05bbe.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%2Feneaslari.com%2F6e7e931e-7e8a-49a7-a601-012eb3d05bbe.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&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%2Feneaslari.com%2Fb9312d5f-68b8-4bd4-b958-b86f7946f5e8.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%2Feneaslari.com%2Fb9312d5f-68b8-4bd4-b958-b86f7946f5e8.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add Use Action and set the property to "E" button (the key that will open the door)&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%2Feneaslari.com%2F957d47e7-c2f3-43be-a817-0e5248c108ac.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%2Feneaslari.com%2F957d47e7-c2f3-43be-a817-0e5248c108ac.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also add the Usable layer on the door object so the PlayerAction works&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%2Feneaslari.com%2Fcda4ad17-b3f3-4770-8272-1745b832cb0c.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%2Feneaslari.com%2Fcda4ad17-b3f3-4770-8272-1745b832cb0c.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;And Finaly Add DoorTrigger.cs at the DoorTrigger GameObject if you want the door to open automatically when you get close.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&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%2Feneaslari.com%2Fdd232e26-a512-4395-9b5a-376db42c3bd9.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%2Feneaslari.com%2Fdd232e26-a512-4395-9b5a-376db42c3bd9.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Assign the Door GameObject in the inspector&lt;/p&gt;

&lt;p&gt;Now Make a Auto door and a sliding door changing the Variables in the inspector of the Door.cs or Attach the DoorTrigger.cs to the DoorTrigger GameObject&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt;&lt;br&gt;
You've now added a functional door to your Unity project, enhancing its interactivity. Experiment with different door designs and behaviors to create a unique experience in your game.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Call to Action&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Encourage readers to comment, share, or try more tutorials.&lt;/strong&gt;
Example:
"Have fun with your new door system! If you have any questions or want to see more tutorials like this, leave a comment below or share your thoughts on social media."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;7. Additional Resources&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=cPltQK5LlGE&amp;amp;t=1s" rel="noopener noreferrer"&gt;Doors in Unity - Sliding and Rotating Doors 
LlamAcademy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>unity3d</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Optimizing Unity Projects: Architectural Patterns and Best Practices for Scalable Game Development</title>
      <dc:creator>EneasLari</dc:creator>
      <pubDate>Wed, 05 Jun 2024 20:11:21 +0000</pubDate>
      <link>https://forem.com/eneaslari/optimizing-unity-projects-architectural-patterns-and-best-practices-for-scalable-game-development-45n3</link>
      <guid>https://forem.com/eneaslari/optimizing-unity-projects-architectural-patterns-and-best-practices-for-scalable-game-development-45n3</guid>
      <description>&lt;p&gt;Embarking on a Unity project is always an exciting journey filled with creativity and technical challenges. However, like many game developers, I've often found myself grappling with the complexities of organizing code and game objects. In my experience, without a solid architectural foundation, projects can quickly become tangled webs that are hard to manage and scale. This issue hit home for me during the development of my latest match-three game.&lt;/p&gt;

&lt;p&gt;Initially, everything seemed manageable, but as the game grew, so did the complexity of its structure. New features, interactions, and game mechanics piled up, turning my well-intentioned code into a labyrinth of dependencies. It wasn't long before I found myself stuck, spending more time troubleshooting and untangling code than actually developing the game. The tipping point came when I realized that adding anything new or modifying existing features was becoming a Herculean task. It was clear that my initial approach wasn't sustainable, and I had no choice but to take a step back.&lt;/p&gt;

&lt;p&gt;Reluctantly, I made the decision to rewrite our entire codebase—a daunting but necessary step to save the project. Throughout this challenging process, I learned just how critical it is to choose the right architecture early on. Eager to help fellow developers sidestep these issues, I began educating myself on various architectural patterns and principles. While I haven't personally tested all of these strategies, the ones I've implemented in my Unity projects have been transformative. They've not only kept my projects well-organized but have also enhanced their scalability and maintainability. Let's explore these architectural lifesavers.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;MVC (Model-View-Controller)&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model&lt;/strong&gt;: Represents the data and business logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;View&lt;/strong&gt;: Handles the presentation layer and user interface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Controller&lt;/strong&gt;: Manages input and updates the model and view accordingly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;MVVM (Model-View-ViewModel)&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model&lt;/strong&gt;: Contains the application's data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;View&lt;/strong&gt;: Displays data and sends user commands to the ViewModel.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ViewModel&lt;/strong&gt;: Acts as a bridge between the Model and View, handling the presentation logic.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;ECS (Entity-Component-System)&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Entity&lt;/strong&gt;: Represents objects in the game.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Component&lt;/strong&gt;: Holds data related to entities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;System&lt;/strong&gt;: Contains logic that processes entities with certain components.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Service Locator&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Provides a centralized registry for services (like audio, input, etc.) and allows for decoupling between classes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. &lt;strong&gt;Singletons&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Ensures a class has only one instance and provides a global point of access to it. Commonly used for game managers, input managers, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. &lt;strong&gt;Observer Pattern&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Allows objects (observers) to be notified of changes in other objects (subjects). Useful for event systems and state changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  7. &lt;strong&gt;Command Pattern&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Encapsulates a request as an object, thereby allowing for parameterization and queuing of requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  1. MVC Detailed Explanation
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Model
&lt;/h4&gt;

&lt;p&gt;The Model represents the data and the business logic of your application. In a Unity context, the Model would manage the game data, rules, and behaviors independently of the user interface. It's purely about the data and its related logic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: In a role-playing game (RPG), the Model might manage character stats, inventory items, and game mechanics like health and damage calculations.&lt;/p&gt;

&lt;h4&gt;
  
  
  View
&lt;/h4&gt;

&lt;p&gt;The View is responsible for presenting data to the player and handling user interactions. Views are typically linked to Unity scenes or UI elements, displaying information to the player and sending user inputs to the Controller.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: The View could be a UI canvas displaying the player's health, inventory, and stats.&lt;/p&gt;

&lt;h4&gt;
  
  
  Controller
&lt;/h4&gt;

&lt;p&gt;The Controller serves as an intermediary that manages communication between the Model and the View. It responds to user input, updating the Model as necessary, and refreshes the View when the data changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: When a player moves an item in their inventory, the Controller would update the Model to reflect this change and then prompt the View to update the UI display.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. MVVM (Model-View-View Model)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;MVVM&lt;/strong&gt; stands for Model-View-ViewModel. This pattern is particularly useful for projects where you want to separate the game logic and how it's displayed, which can make it easier to manage and update your game.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model&lt;/strong&gt;: This is where your game's data lives. Think of it as the heart of your game's rules and what happens in the game.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;View&lt;/strong&gt;: This is what the players see on their screens. It might include things like health bars, menus, or the game world itself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ViewModel&lt;/strong&gt;: This acts as a middleman between the Model and the View. It takes data from the Model and formats it so the View can display it in a user-friendly way.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: Let’s say you’re making a card game. The Model would handle the logic of the cards, such as their values and rules. The ViewModel would take this information and prepare a display like sorting the cards or highlighting playable ones. The View would then show these cards on the screen, laid out nicely for the player to interact with.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. ECS (Entity-Component-System)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;ECS&lt;/strong&gt; stands for Entity-Component-System, and it’s a bit different from traditional object-oriented programming. It’s great for games because it helps manage lots of objects and interactions efficiently, making your game run smoother.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Entity&lt;/strong&gt;: These are the individual things in your game, like players, enemies, or items. They are just identifiers with no actual data or behavior.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Component&lt;/strong&gt;: Components are data containers attached to entities. For example, a health component might store the health value of an entity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;System&lt;/strong&gt;: Systems are where the logic is processed. They operate on entities that have specific components. For example, a movement system might handle all entities that have position and velocity components.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: In a space shooter game, your spaceship entity might have components like position, health, and weapon. Systems would read these components to move the spaceship, track and display health, and manage shooting.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Service Locator
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Service Locator&lt;/strong&gt; pattern is a way to organize different services (like sound effects, data loading, etc.) in your game. It provides a single point where you can access these services without needing to know exactly how they are implemented.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: Imagine your game needs to play sound effects. Instead of each part of your game handling sound playback itself, they just tell the Service Locator, "I need to play this sound." The Service Finder then deals with the details of playing that sound.&lt;/p&gt;

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

&lt;p&gt;A &lt;strong&gt;Singleton&lt;/strong&gt; is a design pattern used to ensure a class has only one instance and provides a global point of access to it. This is useful for things that should only exist once in a game.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: Think of a GameManager in a game, which might handle scores, player data, and game states. By making it a Singleton, you ensure there's only one GameManager being accessed globally, preventing conflicts or duplicate data.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Observer Pattern
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Observer Pattern&lt;/strong&gt; is used to allow objects to observe and react to events in other objects. It’s like a subscription model where observers get notified when something they care about happens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: In a game, you might want the UI to update when a player’s health changes. The health system can notify (or "publish") this event, and any UI elements that are observing (or "subscribed to") the player's health will automatically update.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Command Pattern
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Command Pattern&lt;/strong&gt; encapsulates actions or requests as objects, allowing you to parameterize and schedule operations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: Imagine a strategy game where you can queue up actions for your units. Each action (like move, attack, defend) can be a command object. This allows you to easily implement undo actions, delay commands, or even network commands if you’re playing online.&lt;/p&gt;

&lt;h3&gt;
  
  
  Best Practices and Principles
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;SOLID Principles&lt;/strong&gt;
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Single Responsibility Principle&lt;/strong&gt;: A class should have one, and only one, reason to change.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open/Closed Principle&lt;/strong&gt;: Classes should be open for extension but closed for modification.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Liskov Substitution Principle&lt;/strong&gt;: Subtypes must be substitutable for their base types.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interface Segregation Principle&lt;/strong&gt;: No client should be forced to depend on methods it does not use.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependency Inversion Principle&lt;/strong&gt;: Depend upon abstractions, not concretions.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Dependency Injection&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Promotes loose coupling by injecting dependencies rather than creating them within the classes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Combining Patterns
&lt;/h3&gt;

&lt;p&gt;Often, the best architecture for a Unity project involves combining multiple patterns. For example, you might use MVC for UI, ECS for game object management, and singletons for core services.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Architecture Setup
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Core&lt;/strong&gt;: Singleton managers (e.g., GameManager, AudioManager)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data&lt;/strong&gt;: Scriptable objects for game data, JSON/XML for saving/loading&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Presentation&lt;/strong&gt;: MVC or MVVM for UI management&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gameplay&lt;/strong&gt;: ECS for managing entities and their behaviors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Utilities&lt;/strong&gt;: Service locator for accessing services&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Implementation Tips
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use Unity's Scriptable Objects&lt;/strong&gt; for data-driven design.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Organize your project structure&lt;/strong&gt;: Separate folders for scripts, prefabs, scenes, assets, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use namespaces&lt;/strong&gt; to avoid class name conflicts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automate tasks&lt;/strong&gt; using Unity's built-in tools or custom editor scripts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing&lt;/strong&gt;: Implement unit tests for core logic and integration tests for larger systems.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Selecting the right architecture depends on the specific needs of your Unity project. A hybrid approach that combines the strengths of various patterns often works best. Regularly refactor and review your architecture to ensure it remains robust and scalable as your project grows.&lt;/p&gt;

</description>
      <category>unity3d</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Astro and Express: SSR in Astro</title>
      <dc:creator>EneasLari</dc:creator>
      <pubDate>Wed, 22 May 2024 07:49:43 +0000</pubDate>
      <link>https://forem.com/eneaslari/astro-and-express-ssr-in-astro-2j9d</link>
      <guid>https://forem.com/eneaslari/astro-and-express-ssr-in-astro-2j9d</guid>
      <description>&lt;p&gt;Implementing Server-Side Rendering (SSR) with Astro JS is a great way to improve performance and SEO for your web applications. Astro is designed to support SSR out of the box, making it relatively straightforward to set up. Here’s a basic guide on how to implement SSR with Astro:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Setup Your Astro Project&lt;/strong&gt;:
If you haven’t already created an Astro project, you can start by setting one up. Run the following commands in your terminal:
&lt;/li&gt;
&lt;/ol&gt;

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

&lt;/div&gt;



&lt;p&gt;Follow the prompts to create your new project.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;**Enable SSR with:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx astro add node
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Configure SSR in Astro&lt;/strong&gt;:
By default, Astro projects are configured to render statically. To enable SSR, you’ll need to modify the &lt;code&gt;astro.config.mjs&lt;/code&gt; file:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&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;defineConfig&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;astro/config&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="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
     &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="na"&gt;adapter&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="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;@astrojs/node&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="c1"&gt;// options here&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;Now lets  create an Express server that serves data from a JSON file containing a list of people with their names, last names, and addresses, you'll follow these steps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1:At the root of your astro project Install Express&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Install Express using npm:&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;express
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Set Up the Express Server&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a file named &lt;code&gt;server.mjs&lt;/code&gt; in your project directory and add the following code:&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&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;express&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;handler&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;astroHandler&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;./dist/server/entry.mjs&lt;/span&gt;&lt;span class="dl"&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&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;PORT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/people&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="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Doe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1234 Main St&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="s2"&gt;Jane&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Doe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1235 Main St&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="s2"&gt;Jim&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Beam&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1236 Main St&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="c1"&gt;// Use Astro handler for all other routes&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;astroHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PORT&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server running at http://localhost:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;&lt;strong&gt;Step 3: Run Your Server&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Add &lt;code&gt;"startserver": "node server.mjs"&lt;/code&gt; script at package.json&lt;/p&gt;

&lt;p&gt;To start the server, run the following command in your terminal:&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 startserver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the output indicating that the server is running on &lt;code&gt;http://localhost:3000&lt;/code&gt;. You can now visit &lt;code&gt;http://localhost:3000/people&lt;/code&gt; in your web browser or a tool like Postman to see the JSON data being served.&lt;/p&gt;

&lt;p&gt;This configuration uses the astroHandler, which is exported by the built Astro app, to handle requests that aren’t caught by the earlier Express route (/api/people). This allows you to use Express for APIs or other server-specific tasks while Astro handles the SSR and other routes.&lt;/p&gt;

&lt;p&gt;Edit index.astro to fetch our data from the server and render them at page&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;// Make the fetch request to the &lt;span class="nb"&gt;local &lt;/span&gt;API endpoint
const response &lt;span class="o"&gt;=&lt;/span&gt; await fetch&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'http://localhost:3000/api/people'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
const data &lt;span class="o"&gt;=&lt;/span&gt; await response.json&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Add inside html the follwing code
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    &amp;lt;ul&amp;gt;
      &lt;span class="o"&gt;{&lt;/span&gt;
        data.map&lt;span class="o"&gt;((&lt;/span&gt;person&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
          &amp;lt;li &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;person.name&lt;span class="o"&gt;}&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;{&lt;/span&gt;person.name&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;person.lastName&lt;span class="o"&gt;}&lt;/span&gt; - &lt;span class="o"&gt;{&lt;/span&gt;person.address&lt;span class="o"&gt;}&lt;/span&gt;
          &amp;lt;/li&amp;gt;
        &lt;span class="o"&gt;))&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &amp;lt;/ul&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You Havet to build again the astro project&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 build
npm run serve

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

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;npm run startserver&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%2Feneaslari.com%2Fdaf03974-41cc-4063-a6fc-eee323a45a20.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%2Feneaslari.com%2Fdaf03974-41cc-4063-a6fc-eee323a45a20.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And congratulation you just implemented ssr with astro&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%2Feneaslari.com%2F6dd59567-376e-450e-b7ab-47d2ecaaf2e5.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%2Feneaslari.com%2F6dd59567-376e-450e-b7ab-47d2ecaaf2e5.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>astro</category>
      <category>express</category>
    </item>
    <item>
      <title>Exploring Astro: A Journey into Modern Web Development with Astro JS</title>
      <dc:creator>EneasLari</dc:creator>
      <pubDate>Mon, 20 May 2024 09:51:40 +0000</pubDate>
      <link>https://forem.com/eneaslari/exploring-astro-a-journey-into-modern-web-development-with-astro-js-5ge6</link>
      <guid>https://forem.com/eneaslari/exploring-astro-a-journey-into-modern-web-development-with-astro-js-5ge6</guid>
      <description>&lt;p&gt;I was today years old when I learned about Astro. I know maybe I live under a rock as I discovered that Astro has been a very famous front-end solution for quite some time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is Astro?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Astro JS is a modern web framework designed to help developers build faster websites. It allows you to write your website using multiple web technologies like React, Vue, or Svelte, but it sends the final page to the user's browser as mostly static HTML. This makes the page load faster because the browser doesn't have to do as much work to display the page. Astro also only loads the JavaScript needed for interactivity when it's needed, which keeps pages light and fast.&lt;/p&gt;

&lt;p&gt;Astro JS is a versatile framework that can be used in various scenarios to enhance web development projects.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Static Websites&lt;/strong&gt;: Astro is excellent for building static websites, such as blogs, portfolios, and informational sites. It compiles to static HTML by default, which can be hosted on any static site hosting service, resulting in fast loading times and reduced server costs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Content-Heavy Sites&lt;/strong&gt;: For websites that need to manage and display large amounts of content, like news sites or educational platforms, Astro can be very effective. It allows developers to fetch data at build time and render it into the HTML, ensuring quick load times and a smooth user experience.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;E-commerce Platforms&lt;/strong&gt;: Astro can be used to build e-commerce sites where performance and speed are critical for user retention and SEO. Astro's efficient handling of JavaScript ensures that the user interface remains responsive and engaging without sacrificing load times.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-Page Applications (MPA)&lt;/strong&gt;: For projects where a single-page application (SPA) might be overkill, Astro provides an excellent foundation for building multi-page applications. It allows each page to be independently developed and optimized, using the best-suited frameworks and libraries as needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Personalization and Dynamic Elements&lt;/strong&gt;: Even though Astro is optimized for static generation, it supports client-side JavaScript to add interactivity and dynamic content as needed. This makes it suitable for sites that require user interaction and personalization without loading unnecessary JavaScript upfront.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Documentation Sites&lt;/strong&gt;: Astro's ability to integrate with various front-end frameworks seamlessly makes it ideal for documentation websites that may need interactive examples and demos embedded within the content. This is useful for tech companies and open-source projects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Progressive Web Applications (PWA)&lt;/strong&gt;: Astro's lightweight output and efficient asset handling make it a good choice for developing progressive web applications. PWAs built with Astro can benefit from fast loading times and reliable performance even in poor network conditions.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Astro's flexibility in integrating multiple UI frameworks and its focus on performance optimization make it a compelling choice for a wide range of web development projects.&lt;/p&gt;

&lt;p&gt;Let's get our hands dirty enough talking.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm create astro@latest
&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%2Feneaslari.com%2F958d6005-2d4d-4335-af5f-cc192807565b.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%2Feneaslari.com%2F958d6005-2d4d-4335-af5f-cc192807565b.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, if you want to follow this tutorial, select the same choices as me in the subsequent questions.&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%2Feneaslari.com%2F930a71d1-1e53-401b-b9e4-9879c6617e71.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%2Feneaslari.com%2F930a71d1-1e53-401b-b9e4-9879c6617e71.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Navigate to the newly created directory and run &lt;code&gt;npm run dev&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%2Feneaslari.com%2Fa9bc6c4b-37a1-4473-97de-aace621a9542.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%2Feneaslari.com%2Fa9bc6c4b-37a1-4473-97de-aace621a9542.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If all goes well, Astro should now be serving your project on &lt;a href="http://localhost:4321/" rel="noopener noreferrer"&gt;http://localhost:4321/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Astro will listen for live file changes in your src/ directory, so you will not need to restart the server as you make changes during development.&lt;/p&gt;

&lt;p&gt;Next, let's install the Astro extension on VSCode.&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%2Feneaslari.com%2Fae535d6b-af67-4a3e-b6cb-1b53e0dc1a2b.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%2Feneaslari.com%2Fae535d6b-af67-4a3e-b6cb-1b53e0dc1a2b.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, as you can see, the syntax is highlighted.&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%2Feneaslari.com%2F6b1c4d7f-59ab-44db-9cda-98f841001841.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%2Feneaslari.com%2F6b1c4d7f-59ab-44db-9cda-98f841001841.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we will add a new component. Create a file with the name &lt;code&gt;Test.astro&lt;/code&gt; under the Components directory.&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="nt"&gt;---&lt;/span&gt;
interface Props &lt;span class="o"&gt;{&lt;/span&gt;
  name: string
&lt;span class="o"&gt;}&lt;/span&gt;

const &lt;span class="o"&gt;{&lt;/span&gt; name &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; Astro.props
&lt;span class="nt"&gt;---&lt;/span&gt;

&amp;lt;p&amp;gt;This is a &lt;span class="nb"&gt;test &lt;/span&gt;component with a prop &lt;span class="o"&gt;{&lt;/span&gt;name&lt;span class="o"&gt;}&lt;/span&gt;&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, in order to use it in our index file, add the component at index.astro.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;import Test from &lt;span class="s1"&gt;'../components/Test.astro'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Under the &lt;code&gt;h1&lt;/code&gt; element, add the component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&amp;lt;Test &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'My name'&lt;/span&gt; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will see:&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%2Feneaslari.com%2F1c9d3bfe-3df0-4b48-aa36-f4d93e97afa7.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%2Feneaslari.com%2F1c9d3bfe-3df0-4b48-aa36-f4d93e97afa7.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adding a New Page&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create a New File&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Navigate to the &lt;code&gt;src/pages&lt;/code&gt; directory in your Astro project. This directory is where Astro looks for files to turn into pages on your website.&lt;/li&gt;
&lt;li&gt;Create a new file with an &lt;code&gt;.astro&lt;/code&gt; extension for an Astro component or a &lt;code&gt;.html&lt;/code&gt; extension if you prefer plain HTML. The name you give this file will be used in the URL of your new page. For example, if you create &lt;code&gt;about.astro&lt;/code&gt;, the URL for this page would be &lt;code&gt;/about&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Add Content to the New Page&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open your new file in a text editor or IDE.&lt;/li&gt;
&lt;li&gt;You can write HTML directly in this file. If you're using an &lt;code&gt;.astro&lt;/code&gt; file, you can also utilize components and other features specific to Astro. Here’s a simple example:
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   ---
   // This is the front matter section where you can include JavaScript and import components
   ---

   &amp;lt;html&amp;gt;
     &amp;lt;head&amp;gt;
       &amp;lt;title&amp;gt;About Page&amp;lt;/title&amp;gt;
     &amp;lt;/head&amp;gt;
     &amp;lt;body&amp;gt;
       &amp;lt;h1&amp;gt;Welcome to the About Page&amp;lt;/h1&amp;gt;
       &amp;lt;p&amp;gt;This is an example of an Astro page.&amp;lt;/p&amp;gt;
     &amp;lt;/body&amp;gt;
   &amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Open your web browser and go to &lt;a href="http://localhost:4321/about" rel="noopener noreferrer"&gt;http://localhost:4321/about&lt;/a&gt; to see your new page in action.&lt;/li&gt;
&lt;/ul&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%2Feneaslari.com%2F58c471d7-84a6-4f05-a83d-e19e061f1ece.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%2Feneaslari.com%2F58c471d7-84a6-4f05-a83d-e19e061f1ece.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Creating a page with dynamic routes in an Astro project allows you to handle multiple URLs with a single file, typically used for cases like blog posts, product pages, or user profiles where the content changes based on some variable (like an ID). Here’s how you can set up dynamic routing in Astro:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Create a Dynamic Route File&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Navigate to the &lt;code&gt;src/pages&lt;/code&gt; Directory&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is where Astro looks for files to create pages from.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create a New File with a Dynamic Segment&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name the file with brackets to indicate a dynamic segment. For example, if you want to create dynamic blog post pages where each post has a unique ID, you might name your file &lt;code&gt;[id].astro&lt;/code&gt;. Here, &lt;code&gt;id&lt;/code&gt; will be the variable holding the dynamic part of the URL.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Access the Route Parameter in Your Page&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Open the New Dynamic Route File&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Edit the file to handle the dynamic content. You can access the dynamic parameter using the &lt;code&gt;Astro.request&lt;/code&gt; object.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Example Code for a Dynamic Blog Post Page&lt;/strong&gt; (&lt;code&gt;[id].astro&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
import Layout from '../layouts/Layout.astro'
const { id } = Astro.params

export async function getStaticPaths() {
  return [{ params: { id: 'test' } }, { params: { id: 'test2' } }, { params: { id: 'test3' } }]
}
---

&amp;lt;Layout title='Post'&amp;gt;
  &amp;lt;h1 style='color: white'&amp;gt;{id}&amp;lt;/h1&amp;gt;
&amp;lt;/Layout&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now visit &lt;a href="http://localhost:4321/test" rel="noopener noreferrer"&gt;http://localhost:4321/test&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And you will see the page.&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%2Feneaslari.com%2F2f2c3353-d7fa-44e2-b553-8ed12c7e927a.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%2Feneaslari.com%2F2f2c3353-d7fa-44e2-b553-8ed12c7e927a.png" title="new image file" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's all for now.&lt;br&gt;
We will explore more about Astro as it seems very interesting.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>astro</category>
    </item>
    <item>
      <title>Understanding Nginx: From Simple Concepts to Technical Details and Deploying securely with PM2 and Certbot</title>
      <dc:creator>EneasLari</dc:creator>
      <pubDate>Thu, 02 May 2024 17:03:23 +0000</pubDate>
      <link>https://forem.com/eneaslari/understanding-nginx-from-simple-concepts-to-technical-details-and-deploying-securely-with-pm2-and-certbot-3pk5</link>
      <guid>https://forem.com/eneaslari/understanding-nginx-from-simple-concepts-to-technical-details-and-deploying-securely-with-pm2-and-certbot-3pk5</guid>
      <description>&lt;p&gt;Imagine you have a little shop where you sell lemonade, and you have a big sign that says "Lemonade for Sale." When people see your sign, they come to your shop to buy your lemonade. Now, imagine you're so popular that lots of people come at the same time. You need to make sure everyone gets their lemonade quickly and smoothly, so no one is waiting too long.&lt;/p&gt;

&lt;p&gt;Nginx is like the best helper you could ask for in your shop. It's like a smart organizer who helps you handle all the people coming to your shop. When someone comes up to buy lemonade, Nginx quickly figures out who should get lemonade first, and makes sure that even if lots of people come at once, everyone gets their drink fast and without any trouble. It helps you manage the crowd so you can keep everyone happy!&lt;/p&gt;

&lt;h3&gt;
  
  
  WHAT??
&lt;/h3&gt;

&lt;p&gt;Certainly! Nginx (pronounced as "Engine-X") is a powerful web server software that is also used as a reverse proxy, load balancer, and HTTP cache. It was specifically designed to handle high concurrency, which means it can manage many connections at once, efficiently and without requiring a lot of resources.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Web Server:&lt;/strong&gt; As a web server, Nginx serves static content, like HTML, CSS, and JavaScript files, directly to clients. It is very efficient at this because of its event-driven architecture, which allows it to handle thousands of simultaneous connections on a single thread without much memory overhead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reverse Proxy:&lt;/strong&gt; As a reverse proxy, Nginx sits between the client (like a web browser) and other servers. It can forward client requests to other servers and deliver the responses back to the client. This setup is useful for hiding the characteristics and location of the origin servers or for load balancing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Load Balancer:&lt;/strong&gt; Nginx can distribute incoming network traffic across multiple backend servers (like a group of application servers). This distributes the load, making sure no single server gets overwhelmed, which improves the responsiveness and availability of applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HTTP Cache:&lt;/strong&gt; Nginx can also cache the responses from a server and reuse them to answer identical requests. This reduces the load on the server and speeds up the response time for clients.&lt;/p&gt;

&lt;p&gt;Nginx is known for its high performance, stability, rich feature set, simple configuration, and low resource consumption. These qualities make it a popular choice for scaling web applications and improving their performance and reliability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lets Use NGINX to run the Sigle File NodeJS Server that we set up &lt;a href="https://eneaslari.com/articleview/render/hosting-a-nodejs-web-app-on-ubuntu-server-22.04-6628fdeac48df087e19c296b" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Nginx, pronounced like “engine-ex”, is an open-source web server that, since its initial success as a web server, is now also used as a reverse proxy, HTTP cache, and load balancer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Installing Nginx&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;UFW&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Uncomplicated Firewall (UFW) is a program for managing a netfilter firewall designed to be easy to use. It uses a command-line interface consisting of a small number of simple commands, and uses iptables for configuration. UFW is available by default in all Ubuntu installations since 8.04 LTS.[1] UFW has been available by default in all Debian installations since 10.&lt;/p&gt;

&lt;p&gt;Install ufw&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;ufw
ufw &lt;span class="nb"&gt;enable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Give nginx full control of firewall&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ufw allow &lt;span class="s2"&gt;"Nginx Full"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you install Nginx, a default configuration file is created at &lt;code&gt;/etc/nginx/sites-available/default&lt;/code&gt;. It's a good idea to keep this file for reference, but if you don't want to use it immediately, you should disable it. To disable it, delete the symbolic link in &lt;code&gt;/etc/nginx/sites-enabled/&lt;/code&gt; that points to this default file.&lt;/p&gt;

&lt;p&gt;Now let's Create a new config file with name &lt;code&gt;seinglefileserver.conf&lt;/code&gt; under &lt;code&gt;/etc/nginx/sites-available/&lt;/code&gt; directory&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;server &lt;span class="o"&gt;{&lt;/span&gt;
  server_name test.eneaslari.com&lt;span class="p"&gt;;&lt;/span&gt;
  location / &lt;span class="o"&gt;{&lt;/span&gt;
    proxy_pass http://&amp;lt;Your servers Ip&amp;gt;:6001&lt;span class="p"&gt;;&lt;/span&gt;
    proxy_http_version 1.1&lt;span class="p"&gt;;&lt;/span&gt;
    proxy_set_header Upgrade &lt;span class="nv"&gt;$http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    proxy_set_header Connection &lt;span class="s1"&gt;'upgrade'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    proxy_set_header Host &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    proxy_cache_bypass &lt;span class="nv"&gt;$http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This Nginx configuration file defines a server block that listens for requests directed to the domain &lt;code&gt;test.eneaslari.com&lt;/code&gt;. Let's break down each directive:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;server&lt;/code&gt;: Begins a new server block.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;server_name test.eneaslari.com&lt;/code&gt;: Specifies the domain name for which this server block will be used to handle requests. In this case, it's set to &lt;code&gt;test.eneaslari.com&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;location /&lt;/code&gt;: Defines a location block that matches requests with any URI path.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;proxy_pass http://&amp;lt;Your servers Ip&amp;gt;:6001;&lt;/code&gt;: This directive instructs Nginx to forward incoming requests to another server. In this case, it forwards requests to the IP address specified (replace &lt;code&gt;&amp;lt;Your servers Ip&amp;gt;&lt;/code&gt; with the actual IP address) on port 6001.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;proxy_http_version 1.1;&lt;/code&gt;: Sets the HTTP version used in proxy communication to HTTP/1.1.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;proxy_set_header Upgrade $http_upgrade;&lt;/code&gt;: This sets the &lt;code&gt;Upgrade&lt;/code&gt; header to the value of the &lt;code&gt;Upgrade&lt;/code&gt; header from the client's request. This is often used to enable WebSocket connections.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;proxy_set_header Connection 'upgrade';&lt;/code&gt;: Sets the &lt;code&gt;Connection&lt;/code&gt; header to &lt;code&gt;upgrade&lt;/code&gt;. This is also commonly used for WebSocket connections.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;proxy_set_header Host $host;&lt;/code&gt;: Sets the &lt;code&gt;Host&lt;/code&gt; header to the value of the &lt;code&gt;Host&lt;/code&gt; header from the client's request.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;proxy_cache_bypass $http_upgrade;&lt;/code&gt;: Sets conditions under which the request will bypass the cache. In this case, requests with the &lt;code&gt;Upgrade&lt;/code&gt; header will bypass the cache.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This configuration essentially sets up a reverse proxy that forwards incoming requests from &lt;code&gt;test.eneaslari.com&lt;/code&gt; to another server listening on port 6001. It also includes settings commonly used for WebSocket connections.&lt;/p&gt;

&lt;p&gt;Here's a clearer breakdown of how Nginx's configuration files are structured:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Configuration Storage:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Available Configurations:&lt;/strong&gt; All the server block files are stored in &lt;code&gt;/etc/nginx/sites-available/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enabled Configurations:&lt;/strong&gt; Nginx will only use configurations that are linked in &lt;code&gt;/etc/nginx/sites-enabled/&lt;/code&gt;. These are usually symbolic links to files in the &lt;code&gt;sites-available&lt;/code&gt; directory.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Enabling a New Configuration:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To activate a configuration file, create a symbolic link from the &lt;code&gt;sites-available&lt;/code&gt; directory to the &lt;code&gt;sites-enabled&lt;/code&gt; directory using the following command:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; ln -s /etc/nginx/sites-available/&amp;lt;filename&amp;gt; /etc/nginx/sites-enabled/&amp;lt;filename&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Replace &lt;code&gt;&amp;lt;filename&amp;gt;&lt;/code&gt; with the name of the configuration file you wish to enable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to unlink the default Nginx configuration, you can use 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;&lt;span class="nb"&gt;sudo unlink&lt;/span&gt; /etc/nginx/sites-available/default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Check Nginx Configuration&lt;/strong&gt;: Before restarting Nginx, it's a good practice to check if the configuration is valid.&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;sudo &lt;/span&gt;nginx &lt;span class="nt"&gt;-t&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If there are any syntax errors in your configuration file, this command will point them out. Fix any errors before proceeding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Restart Nginx&lt;/strong&gt;: Once the configuration is validated, you can restart Nginx to apply the changes.&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;sudo &lt;/span&gt;systemctl restart nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will restart Nginx and load the new configuration file. From this point onwards, Nginx will handle requests for &lt;code&gt;test.eneaslari.com&lt;/code&gt; according to the configuration you provided.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test the Configuration&lt;/strong&gt;: After restarting Nginx, you can test whether it's working correctly by accessing &lt;code&gt;http://test.eneaslari.com&lt;/code&gt; in your web browser or by sending requests to this domain using tools like &lt;code&gt;curl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Be sure that you are running the nodeJS Server for example &lt;code&gt;npm start&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That's it! Your Nginx server should now be configured to handle requests for &lt;code&gt;test.eneaslari.com&lt;/code&gt; and proxy them to the specified server.&lt;/p&gt;

&lt;p&gt;Now Visit test.eneaslari.com/ (for you it will be something different depends on what you have defined your servers name. Also you have to be sure that you have connected the specified domain from your domain provider with the server)&lt;/p&gt;

&lt;h3&gt;
  
  
  Optional
&lt;/h3&gt;

&lt;p&gt;Now let's take it to the next level and use PM2 to run server in the background&lt;/p&gt;

&lt;p&gt;Create at the root of your project a file with name ecosystem.config.cjs&lt;/p&gt;

&lt;p&gt;Past this code :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;module. Exports &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  apps: &lt;span class="o"&gt;[{&lt;/span&gt;
    name: &lt;span class="s2"&gt;"test.eneaslari.com"&lt;/span&gt;,
    script: &lt;span class="s2"&gt;"npm start"&lt;/span&gt;,
    watch: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"./"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
    ignore_watch: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"node_modules"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
  &lt;span class="o"&gt;}]&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
//run this file with pm2 with pm2 start ecosystem.config.cjs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;module.exports&lt;/code&gt;: This syntax is used in Node.js to export modules, making them available to other files. In this case, it's exporting an object that contains PM2 configuration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;apps&lt;/code&gt;: This key holds an array of objects, where each object represents a configuration for a specific application or microservice that PM2 will manage. You can include multiple configurations in the &lt;code&gt;apps&lt;/code&gt; array for different applications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;name&lt;/code&gt;: A string that specifies the name of the application as it will appear in PM2's process listing. In this case, the application is named "test.eneaslari.com".&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;script&lt;/code&gt;: Defines the entry point script for the application. Here, &lt;code&gt;"npm start"&lt;/code&gt; is used, which means PM2 will execute the &lt;code&gt;start&lt;/code&gt; script defined in your &lt;code&gt;package.json&lt;/code&gt; file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;watch&lt;/code&gt;: If set to &lt;code&gt;true&lt;/code&gt;, PM2 will automatically restart the application when file changes in the current directory are detected. Here, it's set to watch all changes in the directory where PM2 is started (&lt;code&gt;"./"&lt;/code&gt;). This is useful during development for automatic restarts on file save.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;ignore_watch&lt;/code&gt;: An array of patterns to ignore from watching. In this configuration, changes in the &lt;code&gt;node_modules&lt;/code&gt; directory won't trigger a restart. This is important because &lt;code&gt;node_modules&lt;/code&gt; can contain a large number of files and frequent changes, which aren't typically necessary to watch for development purposes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Install PM2&lt;/strong&gt;: If you haven't already installed PM2, you can do so globally using npm:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; pm2
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Navigate to Your Project Directory&lt;/strong&gt;: Open your terminal or command prompt and navigate to your project directory where the &lt;code&gt;ecosystem.config.js&lt;/code&gt; file is located.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Start Your Application with PM2&lt;/strong&gt;: Run the following command to start your application using PM2:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pm2 start ecosystem.config.cjs
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&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%2Feneaslari.com%2F9934e34c-36fc-4617-b91c-add0bc886bdd.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%2Feneaslari.com%2F9934e34c-36fc-4617-b91c-add0bc886bdd.PNG" title="How nodejs work under the hood" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This command will start your application as defined in the PM2 configuration file (&lt;code&gt;ecosystem.config.js&lt;/code&gt;). PM2 will manage your application process and keep it running in the background.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Check Application Status&lt;/strong&gt;: You can check the status of your application by running:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pm2 status
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This command will show you a list of applications managed by PM2 along with their status.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Monitor Application Logs&lt;/strong&gt;: To monitor application logs, you can use the following command:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pm2 logs
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;More pm2 commands &lt;a href="https://pm2.keymetrics.io/docs/usage/quick-start/" rel="noopener noreferrer"&gt;here &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Securing Your Node.js Application with SSL&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ensuring that your Node.js application is secure is crucial, especially when dealing with sensitive data. One effective way to secure your application is by implementing SSL/TLS, which encrypts the data transmitted between your server and clients. Below is a step-by-step guide on how to set up SSL for a Node.js application hosted with Nginx using Certbot and Let's Encrypt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Step 1: Install Certbot and Its Nginx Plugin&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First, you need to install Certbot and the Certbot Nginx plugin on your server. Certbot is a free, automated tool that simplifies the process of obtaining and renewing Let’s Encrypt SSL certificates. To install these packages, run:&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;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;certbot python3-certbot-nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command installs Certbot along with the Nginx plugin, which allows Certbot to automatically configure SSL for Nginx.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Step 2: Obtain an SSL Certificate&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once the installation is complete, you can proceed to obtain an SSL certificate for your domain. Replace &lt;code&gt;test.eneaslari.com&lt;/code&gt; with your actual domain 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="nb"&gt;sudo &lt;/span&gt;certbot &lt;span class="nt"&gt;--nginx&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; test.eneaslari.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command instructs Certbot to authenticate your domain, obtain an SSL certificate, and configure Nginx to use this certificate. Follow the interactive prompts to complete the process. Ensure that your domain is pointed to the server where you are running this command and that port 80 is open, as Certbot uses it to validate domain ownership.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Step 3: Verify Automatic Renewal Setup&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s Encrypt certificates are valid for ninety days. Fortunately, Certbot creates a scheduled task to automatically renew certificates before they expire. Check the status of the Certbot timer to confirm it's active:&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;sudo &lt;/span&gt;systemctl status certbot.timer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will show you whether the timer is active and when the next renewal attempt is scheduled. It's important that this service is running to avoid any interruptions due to an expired certificate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Final Step: Confirmation&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Congratulations! You have successfully secured your Node.js application with SSL/TLS using Certbot and Let's Encrypt. Your communications are now encrypted, significantly enhancing the security of your application.&lt;/p&gt;

</description>
      <category>node</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Hosting a NodeJS Web App on Ubuntu Server 22.04</title>
      <dc:creator>EneasLari</dc:creator>
      <pubDate>Mon, 29 Apr 2024 20:20:32 +0000</pubDate>
      <link>https://forem.com/eneaslari/hosting-a-nodejs-web-app-on-ubuntu-server-2204-1866</link>
      <guid>https://forem.com/eneaslari/hosting-a-nodejs-web-app-on-ubuntu-server-2204-1866</guid>
      <description>&lt;p&gt;Let's dive into setting up and running a Node.js server on a Linux Ubuntu machine, and guess what? We're not starting from scratch! 🚀 We'll be using the super sleek one-file server I crafted in a previous article. If you missed it, don't worry—you can catch up &lt;a href="https://eneaslari.com/articleview/render/creating-a-single-file-node.js-api-with-express-mongodb-and-ejs-integration-654b70d76105d6905a4fe0ca" rel="noopener noreferrer"&gt;right here&lt;/a&gt;. Get ready to turbocharge your server setup and have some fun along the way! 🎉👨‍💻&lt;/p&gt;

&lt;p&gt;Ready to bring your Node.js project to life on your local server? 🌟 Let's roll up our sleeves and jump right in!&lt;/p&gt;

&lt;p&gt;First up, let’s snatch the project from GitHub. Go ahead and clone the repository with this slick command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/EneasLari/singlefilenodejs.git
&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%2Feneaslari.com%2Ff5887e68-b67d-4f95-b5b0-9aebb8dbd5da.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%2Feneaslari.com%2Ff5887e68-b67d-4f95-b5b0-9aebb8dbd5da.PNG" title="git clone" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next step on our adventure: saddle up those dependencies! 🚀 Run this command in your project directory:&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;
&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%2Feneaslari.com%2Fa6f20171-06ad-4f8b-8ea0-cb7c45998deb.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%2Feneaslari.com%2Fa6f20171-06ad-4f8b-8ea0-cb7c45998deb.PNG" title="npm install" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Don’t have MongoDB installed yet? No stress! Follow these easy-peasy instructions &lt;a href="https://www.cherryservers.com/blog/install-mongodb-ubuntu-22-04" rel="noopener noreferrer"&gt;right here&lt;/a&gt; to get set up.&lt;/p&gt;

&lt;p&gt;Now, let's fire up that server with:&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;And watch the magic happen! 🧙‍♂️&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%2Feneaslari.com%2F650ea153-aa2d-4a66-a9c8-6ac197f0a426.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%2Feneaslari.com%2F650ea153-aa2d-4a66-a9c8-6ac197f0a426.PNG" title="npm run dev" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Want to show off your server to the world? 🌍 Let's open up port 5000! Here’s how to make it available using UFW, the Uncomplicated Firewall:&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;sudo &lt;/span&gt;ufw allow 5000/tcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And voilà! Your local server is now ready to welcome visitors from anywhere, just like a party host opening the gates to an awesome backyard bash! 🎉&lt;/p&gt;

&lt;p&gt;Now, pull up your browser and take your freshly served Node.js app for a spin! 🎢 Happy coding!&lt;/p&gt;

&lt;p&gt;Here’s how to do it:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Check UFW Status&lt;/strong&gt;&lt;br&gt;
First, check if UFW is enabled on your system:&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;sudo &lt;/span&gt;ufw status verbose
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If UFW is not active, enable it with:&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;sudo &lt;/span&gt;ufw &lt;span class="nb"&gt;enable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will start the firewall and ensure it is set to start automatically when your system boots.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Allow Port 5000&lt;/strong&gt;&lt;br&gt;
Specify if the rule applies to TCP or UDP traffic. If your application requires both protocols, you should enable both. Here's how to do it:&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;sudo &lt;/span&gt;ufw allow 5000/tcp
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow 5000/udp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you only need it for one protocol, you can just run the respective command.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Verify the Changes&lt;/strong&gt;&lt;br&gt;
After adding the rules, it's important to verify that they have been implemented correctly:&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;sudo &lt;/span&gt;ufw status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will list all active rules, including the newly added entries for port 5000, confirming that it has been opened successfully.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Additional Notes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose of Port 5000&lt;/strong&gt;: Port 5000 is commonly used for web server development (e.g., Flask and other frameworks often use this port by default) as well as some media services. Ensure that opening this port is safe within your network environment and aligns with your security policies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logging and Monitoring&lt;/strong&gt;: For security, consider enabling logging for UFW:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nb"&gt;sudo &lt;/span&gt;ufw logging on
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This helps in keeping track of attempted connections, aiding in security audits and troubleshooting.&lt;/p&gt;

&lt;p&gt;Alright! 🌟 Now you're all set up and ready to roll! Just point your browser to your server's IP and the magic port 5000. Here's an example, but remember, your server IP might be different:&lt;/p&gt;

&lt;p&gt;🌐 Check out: &lt;a href="http://192.168.72.128:5000/" rel="noopener noreferrer"&gt;http://192.168.72.128:5000/&lt;/a&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%2Feneaslari.com%2F755306bf-87bf-4db8-a6b2-09ae6a9c8acd.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%2Feneaslari.com%2F755306bf-87bf-4db8-a6b2-09ae6a9c8acd.PNG" title="server running" alt="alt text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And just like that, you've got your Node.js server humming along on your local setup! 🎉&lt;/p&gt;

&lt;p&gt;Stay tuned! In our next article, we're going to level up and introduce PM2 to keep your server running smooth like butter, even when you close your terminal. Think of it as hiring a little digital assistant to keep the lights on 24/7! 🤖✨&lt;/p&gt;

&lt;p&gt;So, pat yourself on the back, grab a cup of your favorite brew, and take a moment to revel in your success! 🔥&lt;/p&gt;

</description>
      <category>node</category>
      <category>ubuntu</category>
    </item>
    <item>
      <title>How to Set Up a Local Ubuntu Server(22.04) on VMware for Web App Testing</title>
      <dc:creator>EneasLari</dc:creator>
      <pubDate>Tue, 23 Apr 2024 19:02:03 +0000</pubDate>
      <link>https://forem.com/eneaslari/how-to-set-up-a-local-ubuntu-server2204-on-vmware-for-web-app-testing-o9m</link>
      <guid>https://forem.com/eneaslari/how-to-set-up-a-local-ubuntu-server2204-on-vmware-for-web-app-testing-o9m</guid>
      <description>&lt;p&gt;I usually code on my Windows machine because it's cozy and convenient 😊. But for launching my projects, I use a Linux server. I thought about getting a second server for testing new ideas. Then, a great idea struck! 🌟 Why not use a virtual machine on my current setup? It's like having a small test lab without needing extra hardware.&lt;/p&gt;

&lt;p&gt;I prefer using VMWare 🖥️ to create virtual machines, and I install Ubuntu on them. You can find VMWare &lt;a href="https://www.vmware.com/products/workstation-player.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Also, make sure to grab an ISO of the latest Ubuntu server version, which is currently 22.04.4. You can download it &lt;a href="https://ubuntu.com/download/server" rel="noopener noreferrer"&gt;here&lt;/a&gt;. This setup helps me ensure that my digital sandbox is always ready for action! 🚀&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;System Requirements:&lt;/strong&gt; (As Official Ubuntu Page Suggests)&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%2Feneaslari.com%2Fb9ed62bc-74f4-45eb-b6eb-00206bee0ef1.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%2Feneaslari.com%2Fb9ed62bc-74f4-45eb-b6eb-00206bee0ef1.PNG" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now Lets Create the Virtual machine at VMware&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;🎉 &lt;strong&gt;Kick things off by creating a new Virtual Machine!&lt;/strong&gt; 🎉&lt;/li&gt;
&lt;/ol&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%2Feneaslari.com%2Fa80aa617-73c0-421b-bbf1-272a68dc89ba.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%2Feneaslari.com%2Fa80aa617-73c0-421b-bbf1-272a68dc89ba.PNG" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click that big shiny “Create a New Virtual Machine” button and feel like a boss! 🚀&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;📀 &lt;strong&gt;Now, grab that ISO you snagged from Ubuntu!&lt;/strong&gt; 📀&lt;/li&gt;
&lt;/ol&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%2Feneaslari.com%2F6f9ce5f7-2b66-4890-820d-85eead026d68.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%2Feneaslari.com%2F6f9ce5f7-2b66-4890-820d-85eead026d68.PNG" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Time to pick the ISO file you downloaded earlier. It’s like choosing the perfect topping for your ice cream! 🍦&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;🖊️ &lt;strong&gt;Time to name your new digital baby and pick its home!&lt;/strong&gt; 🖊️&lt;/li&gt;
&lt;/ol&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%2Feneaslari.com%2F87f2939e-86db-4ff6-8533-69bdda120bf0.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%2Feneaslari.com%2F87f2939e-86db-4ff6-8533-69bdda120bf0.PNG" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What’s in a name? Everything! Name your VM and choose where it's going to live on your computer. Like setting up a room for a new pet! 🐾&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;💾 &lt;strong&gt;How much space will your VM need? Pack its digital suitcase!&lt;/strong&gt; 💾&lt;/li&gt;
&lt;/ol&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%2Feneaslari.com%2F8d505718-b2f8-4b61-ac9a-a076a501dac4.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%2Feneaslari.com%2F8d505718-b2f8-4b61-ac9a-a076a501dac4.PNG" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Slide that bar to give your VM room to stretch its legs. More GBs, more fun! 🎢&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;🎬 &lt;strong&gt;Hit 'Finish' and let the magic happen!&lt;/strong&gt; 🎬&lt;/li&gt;
&lt;/ol&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%2Feneaslari.com%2F67d380b8-fe41-49f8-b085-63dbad7dc910.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%2Feneaslari.com%2F67d380b8-fe41-49f8-b085-63dbad7dc910.PNG" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All set? Smash that Finish button like you’re launching a rocket to Mars! 🚀🌌&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now Lets Install Ubuntu 22.04 LTS Server Edition&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;🚀 &lt;strong&gt;Step 1 - Let's Get This Boot-y Party Started with Ubuntu ISO!&lt;/strong&gt; 🚀&lt;/p&gt;

&lt;p&gt;Plug in that shiny new Ubuntu 22.04 bootable USB drive you prepared. Time to wake up your system with a jolt of Ubuntu energy! ⚡️&lt;/p&gt;

&lt;p&gt;When your system starts, you'll be greeted by the Grub menu, like a doorman at a fancy club. By default, it’s all set to take you straight to the "Try or Install Ubuntu Server" option—like the VIP entrance! 🌟&lt;/p&gt;

&lt;p&gt;Just sit back and let it whisk you away into the live system, no clicks needed. It’s like your computer is on autopilot! 🛫&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%2Feneaslari.com%2Fb1176ab6-c6e7-48c3-a646-fa6baa3e8cca.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%2Feneaslari.com%2Fb1176ab6-c6e7-48c3-a646-fa6baa3e8cca.png" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🌍 &lt;strong&gt;Step 2 - Pick Your Linguistic Adventure for the Ubuntu Installer!&lt;/strong&gt; 🌍&lt;/p&gt;

&lt;p&gt;After a short techno intermission (just a few seconds!), you'll dive into the language selection window. It's like choosing the language for your epic adventure in the Ubuntu world! 🗺️&lt;/p&gt;

&lt;p&gt;I go with "English" because it's classic and straightforward, like ordering vanilla at an ice cream shop—but hey, vanilla goes with everything! 🍦&lt;/p&gt;

&lt;p&gt;Press ENTER and stride confidently into the next phase. It’s like hitting the "Next" button on your journey to tech greatness! ⭐️&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%2Feneaslari.com%2Fde63ac43-0946-40e1-9bd6-4a138d7eec0f.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%2Feneaslari.com%2Fde63ac43-0946-40e1-9bd6-4a138d7eec0f.png" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 3 - Keyboard Configuration&lt;br&gt;
Choose your preferred keyboard layout. I go with English US.&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%2Feneaslari.com%2F752221a6-0d05-4dc5-a19f-3aaad1363903.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%2Feneaslari.com%2F752221a6-0d05-4dc5-a19f-3aaad1363903.png" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🛠️ &lt;strong&gt;Step 4 - Select Your Ubuntu Installation Flavor!&lt;/strong&gt; 🛠️&lt;/p&gt;

&lt;p&gt;Time to lay the foundation! You’ll see two savory options pop up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ubuntu Server:&lt;/strong&gt; The classic choice, packed with all the essentials for a robust server. It’s like the full meal deal!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ubuntu Server (minimized):&lt;/strong&gt; Stripped down for speed, perfect for systems where human logins are as rare as a unicorn sighting! 🦄&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I stick with the hearty standard: &lt;strong&gt;Ubuntu Server&lt;/strong&gt;. Just hit enter and keep cruising on your setup journey! 🚀&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%2Feneaslari.com%2Fedf7ed16-50b8-4230-975e-73fc166f10fd.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%2Feneaslari.com%2Fedf7ed16-50b8-4230-975e-73fc166f10fd.png" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🌐 &lt;strong&gt;Step 5 - Hook Up Those Network Connections!&lt;/strong&gt; 🌐&lt;/p&gt;

&lt;p&gt;Now, let's get your server chatting! It’s time to configure at least one network interface to make sure your server can mingle with other systems. 🤝&lt;/p&gt;

&lt;p&gt;Got a DHCP server on your network? Great! By default, your server is set to automatically snag an IP address from the DHCP server—like getting a free pass to the internet party! 🎫&lt;/p&gt;

&lt;p&gt;Just leave it as is to continue seamlessly. Your server is about to get connected without lifting a finger! 🎉&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%2Feneaslari.com%2F74cbfb32-4f34-4b89-af7d-23a0ca588d0c.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%2Feneaslari.com%2F74cbfb32-4f34-4b89-af7d-23a0ca588d0c.png" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Step 6 - Configure Proxy&lt;/strong&gt; 🔗&lt;/p&gt;

&lt;p&gt;Need a proxy to access the internet? Enter the details now. If not, just leave it blank and hit ENTER to continue. 🚀&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%2Feneaslari.com%2Fda06bc2c-8e56-42aa-b815-2c296f242629.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%2Feneaslari.com%2Fda06bc2c-8e56-42aa-b815-2c296f242629.png" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📡 &lt;strong&gt;Step 7 - Choose Your Ubuntu Archive Mirror&lt;/strong&gt; 📡&lt;/p&gt;

&lt;p&gt;The installer automatically selects the nearest archive mirror for your server. If you prefer a different one, just enter your chosen mirror's details. Otherwise, you're all set to go with the default!&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%2Feneaslari.com%2F6c3c1ef6-cf57-4fd0-824b-6753f7492ba2.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%2Feneaslari.com%2F6c3c1ef6-cf57-4fd0-824b-6753f7492ba2.png" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 8 - Update Installer (Optional)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You might get a prompt about a new Ubuntu installer update. Fancy the latest features? Choose "Update to the new installer" and hit ENTER. It’ll download and refresh your setup process.&lt;/p&gt;

&lt;p&gt;Prefer to keep things classic? Select "Continue without updating". &lt;/p&gt;

&lt;p&gt;I'm going for the update to check out the new installer TUI! 🔄&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%2Feneaslari.com%2Fe63a7046-6fda-4a5f-a210-8a137c39ae8c.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%2Feneaslari.com%2Fe63a7046-6fda-4a5f-a210-8a137c39ae8c.png" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 9 - Disk Partitioning&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Time to decide on disk space! Let the installer automatically partition your drive or customize it manually. Choose what suits your setup best!&lt;/p&gt;

&lt;p&gt;If you want to automatically partition the disk, simply choose "Use an entire disk" option.(I will choose this because I have a virtual machine)&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%2Feneaslari.com%2F8e153b7a-8e96-47b4-b184-4b6f5f9ffc88.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%2Feneaslari.com%2F8e153b7a-8e96-47b4-b184-4b6f5f9ffc88.png" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 10 - Set Hostname and User Details&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, name your Ubuntu server (hostname) and set up your username and password. These details will be your keys to logging in later!&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%2Feneaslari.com%2F8bae0294-030f-44ca-81c9-c71af2c4960d.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%2Feneaslari.com%2F8bae0294-030f-44ca-81c9-c71af2c4960d.png" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 11 - Enable Ubuntu Pro&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you have an Ubuntu Pro account, select "Enable Ubuntu Pro" to upgrade your server. This ensures security updates until 2032.&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%2Feneaslari.com%2F8a3a52aa-0f0e-4172-8f4b-add5620ba0e4.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%2Feneaslari.com%2F8a3a52aa-0f0e-4172-8f4b-add5620ba0e4.png" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 12 - Configure SSH&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In step, you can setup SSH. Check the "Install OpenSSH Server" check-box and choose "Done" and hit ENTER&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%2Feneaslari.com%2F3fcf2ae6-fa10-47a4-afcb-45b32ba02eb0.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%2Feneaslari.com%2F3fcf2ae6-fa10-47a4-afcb-45b32ba02eb0.png" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 13 - Select Featured Server Snaps&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next up, choose from popular snap applications to install on your server. Use the SPACEBAR to select or deselect your preferred apps, then hit ENTER to continue.&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%2Feneaslari.com%2F1b23ac9d-312d-4dec-adeb-138cc8e139bb.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%2Feneaslari.com%2F1b23ac9d-312d-4dec-adeb-138cc8e139bb.png" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Installation Begins&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Your Ubuntu server installation is now underway! It's downloading and installing numerous packages, so grab a coffee and hang tight—it'll be worth the wait! ☕🕒&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%2Feneaslari.com%2F2607360a-d0d1-4f80-986d-88a69218d8e4.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%2Feneaslari.com%2F2607360a-d0d1-4f80-986d-88a69218d8e4.png" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 14 - Reboot Ubuntu Server&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After the installation wraps up, choose "Reboot Now" and press ENTER to restart your Ubuntu server and bring all the changes to life!&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%2Feneaslari.com%2Fb9de8518-c97e-4ebd-9105-afabcd6d0bf3.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%2Feneaslari.com%2Fb9de8518-c97e-4ebd-9105-afabcd6d0bf3.png" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Congratulations!&lt;/strong&gt; 🎉 Ubuntu 22.04 LTS server is successfully installed! You're all set to start using your new server. Great job!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Log in to Ubuntu Server&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Time to dive in! Log in to your newly installed Ubuntu server using the username and password you set up during the installation. You’re ready to start exploring your new server environment! 🚀&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%2Feneaslari.com%2F2c2ae8f2-c276-4352-b79e-dc6af25bd423.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%2Feneaslari.com%2F2c2ae8f2-c276-4352-b79e-dc6af25bd423.png" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update Ubuntu&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Right after installation, it's crucial to get the latest updates. For Ubuntu, fire up your terminal and run these commands to ensure everything is up-to-date:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;To fetch the list of available updates:
&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;sudo &lt;/span&gt;apt update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;To upgrade all your packages to the latest versions:
&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;sudo &lt;/span&gt;apt full-upgrade
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This will keep your server secure and running smoothly.&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%2Feneaslari.com%2Fb15c24b3-2b4b-4792-978a-013eefa1205f.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%2Feneaslari.com%2Fb15c24b3-2b4b-4792-978a-013eefa1205f.png" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;During the installing updates task, you will be prompted to restart some services. Choose OK to do so.&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%2Feneaslari.com%2F09645010-3ecf-450b-adb8-e512e51f6438.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%2Feneaslari.com%2F09645010-3ecf-450b-adb8-e512e51f6438.png" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Clean Up and Reboot&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After updating, it's good practice to clean up any unnecessary files or packages. Here's how you can tidy up your Ubuntu server:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Remove packages that are no longer required:
&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;sudo &lt;/span&gt;apt autoremove
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Clean up the local repository of retrieved package files:
&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;sudo &lt;/span&gt;apt autoclean
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Once that's done, give your system a fresh start with a reboot:&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;sudo &lt;/span&gt;reboot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures your server is lean, clean, and up to date!&lt;/p&gt;

&lt;p&gt;To utilize the Linux server now ready on VMware, you can directly access it, but for those who prefer a visual directory structure for file editing, Visual Studio Code is a great option. You can connect to the server via SSH through Visual Studio Code. It's important to note that the virtual machine must remain running for the duration of your connection session with Visual Studio Code. Here's how to set this up for a more efficient workflow.&lt;/p&gt;

&lt;p&gt;Let's connect to our VPS with visual studio Code&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1 — Install the Remote-SSH Plugin&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Search Remote-SSH on extensions Marketplace and install 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%2Fvbxk74zjfjan807evtnm.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%2Fvbxk74zjfjan807evtnm.png" alt="Image description" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2 — Configuring the Remote-SSH Plugin and Connecting To Your Server&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now that you have the plugin installed you can configure it to connect to a server. To do so, you’ll need the following pieces of information:&lt;/p&gt;

&lt;p&gt;The server’s IP or hostname.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The server’s IP or hostname.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The username you’ll connect with.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The private key you’ll use to authenticate your user.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’ll use this information to create an SSH configuration file that Visual Studio Code can use to SSH to the server to sync files and execute code on your behalf. You will create this configuration using Visual Studio Code.&lt;/p&gt;

&lt;p&gt;Now that you have the Remote-SSH plugin installed, you’ll see a small green box in the bottom left-hand corner of the Visual Studio Code interface.&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%2Fd7xecr6r1fqkzat3iqda.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%2Fd7xecr6r1fqkzat3iqda.png" alt="Image description" width="115" height="192"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click the button, and a dialog box appears in the top center. Select Remote-SSH: Open Configuration File… from the list:&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%2Fv38mc6dmxsv95wb8uy37.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%2Fv38mc6dmxsv95wb8uy37.png" alt="Image description" width="800" height="123"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next prompt will ask you which configuration file you want to open. If you’re on Windows, you’ll see two locations: one in your personal user directory, and one in the installation location for SSH. You should use the file in your user directory when configuring the server.&lt;/p&gt;

&lt;p&gt;Select the file and your editor will open the config file. Add the following code to the file to define the connection to your server, replacing the highlighted sections with the information for your server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Host my_remote_server
    HostName your_server_ip_or_hostname
    User sammy
    IdentityFile /location/of/your/private/key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Visual Studio Code is now configured and ready to connect to your server. Click on the green Open a remote window button in the bottom left-hand corner and select Remote-SSH: Connect to Host…&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%2F9qdadrz18nm55ihu0nlt.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%2F9qdadrz18nm55ihu0nlt.png" alt="Image description" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you’ve done this all the available and configured servers will appear in the dropdown menu. Select the server that you want to connect to from this list.&lt;/p&gt;

&lt;p&gt;If this is the first time you have connected to this server from your machine, you’ll likely be prompted with the SSH Fingerprint verification dialog, like the one in the following 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%2Fwyzqd1lyhkbh69m5jzqz.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%2Fwyzqd1lyhkbh69m5jzqz.png" alt="Image description" width="800" height="120"&gt;&lt;/a&gt;&lt;br&gt;
This is to ensure that you are really connecting to the server you think you are. You can verify this by logging in to your server manually and running ssh-keygen -l -f /etc/ssh/ssh_host_key.pub to view the fingerprint of the server. If this fingerprint is the same as the one being presented to you in Visual Studio Code, then you are indeed connecting to the server you think you are so you can click Continue.&lt;/p&gt;

&lt;p&gt;Visual Studio Code defaults to opening a new window when a new connection is made. A new window will appear with the welcome screen. You’ll know that your connection was successful if you see SSH: your_ip_address_or_hostname in the green box in the bottom left-hand corner. This means that Visual Studio Code is connected and communicating with your remote 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%2Fu4d7w430b5ke83hii80u.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%2Fu4d7w430b5ke83hii80u.png" alt="Image description" width="800" height="47"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next let's clean and update the server&lt;/p&gt;

&lt;p&gt;Run the following commands&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt clean all &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt dist-upgrade
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/www/html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Nginx&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Nginx, pronounced like “engine-ex”, is an open-source web server that, since its initial success as a web server, is now also used as a reverse proxy, HTTP cache, and load balancer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Installing Nginx&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;UFW&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Uncomplicated Firewall (UFW) is a program for managing a netfilter firewall designed to be easy to use. It uses a command-line interface consisting of a small number of simple commands, and uses iptables for configuration. UFW is available by default in all Ubuntu installations since 8.04 LTS.[1] UFW has been available by default in all Debian installations since 10.&lt;/p&gt;

&lt;p&gt;Install ufw&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;ufw
ufw &lt;span class="nb"&gt;enable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Give nginx full control of firewall&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Now you have a full configured ubuntu server. You can run Node.js, dotNet core, static websites , database servers and many other things  into your machine&lt;/p&gt;

&lt;p&gt;Tell me if you want to to make a new post on how to run some of them in your server.&lt;/p&gt;

&lt;p&gt;Thanks for your time.&lt;br&gt;
Leave a question or comment below.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>ubuntu</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Daily Habit Persistence for Programmers: Techniques for Consistent Coding Practice</title>
      <dc:creator>EneasLari</dc:creator>
      <pubDate>Mon, 11 Dec 2023 12:52:41 +0000</pubDate>
      <link>https://forem.com/eneaslari/daily-habit-persistence-for-programmers-techniques-for-consistent-coding-practice-cf6</link>
      <guid>https://forem.com/eneaslari/daily-habit-persistence-for-programmers-techniques-for-consistent-coding-practice-cf6</guid>
      <description>&lt;p&gt;A habit tracker is an efficient tool for monitoring consistency in habits, valuable for programmers looking to enhance their coding discipline. It involves marking a calendar each day a specific habit, like coding, is practiced, creating a visual streak of consistency. This method, used historically by figures like Benjamin Franklin for personal virtues and Jerry Seinfeld for writing jokes, can be adapted by programmers for daily coding tasks. Franklin's approach involved nightly reflections on progress, while Seinfeld focused on maintaining a continuous streak of joke-writing, valuing consistency over quality.&lt;/p&gt;

&lt;p&gt;For programmers, applying this "don't break the chain" philosophy can mean setting daily coding goals, irrespective of the complexity or success of the task, to build a habit of regular coding. This could be as simple as writing a few lines of code, debugging, or learning a new programming concept each day. The habit tracker, by making the habit of coding visible and satisfying, can be a powerful tool for personal and professional growth, aiding in developing a robust portfolio and enhancing coding skills through consistent practice.&lt;/p&gt;

&lt;p&gt;Research supports the effectiveness of habit tracking in various goals, such as weight loss and quitting smoking, where tracking progress leads to better outcomes. For instance, a study showed that people who maintained a daily food log lost twice as much weight compared to those who didn’t. Similarly, for programmers, tracking their daily coding activities, whether it's writing new code, fixing bugs, or learning new technologies, can spark a desire to maintain and improve their habits.&lt;/p&gt;

&lt;p&gt;Additionally, habit tracking promotes honesty and self-awareness in evaluating one's work. Programmers often have a distorted view of their productivity or coding skills. By tracking their daily coding habits, they gain a clear and objective view of their actual performance. This visibility can be a powerful motivator to stay consistent and honest about one’s coding practices and progress, helping to overcome any self-deception about the amount of work done or skills mastered.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let’s break down the benefits of habit tracking.
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Obvious&lt;/strong&gt;: Habit tracking offers significant benefits, especially for programmers looking to enhance their coding routines. The first key benefit is its visibility. When a programmer records their coding activities, it acts as a trigger for subsequent actions. This method creates a series of visual cues, like a streak of marked days on a calendar, indicating days spent coding or working on a project. Seeing this visual representation of their coding streak can motivate programmers to continue their practice.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Attractive&lt;/strong&gt;: The progression visible through habit tracking is a strong motivator. For programmers, seeing a series of completed tasks, such as days spent coding or problems solved, signals forward movement and boosts motivation. This is especially helpful during challenging periods, providing a visual reminder of past successes and encouraging continuation. The sight of an unmarked day can serve as a prompt to engage in coding to maintain the streak, reinforcing the habit of daily programming.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Satisfying&lt;/strong&gt;: The act of tracking itself becomes rewarding. For a programmer, marking off a day of coding, completing a project phase, or solving a challenging bug provides a sense of achievement. Watching the growth of accomplishments, like an expanding codebase or a series of successful deployments, is intrinsically gratifying. Habit tracking shifts focus from the end goal (like developing a complex software) to the process (consistent coding), fostering a mindset of regular improvement and persistence.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In summary, habit tracking for programmers is beneficial as it (1) provides a clear visual cue to continue coding practices, (2) motivates through visible progress and the desire not to break the streak, and (3) offers satisfaction in recording each coding session. This process helps in framing a programmer's identity around consistent practice and improvement.&lt;/p&gt;

&lt;p&gt;To make tracking more manageable, automation is key. Tools like integrated development environments (IDEs) can automatically track coding progress, while manual tracking should focus on key programming habits. Prompt recording of activities post-completion can seamlessly integrate into a programmer's routine, making the habit of tracking as natural as coding itself.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>programming</category>
      <category>learning</category>
    </item>
    <item>
      <title>How to Identify and Correct the Reasons Behind Your Bad Habits</title>
      <dc:creator>EneasLari</dc:creator>
      <pubDate>Mon, 20 Nov 2023 07:40:13 +0000</pubDate>
      <link>https://forem.com/eneaslari/how-to-identify-and-correct-the-reasons-behind-your-bad-habits-3ph8</link>
      <guid>https://forem.com/eneaslari/how-to-identify-and-correct-the-reasons-behind-your-bad-habits-3ph8</guid>
      <description>&lt;p&gt;Today, we're tackling a crucial topic: understanding and changing your bad habits. Our inspiration comes from "Atomic Habits" by James Clear, a book that greatly influenced my view on habit formation. We'll discuss practical methods to identify why we stick to negative habits and how to effectively replace them with better ones. &lt;/p&gt;

&lt;h4&gt;
  
  
  Understanding the Deep Motives Behind Our Habits and Cravings
&lt;/h4&gt;

&lt;p&gt;Every action we take is driven by a basic desire and a deeper need. For example, we eat not only because food tastes good, but also because it's necessary for survival. Our cravings often reflect deeper needs like feeling safe, accepted, or important.&lt;/p&gt;

&lt;p&gt;Our habits, like using social media or playing video games, fulfill these deeper needs. These habits are modern ways to satisfy age-old human needs, but they're not always the best methods. We stick to habits we've learned, even if better options exist.&lt;/p&gt;

&lt;p&gt;Habits form through associations our brain makes with things around us. For instance, we learn not to touch a hot stove because we associate it with getting burned.&lt;/p&gt;

&lt;p&gt;Our habits are based on our experiences and what we've learned over time. We use past experiences to predict how to react in situations. Our actions depend on these predictions, and different people may react differently to the same thing based on their past experiences.&lt;/p&gt;

&lt;p&gt;Feelings, like being cold or hot, influence our actions. When we feel something is missing, we crave a change. For example, feeling cold makes us wear more clothes. Desire is the wish to feel differently from how we currently feel, driving actions like eating too much or using social media.&lt;/p&gt;

&lt;p&gt;Our feelings help us decide what to do, as they tell us what to pursue or avoid. Emotions help us label things as good or bad.&lt;/p&gt;

&lt;p&gt;In summary, our cravings and habits are ways to meet deep needs. When a habit satisfies a need, we repeat it. Understanding this can help us choose better habits that make us feel good.&lt;/p&gt;

&lt;h4&gt;
  
  
  How to Rewire Your Mind to Find Pleasure in Challenging Habits
&lt;/h4&gt;

&lt;p&gt;To make challenging habits more appealing, try associating them with positive experiences and shift your mindset.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Change Your Language&lt;/strong&gt;: Replace "have to" with "get to" in your daily tasks. This simple switch can transform tasks from burdens to opportunities.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Focus on Positive Aspects&lt;/strong&gt;: Highlight the benefits of your habits instead of their drawbacks. This helps in reprogramming your mind to see the habit as more attractive.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Associate Habits with Enjoyable Activities&lt;/strong&gt;: Link your habits with something you enjoy. This association can become a cue for motivation. For example, play a certain song to get into a specific mood.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Mindset Shifts for Different Situations&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Exercise&lt;/strong&gt;: See it as skill-building and strengthening rather than a chore.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Finance&lt;/strong&gt;: View saving money as increasing future freedom, not as sacrifice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Meditation&lt;/strong&gt;: Treat distractions as opportunities for practice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance Anxiety&lt;/strong&gt;: Reframe nervousness as excitement and readiness.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create Motivation Rituals&lt;/strong&gt;: Develop routines that prepare you mentally and emotionally for a habit. These can range from stretching before a sport to a simple breathing and smiling routine before doing something you love.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Cues for Emotional State Changes&lt;/strong&gt;: Establish a routine that signifies a positive emotional state, like happiness. Use this routine whenever you need to shift your mood.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reframe Your Perception of Habits&lt;/strong&gt;: View each habit as an opportunity, not a chore. This reframing can make the habit more appealing.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By applying these strategies, you can transform difficult habits into attractive ones by reshaping how you view and interact with them.&lt;/p&gt;

&lt;p&gt;Thank you for joining me on this journey to understand and amend our bad habits. Your willingness to explore and address these challenges is the first step towards lasting change. I'm eager to hear about your progress and insights, so please feel free to share your experiences in the comments or reach out directly. Until next time, embrace each day as a new opportunity for growth and self-improvement. Farewell for now, and good luck on your continuous journey towards a better and more fulfilling life!"&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>learning</category>
      <category>programming</category>
    </item>
    <item>
      <title>The Pomodoro Technique - How to use it effectively as a programmer</title>
      <dc:creator>EneasLari</dc:creator>
      <pubDate>Tue, 14 Nov 2023 15:38:15 +0000</pubDate>
      <link>https://forem.com/eneaslari/the-pomodoro-technique-how-to-use-it-effectively-as-a-programmer-271f</link>
      <guid>https://forem.com/eneaslari/the-pomodoro-technique-how-to-use-it-effectively-as-a-programmer-271f</guid>
      <description>&lt;h3&gt;
  
  
  What is Pomodoro Technique?
&lt;/h3&gt;

&lt;p&gt;The Pomodoro Technique is a time management method developed by Francesco Cirillo in the late 1980s. It uses a timer to break work into intervals, traditionally 25 minutes in length, separated by short breaks. Each interval is known as a "pomodoro", from the Italian word for 'tomato', inspired by the tomato-shaped kitchen timer Cirillo used as a university student. This technique encourages individuals to work with the time they have—rather than against it. By integrating frequent short breaks, it aims to ensure consistent productivity and prevent mental fatigue.&lt;/p&gt;

&lt;h4&gt;
  
  
  Preparation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Set up your programming environment before starting the timer. This includes opening necessary files, setting up your IDE, and having a clear task list or backlog of programming tasks ready.&lt;/li&gt;
&lt;li&gt;Choose a task or a set of related tasks that you can work on during a single Pomodoro session.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Pomodoro Sessions (25 minutes):
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Start a Pomodoro timer for 25 minutes.&lt;/li&gt;
&lt;li&gt;Focus solely on programming tasks during this time. Avoid distractions like social media, emails, or casual browsing.&lt;/li&gt;
&lt;li&gt;If a distraction or a new task comes up, jot it down on a piece of paper and continue with your current task.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Short Break (5 minutes):
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;After 25 minutes, take a 5-minute break. This is crucial for mental relaxation.&lt;/li&gt;
&lt;li&gt;During the break, stand up, stretch, grab a drink, or do something non-work related to reset your mind.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Long Break (after 4 Pomodoros):
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;After completing four Pomodoro sessions, take a longer break, around 15 to 30 minutes.&lt;/li&gt;
&lt;li&gt;Use this time to completely step away from your work. This could involve a short walk, a light snack, or a relaxing activity.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Reflection:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;At the end of the day, spend a few minutes reflecting on what you've accomplished and what can be improved in your process.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Task Management:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Adjust tasks based on their complexity. Some tasks may require more than one Pomodoro. Break down larger tasks into smaller, manageable chunks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Dealing with Complex Problems:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;For complex programming problems, use one Pomodoro to plan your approach and subsequent sessions to execute it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Consider adopting the Pomodoro Technique if you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If minor distractions frequently disrupt your workday.&lt;/li&gt;
&lt;li&gt;If you tend to work beyond the point of optimal productivity.&lt;/li&gt;
&lt;li&gt;If you engage in open-ended tasks, like studying for exams or researching for blog posts, that can consume unlimited time.&lt;/li&gt;
&lt;li&gt;If you're overly optimistic about your daily productivity capacity.&lt;/li&gt;
&lt;li&gt;If you enjoy setting goals in a fun, game-like way.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Effectiveness of the Pomodoro Technique
&lt;/h3&gt;

&lt;p&gt;The Pomodoro Technique, often perceived as whimsical due to its use of a tomato (Pomodoro in Italian) as a symbol for time intervals, stands out for its remarkable efficacy in enhancing productivity. Here's an exploration of what makes this method uniquely adept at improving work efficiency:&lt;/p&gt;

&lt;h4&gt;
  
  
  Facilitating a Simple Start
&lt;/h4&gt;

&lt;p&gt;Procrastination, contrary to popular belief, is less about laziness and more about avoiding negative emotions associated with daunting tasks. Facing a large, uncertain project can be overwhelming, leading many to seek temporary mood boosts through distractions like social media or streaming services.&lt;/p&gt;

&lt;p&gt;However, research suggests that breaking down these overwhelming tasks into tiny, non-intimidating steps is an effective way to combat procrastination. For instance, rather than attempting to write a novel in one go, starting with just five minutes of writing, or even editing a single paragraph, can be less daunting. This approach of taking small steps for a short duration makes it easier to tackle a larger project.&lt;/p&gt;

&lt;p&gt;This is where the Pomodoro Technique shines. It encourages breaking down large tasks or projects into 25-minute segments. This focus on short-term goals keeps you centered on the immediate task rather than being overwhelmed by the entire project. The key is not to worry about the final outcome but to progress one Pomodoro at a time.&lt;/p&gt;

&lt;h4&gt;
  
  
  Counteracting Distractions
&lt;/h4&gt;

&lt;p&gt;In our information-saturated world, distractions are a constant challenge. Interruptions, especially during a state of flow, can significantly hinder the regaining of focus. Surprisingly, studies have shown that more than half of all workday distractions are self-imposed, often justified as necessary or minor.&lt;/p&gt;

&lt;p&gt;Yet, these seemingly small interruptions accumulate, affecting not just the time lost to the distraction but also the time needed to refocus. For example, a quick glance at Facebook can lead to a 20-minute effort to refocus on the original task.&lt;/p&gt;

&lt;p&gt;The Pomodoro Technique addresses this by helping you resist self-interruptions and retraining your brain to maintain focus. Each Pomodoro is dedicated to a single task, with breaks serving as opportunities to reset and refocus your attention on the task at hand. This structured approach significantly minimizes the impact of both external and internal distractions, leading to more productive work sessions.&lt;/p&gt;

&lt;p&gt;The Pomodoro Technique helps combat the planning fallacy, where we underestimate the time needed for future tasks. By working in short, timed sessions, time transforms from an abstract concept to a tangible unit, called a "pomodoro." Each pomodoro is a focused effort on a task, changing how we perceive time. Instead of seeing time as something lost, it becomes a positive measure of accomplished tasks.&lt;/p&gt;

&lt;p&gt;This method alters our perception of time, making it a precise productivity measure, leading to more realistic time estimates. Using the Pomodoro technique, you gain a clear understanding of your time and efforts, improving your ability to plan and assess tasks. Over time, this allows for more accurate task estimation and the development of consistent work habits.&lt;/p&gt;

&lt;h3&gt;
  
  
  Turning Productivity into a Game
&lt;/h3&gt;

&lt;p&gt;The Pomodoro Technique offers a chance for continuous improvement with each session. As Cirillo suggests, gaining speed in your tasks comes from enhanced concentration and awareness, achieved one pomodoro at a time.&lt;/p&gt;

&lt;p&gt;This method is effective because it emphasizes regularity over flawlessness. Every pomodoro is a new opportunity to assess your objectives, sharpen your focus, and minimize interruptions. It's a flexible system that you can tailor to your needs.&lt;/p&gt;

&lt;p&gt;To keep yourself motivated, try gradually increasing your daily pomodoro count. Set challenges, like completing a major task within a specific number of pomodoros, or aim for a certain number of pomodoros each day to maintain a streak. Viewing time management through the lens of 'tomatoes' rather than hours adds an element of enjoyment to the process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Alternatives to the Pomodoro Technique
&lt;/h3&gt;

&lt;p&gt;The Pomodoro Technique, which involves focused work sessions interspersed with short breaks, is popular among programmers, but there are several alternative methods that can also be effective. Here are some alternatives to consider:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flow Time Technique&lt;/strong&gt;: Inspired by the concept of 'flow' in psychology, this method involves working in natural cycles of concentration and rest. Programmers work until they feel a decrease in focus, then take a short break. This technique is more flexible than the Pomodoro and aligns with the natural attention span.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Time Blocking&lt;/strong&gt;: This involves allocating specific blocks of time to different tasks or types of work. For instance, a programmer might block out a morning for deep work (like coding) and afternoons for meetings and emails. This helps in managing the day more effectively.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The 52-17 Method&lt;/strong&gt;: Similar to Pomodoro but with longer intervals. You work for 52 minutes and then take a 17-minute break. This longer period can be more suitable for tasks that require deep concentration, like programming.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Eisenhower Matrix&lt;/strong&gt;: Not a time management technique per se, but a prioritization tool. Tasks are divided into four categories: urgent and important, important but not urgent, urgent but not important, and neither urgent nor important. This helps in focusing on what really matters.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GTD (Getting Things Done)&lt;/strong&gt;: A holistic approach to productivity that involves capturing all the tasks you need to accomplish in a trusted system, then organizing and prioritizing these tasks. This can help programmers manage complex projects and multitasking more efficiently.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The 90-Minute Focus Session&lt;/strong&gt;: Based on the idea that the brain naturally goes through a rest-activity cycle every 90 minutes. Programmers work for 90 minutes followed by a significant break. This can be especially useful for long, uninterrupted coding sessions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ultradian Rhythms Management&lt;/strong&gt;: Similar to the 90-minute focus session, this method is based on the body's natural rhythms. It suggests working in tandem with these rhythms (usually 90-120 minutes of work followed by a break) to maximize productivity and maintain energy levels.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Two-Minute Rule&lt;/strong&gt;: A part of the GTD methodology, where if a task can be done in two minutes or less, do it immediately. This is useful for small coding tweaks or quick email responses, preventing small tasks from piling up.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Must, Should, Want Method&lt;/strong&gt;: A prioritization technique where tasks are categorized into what you must do, should do, and want to do. This helps in balancing urgent tasks with long-term projects and personal development.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Custom Hybrid Methods&lt;/strong&gt;: Many programmers create their own hybrid productivity methods, combining elements from different techniques to best suit their workflow, project needs, and personal preferences.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each of these techniques has its advantages and can be adapted to the unique workflow of individual programmers. Experimenting with different methods can help in finding the one that best enhances productivity and work satisfaction.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>programming</category>
      <category>discuss</category>
      <category>learning</category>
    </item>
  </channel>
</rss>
