<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Michael</title>
    <description>The latest articles on DEV Community by Michael (@mbround18).</description>
    <link>https://dev.to/mbround18</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%2F657213%2F36953563-8d9b-4954-af48-d7b0e9d365b7.png</url>
      <title>DEV Community: Michael</title>
      <link>https://dev.to/mbround18</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mbround18"/>
    <language>en</language>
    <item>
      <title>Supercharge Your Hytale Modding Workflow with mdevtools</title>
      <dc:creator>Michael</dc:creator>
      <pubDate>Sun, 01 Feb 2026 01:29:17 +0000</pubDate>
      <link>https://dev.to/mbround18/hytale-mod-development-hot-reloading-46je</link>
      <guid>https://dev.to/mbround18/hytale-mod-development-hot-reloading-46je</guid>
      <description>&lt;p&gt;Tired of restarting your server every time you change a line of code?&lt;/p&gt;

&lt;p&gt;In this guide, we’ll set up &lt;strong&gt;mdevtools&lt;/strong&gt; to enable hot-reloading for your Hytale modding environment. By creating a tight loop between your Gradle build and your running server, you can iterate faster and stay in the flow.&lt;/p&gt;

&lt;p&gt;I’m actively using this exact workflow right now to build the procedural generation systems for &lt;strong&gt;&lt;a href="https://vex.boop.ninja" rel="noopener noreferrer"&gt;Vex's Dungeon Challenge&lt;/a&gt;&lt;/strong&gt;. When you are tweaking complex dungeon logic or iterating on gameplay mechanics, saving those 30-second restart loops saves hours of development time every week.&lt;/p&gt;

&lt;p&gt;Here is how to set it up.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. Download and Install mdevtools
&lt;/h3&gt;

&lt;p&gt;First, grab the latest &lt;strong&gt;mdevtools&lt;/strong&gt; jar file from CurseForge:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.curseforge.com/hytale/mods/mdevtools-development-tools" rel="noopener noreferrer"&gt;Download mdevtools&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where to place the jar:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Depending on your project structure, place the downloaded jar in the following location:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Project Type&lt;/th&gt;
&lt;th&gt;Destination Path&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Standard Template&lt;/strong&gt; (mbround18)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;data/server/Server/builtin&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Custom Setup&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Create a &lt;code&gt;builtin&lt;/code&gt; folder in your server root and drop it there.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  2. Configure Your Manifest
&lt;/h3&gt;

&lt;p&gt;To ensure the mod loads correctly without crashing, verify that your &lt;code&gt;hytale-mod.json&lt;/code&gt; (or equivalent manifest) contains the dependency fields.&lt;/p&gt;

&lt;p&gt;Add the following to your manifest:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"Dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"OptionalDependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; For single-mod development, leaving these objects empty is perfectly fine. They just need to be present.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  3. Automate the Copy Process with Gradle
&lt;/h3&gt;

&lt;p&gt;We need a way to move your compiled jar into the server's mods folder automatically. Add this task to your &lt;code&gt;build.gradle&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;This snippet creates an &lt;code&gt;installModJar&lt;/code&gt; task that builds your jar and immediately copies it to the server directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="c1"&gt;// In build.gradle&lt;/span&gt;
&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;register&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"installModJar"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Copy&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 1. Build the jar first&lt;/span&gt;
    &lt;span class="n"&gt;dependsOn&lt;/span&gt; &lt;span class="s2"&gt;":plugins:yourmod:jar"&lt;/span&gt; 

    &lt;span class="c1"&gt;// 2. Grab the output file&lt;/span&gt;
    &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;":plugins:yourmod"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;named&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"jar"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;flatMap&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;archiveFile&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// 3. Drop it into the server mods folder&lt;/span&gt;
    &lt;span class="n"&gt;into&lt;/span&gt; &lt;span class="nf"&gt;file&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"data/server/Server/mods"&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;h3&gt;
  
  
  4. The "Hot Reload" Script
&lt;/h3&gt;

&lt;p&gt;Finally, we tie it all together with a lightweight Bash script. This allows you to rebuild and replace the jar without restarting your Docker container.&lt;/p&gt;

&lt;p&gt;Save this as &lt;code&gt;dev-reload.sh&lt;/code&gt; in your project root and make it executable (&lt;code&gt;chmod +x dev-reload.sh&lt;/code&gt;).&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="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail
&lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;$'&lt;/span&gt;&lt;span class="se"&gt;\n\t&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;

&lt;span class="c"&gt;# Configuration&lt;/span&gt;
&lt;span class="nv"&gt;WATCH_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"plugin/src"&lt;/span&gt;
&lt;span class="nv"&gt;BUILD_TASK&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"installModJar"&lt;/span&gt; &lt;span class="c"&gt;# Updated to match the Gradle task above&lt;/span&gt;
&lt;span class="nv"&gt;JAR_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"plugin-name-0.1.0.jar"&lt;/span&gt;
&lt;span class="nv"&gt;JAR_SOURCE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"./plugin/build/libs"&lt;/span&gt;
&lt;span class="nv"&gt;JAR_DEST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"data/server/Server/mods"&lt;/span&gt;
&lt;span class="nv"&gt;DEBOUNCE_SECONDS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5

&lt;span class="nv"&gt;last_build_time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0

build_and_copy&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;# Run the gradle task we created in Step 3&lt;/span&gt;
  ./gradlew &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BUILD_TASK&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 
&lt;span class="o"&gt;}&lt;/span&gt;

hard_reload&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  build_and_copy
  &lt;span class="c"&gt;# NOTE: UI assets do NOT hot reload. &lt;/span&gt;
  &lt;span class="c"&gt;# If you have new UI files, uncomment lines below to rebuild assets zip.&lt;/span&gt;
  &lt;span class="c"&gt;# ./gradlew assetsZip \&lt;/span&gt;
  &lt;span class="c"&gt;#    &amp;amp;&amp;amp; cp "dist/$(ls dist | grep -m1 -E 'assets.*\.zip')" "$JAR_DEST/"&lt;/span&gt;

  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Restarting Docker container..."&lt;/span&gt;
  docker compose restart
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hard reload complete."&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=========================================================="&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;" Hytale Dev Loop: Ready."&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;" [r] Reload Code (Hot)"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;" [h] Hard Reload (Restart Container + UI)"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;" [e] Exit"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=========================================================="&lt;/span&gt;

&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt; "&lt;/span&gt;
  &lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;-n1&lt;/span&gt; key
  &lt;span class="nb"&gt;echo
  &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in
    &lt;/span&gt;r|R&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nv"&gt;now&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%s&lt;span class="si"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt; now - last_build_time &amp;lt; DEBOUNCE_SECONDS &lt;span class="o"&gt;))&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Debounced. Wait a moment before reloading again."&lt;/span&gt;
        &lt;span class="k"&gt;continue
      fi
      &lt;/span&gt;&lt;span class="nv"&gt;last_build_time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$now&lt;/span&gt;
      &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Rebuilding and hot-swapping..."&lt;/span&gt;
      build_and_copy
      &lt;span class="p"&gt;;;&lt;/span&gt;
    h|H&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hard reload requested..."&lt;/span&gt;
      hard_reload
      &lt;span class="p"&gt;;;&lt;/span&gt;
    e|E&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Exiting."&lt;/span&gt;
      &lt;span class="nb"&gt;break&lt;/span&gt;
      &lt;span class="p"&gt;;;&lt;/span&gt;
    &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="c"&gt;# Ignore other keys&lt;/span&gt;
      &lt;span class="p"&gt;;;&lt;/span&gt;
  &lt;span class="k"&gt;esac&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;

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

&lt;/div&gt;






&lt;h3&gt;
  
  
  5. Bonus: Better UI Development
&lt;/h3&gt;

&lt;p&gt;While &lt;strong&gt;mdevtools&lt;/strong&gt; handles your Java code hot-reloading, writing Hytale UI files (&lt;code&gt;.ui&lt;/code&gt;) can still be tricky. The game requires a Hard Reload to see UI changes, so you want to catch errors &lt;em&gt;before&lt;/em&gt; you restart.&lt;/p&gt;

&lt;p&gt;I’ve built a VS Code extension specifically to solve this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=MBRound18.hytale-ui-ultimate" rel="noopener noreferrer"&gt;Hytale UI Ultimate&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I use this tool to build the interfaces for Vex's Dungeon Challenge. It provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Syntax Highlighting&lt;/strong&gt; for &lt;code&gt;.ui&lt;/code&gt; files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Diagnostics&lt;/strong&gt; to catch invalid group naming and missing attributes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Import Navigation&lt;/strong&gt; (Ctrl+Click) to jump between UI files.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pairing this extension with the &lt;strong&gt;Hard Reload (&lt;code&gt;h&lt;/code&gt;)&lt;/strong&gt; script above gives you the most robust workflow currently possible.&lt;/p&gt;




&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;You now have a terminal dashboard for development. Instead of manually moving files or waiting for long boot times, you can simply press &lt;code&gt;r&lt;/code&gt; to inject your new code instantly.&lt;/p&gt;

&lt;p&gt;Happy Modding!&lt;/p&gt;

</description>
      <category>hytale</category>
      <category>java</category>
      <category>programming</category>
    </item>
    <item>
      <title>Job Search Fatigue? Here’s How to Fight Burnout and Stay Motivated</title>
      <dc:creator>Michael</dc:creator>
      <pubDate>Tue, 17 Sep 2024 20:24:46 +0000</pubDate>
      <link>https://dev.to/mbround18/job-search-fatigue-heres-how-to-fight-burnout-and-stay-motivated-fm2</link>
      <guid>https://dev.to/mbround18/job-search-fatigue-heres-how-to-fight-burnout-and-stay-motivated-fm2</guid>
      <description>&lt;p&gt;Job searching can be difficult, especially in today’s competitive market, where AI and tough economic conditions add pressure, particularly for engineering roles. However, with the right strategies, you can stay upbeat and motivated on your search! Here are some helpful tips:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Start Your Day Like You’re Going to Work&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This might sound simple, but getting ready in the morning as if you’re heading into the office is incredibly effective. Getting out of bed, following your routine, and dressing for success puts your mind into a productive space. While it may be tempting to lounge around or mindlessly scroll through job listings, sticking to a routine keeps you mentally prepared for that dream job once you land it.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Keep a Detailed Job Application Log&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Organization is key when applying to multiple jobs. Creating a spreadsheet to track applications, including the job title, company, salary, link to the posting, and interview status, can be a lifesaver. This will save you from scrambling to find information when a recruiter reaches out. A well-kept log keeps you prepared and helps you follow up efficiently.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Turn Rejections into Learning Opportunities&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Rejection emails aren’t fun, but they can offer valuable insights. After receiving one, refer to your log and look up the original job posting. Then, consider sending a polite message to the hiring manager via LinkedIn. Thank them for the opportunity and ask if there was anything in your resume or skills they noticed that could be improved. Not all managers will reply, but those who do can provide feedback that helps you grow.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Take Breaks to Recharge&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;It may sound counterintuitive, but breaks are essential to maintain focus. Stand up, walk the dog, play with your cat, or simply stretch. Movement boosts blood flow, helping you think more clearly. It also combats the drowsiness that creeps in after hours of job hunting. Staying refreshed ensures you’re applying with energy and enthusiasm.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. &lt;strong&gt;Work on a Side Project&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Whether technical or non-technical, take time to work on something just for yourself. Dive into a new programming language, contribute to an open-source project, or even tackle some household tasks. Keeping your brain engaged and learning is key to staying sharp. Bonus points if your side project is on GitHub or GitLab — it helps showcase your skills and keeps you visible to potential employers.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Final Thoughts&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You’ve got this! Job searching in today’s world can feel overwhelming, with recruiters buried under resumes and applicants feeling the pressure to send dozens of applications just to get a callback. But remember, you’re not alone. Lean into your network. Now more than ever, securing a job isn’t just about the number of applications; it’s about building relationships. Reach out to former coworkers, check in, and open up a conversation — you never know where it might lead!&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Author's Note&lt;/strong&gt;: &lt;em&gt;I recently lost my job, and these are the guidelines I try to follow every day. With the support of the wagging tails of my two dogs and the encouragement of my wife, I’ve starting each day motivated and with a smile. I hope these tips help you as much as they’ve helped me stay motivated during this process.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How to use Meilisearch with WikiJS</title>
      <dc:creator>Michael</dc:creator>
      <pubDate>Wed, 21 Aug 2024 17:56:24 +0000</pubDate>
      <link>https://dev.to/mbround18/how-to-use-meilisearch-with-wikijs-5g3b</link>
      <guid>https://dev.to/mbround18/how-to-use-meilisearch-with-wikijs-5g3b</guid>
      <description>&lt;h2&gt;
  
  
  TLDR
&lt;/h2&gt;

&lt;p&gt;Sauce: &lt;a href="https://github.com/mbround18/wikijs-module-meilisearch" rel="noopener noreferrer"&gt;https://github.com/mbround18/wikijs-module-meilisearch&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The software
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is Meilisearch
&lt;/h3&gt;

&lt;p&gt;Meilisearch is an open-source search engine built for speed and simplicity. Written in Rust, it’s designed to deliver fast, relevant search results with minimal configuration. Meilisearch excels at full-text search and is optimized for performance, even with large datasets. It supports features like typo tolerance and customizable relevance ranking right out of the box.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.meilisearch.com/" rel="noopener noreferrer"&gt;Link to Meilisearch&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What is WikiJS
&lt;/h3&gt;

&lt;p&gt;Wiki.js is a modern, open-source wiki software that offers a powerful and flexible platform for managing and sharing content. Built on Node.js, it’s designed to be lightweight, fast, and easy to use, with a sleek and intuitive interface that makes it accessible for users of all skill levels.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://js.wiki/" rel="noopener noreferrer"&gt;Link to Wikijs&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to integrate the two
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Running instance of Meilisearch&lt;/li&gt;
&lt;li&gt;Running instance of wikijs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/mbround18/wikijs-module-meilisearch/blob/main/docker-compose.yml" rel="noopener noreferrer"&gt;If you dont have these, you can use this docker compose.&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Using the docker compose
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Download the docker compose into a directory.&lt;/li&gt;
&lt;li&gt;Create a folder called pkg&lt;/li&gt;
&lt;li&gt;Create a folder called tmp&lt;/li&gt;
&lt;li&gt;Create a folder called config.&lt;/li&gt;
&lt;li&gt;In the config folder, &lt;a href="https://github.com/mbround18/wikijs-module-meilisearch/blob/main/config/wiki.yml" rel="noopener noreferrer"&gt;for this demo download this config&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;docker compose up&lt;/code&gt; to have it generate the files as needed.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Installing the module
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to &lt;a href="https://github.com/mbround18/wikijs-module-meilisearch" rel="noopener noreferrer"&gt;the module that integrates them on github.com/mbround18/wikijs-module-meilisearch&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Navigate to the releases tab&lt;/li&gt;
&lt;li&gt;On the latest release download the Meilisearch.zip file.&lt;/li&gt;
&lt;li&gt;Extract the zip to &lt;code&gt;/wiki/server/modules/search/meilisearch&lt;/code&gt; on your wikijs server. If you are using compose, &lt;code&gt;docker compose down&lt;/code&gt; and extract the zip file into your &lt;code&gt;./pkg&lt;/code&gt; folder.&lt;/li&gt;
&lt;li&gt;Restart your wikijs server.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Setting up the module.
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Its recommended for a production instance, have meilisearch generate a new key for your app to use. You can do so via this curl command:&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--request&lt;/span&gt; POST &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--url&lt;/span&gt; http://localhost:7700/keys &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer demo'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'{
    "description": "Wikijs Integration",
    "actions": ["*"],
    "indexes": ["wiki_index"],
    "expiresAt": "2042-04-02T00:42:42Z"
}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;change the word demo to your master key. If you are following along with docker compose this will work with just demo. Unless you changed it in the compose file. Then use what you set for &lt;code&gt;$MEILI_MASTER_KEY&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;Log into your wikijs instance, for compose demo you might have to create the initial login. Just remember to set the url to &lt;code&gt;http://localhost:3000&lt;/code&gt; on that inital setup screen.&lt;/li&gt;
&lt;li&gt;Navigate to the admin dashboard.&lt;/li&gt;
&lt;li&gt;Click Search Engine&lt;/li&gt;
&lt;li&gt;Enable Meilisearch&lt;/li&gt;
&lt;li&gt;Adjust the API key and host as needed.&lt;/li&gt;
&lt;li&gt;Click Apply, if you do not get a green toast message, simply click apply again. This can happen due to the task in Meilisearch stalling while creating the index.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Its setup now what?
&lt;/h3&gt;

&lt;p&gt;Now you can start using Meilisearch to search your wiki! If you have existing content, you can click rebuild and it should add all your content to meilisearch! :) &lt;/p&gt;

&lt;p&gt;As you use wikijs normally it will Create, Update, and Delete documents in Meilisearch as part of normal page rendering. &lt;/p&gt;

&lt;p&gt;If you want to see a live example of this, on &lt;a href="https://wiki.boop.ninja/" rel="noopener noreferrer"&gt;my Dungeons and Dragons wiki&lt;/a&gt; we have this integrated already. It has been amazing to recall character data or scene data at your fingertips in an instant. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note about implementation, currently the suggestions match who lines. In the future, ill rewrite that segment to truncate and have smaller suggestions.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>meilisearch</category>
      <category>javascript</category>
      <category>rust</category>
      <category>wikijs</category>
    </item>
    <item>
      <title>Docker Caching with Compose</title>
      <dc:creator>Michael</dc:creator>
      <pubDate>Thu, 18 Jul 2024 16:33:27 +0000</pubDate>
      <link>https://dev.to/mbround18/docker-caching-with-compose-3l5i</link>
      <guid>https://dev.to/mbround18/docker-caching-with-compose-3l5i</guid>
      <description>&lt;p&gt;When working with Docker Compose, enabling caching can significantly speed up your builds by reusing layers from previous builds. This article will guide you through the process of setting up caching for Docker Compose, ensuring your development workflow is as efficient as possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before we start, make sure you have the following installed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docker CLI&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;yq&lt;/code&gt; CLI (YAML processor)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker-compose.yaml&lt;/code&gt; file&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step-by-Step Guide
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://gist.github.com/mbround18/80a83f452323fef63f62a87361756a7d" rel="noopener noreferrer"&gt;Skip the Step-by-Step and go straight to the sauce.&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Step 1: Check for Necessary Tools
&lt;/h3&gt;

&lt;p&gt;First, we need to ensure that the required tools are installed on your system. Here’s a script that checks for Docker CLI, &lt;code&gt;yq&lt;/code&gt; CLI, and the presence of the &lt;code&gt;docker-compose.yaml&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check for Docker CLI&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; docker &amp;amp;&amp;gt; /dev/null
&lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Docker CLI not found. Please install Docker."&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# Check for yq CLI&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; yq &amp;amp;&amp;gt; /dev/null
&lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"yq CLI not found. Please install yq."&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# Check for docker-compose.yaml&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; ./docker-compose.yaml &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"docker-compose.yaml not found. Please ensure the file exists in the current directory."&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Set Up Preflight Script
&lt;/h3&gt;

&lt;p&gt;The preflight script prepares the environment for caching. It sets up a temporary file path for the caching configuration.&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="c"&gt;# Set up necessary environment variables if not already set&lt;/span&gt;
: &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DOCKER_IMAGE&lt;/span&gt;:&lt;span class="p"&gt;=your_default_docker_image&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
: &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DOCKER_REGISTRY&lt;/span&gt;:&lt;span class="p"&gt;=your_default_docker_registry&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
: &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DOCKER_USER&lt;/span&gt;:&lt;span class="p"&gt;=your_default_docker_user&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
: &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DOCKER_PASSWORD&lt;/span&gt;:&lt;span class="p"&gt;=your_default_docker_password&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Preflight script for cacher-preflight&lt;/span&gt;
&lt;span class="nv"&gt;working_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;dirname&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;realpath&lt;/span&gt; ./docker-compose.yaml&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;temp_file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$working_dir&lt;/span&gt;&lt;span class="s2"&gt;/docker-compose.caching.yaml"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CACHE_COMPOSE_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$temp_file&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DOCKER_BUILDKIT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Set Up Cacher Script
&lt;/h3&gt;

&lt;p&gt;The cacher script modifies the Docker Compose file to include cache settings for each service.&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="c"&gt;# Copy into cache path, and add caching&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; ./docker-compose.yaml &lt;span class="nv"&gt;$CACHE_COMPOSE_PATH&lt;/span&gt;
&lt;span class="nv"&gt;services&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;yq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.services | keys | .[]'&lt;/span&gt; ./docker-compose.yaml&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;service &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;$services&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;yq &lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;".services.&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;service&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.build.cache_from[0] = &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;type=registry,ref=&lt;/span&gt;&lt;span class="nv"&gt;$DOCKER_IMAGE&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;service&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-buildcache&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nv"&gt;$CACHE_COMPOSE_PATH&lt;/span&gt;
  yq &lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;".services.&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;service&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.build.cache_to[0] = &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;type=registry,ref=&lt;/span&gt;&lt;span class="nv"&gt;$DOCKER_IMAGE&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;service&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-buildcache,mode=max&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nv"&gt;$CACHE_COMPOSE_PATH&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Build and Push Script
&lt;/h3&gt;

&lt;p&gt;Finally, the build script builds and pushes the Docker images, utilizing the caching configurations set up in the previous steps.&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="c"&gt;# Build script for build&lt;/span&gt;
docker buildx create &lt;span class="nt"&gt;--use&lt;/span&gt;

&lt;span class="c"&gt;# After using buildx, you will need to relogin into docker.&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DOCKER_PASSWORD&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | docker login &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DOCKER_USER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--password-stdin&lt;/span&gt; &lt;span class="nv"&gt;$DOCKER_REGISTRY&lt;/span&gt;

docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nv"&gt;$CACHE_COMPOSE_PATH&lt;/span&gt; build
docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nv"&gt;$CACHE_COMPOSE_PATH&lt;/span&gt; push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;With this I was able to speed up compilation in CI/CD greatly by utilizing remote caching. :)&lt;/p&gt;

</description>
      <category>docker</category>
      <category>devops</category>
      <category>learning</category>
      <category>development</category>
    </item>
    <item>
      <title>Sometimes all we need is a good safe word! Even ChatGPT!</title>
      <dc:creator>Michael</dc:creator>
      <pubDate>Sun, 23 Jun 2024 22:27:49 +0000</pubDate>
      <link>https://dev.to/mbround18/sometimes-all-we-need-is-a-good-safe-word-even-chatgpt-2e82</link>
      <guid>https://dev.to/mbround18/sometimes-all-we-need-is-a-good-safe-word-even-chatgpt-2e82</guid>
      <description>&lt;h2&gt;
  
  
  Using Safe Words with ChatGPT to Solve Complex Problems: A Must-Have Technique
&lt;/h2&gt;

&lt;p&gt;When dealing with complex problems, communication clarity is crucial. In my recent experience, I found that using safe words with ChatGPT significantly enhanced my problem-solving process. Let me share how this simple technique can be a game-changer for developers and problem solvers alike.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Concept of Safe Words
&lt;/h3&gt;

&lt;p&gt;Safe words are pre-defined signals used in various contexts to indicate a stop or pause, in the case of AI its to get it to stop responding or talking while you have multiple things you want to explain! &lt;/p&gt;

&lt;h3&gt;
  
  
  My Experience with ChatGPT
&lt;/h3&gt;

&lt;p&gt;In a recent coding project, I was faced with a complex issue involving a { &lt;a href="https://github.com/mbround18/valheim-docker"&gt;Rust-based game server for Valheim&lt;/a&gt;. I needed ChatGPT’s assistance to navigate through multiple steps without losing track of the conversation’s flow or getting overwhelmed by the details. Here’s how I did it:&lt;/p&gt;

&lt;h4&gt;
  
  
  Setting the Rules
&lt;/h4&gt;

&lt;p&gt;I started by defining a clear rule with ChatGPT: I would feed it information, and it would respond with "Ok" until I used the safe word "Pineapple." This ensured that I could provide all necessary details before ChatGPT processed and responded with a solution.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Interaction
&lt;/h4&gt;

&lt;p&gt;Here’s a snapshot of our conversation to illustrate this technique:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;User:&lt;/strong&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I have a complex problem I am trying to solve; I will give you information and you will respond with Ok until I respond with Pineapple. Once I say Pineapple in my prompt you will use all the information I have given you and your knowledge base to come up with a potential solution, do you understand?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;ChatGPT:&lt;/strong&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ok.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;User:&lt;/strong&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I have a UDP and TCP based game server wrapper build in Rust for a game called Valheim.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;ChatGPT:&lt;/strong&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ok.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;User:&lt;/strong&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I need a way to monitor traffic on ports &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"2456:2456/udp"&lt;/li&gt;
&lt;li&gt;"2457:2457/udp"&lt;/li&gt;
&lt;li&gt;"2458:2458/udp"
When it detects no activity it will pause a process by a process name. I have a way to get the process name.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;ChatGPT:&lt;/strong&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ok.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;User:&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;NOTE:&lt;/strong&gt; This was a pretty long output. Truncated for the article. it's just a tree of the src folder in the project. I pasted it directly into the chat with GPT so it could have its context.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Here is my src folder:

src
├── huginn
│   ├── Cargo.toml
│   ├── README.md
│   ├── main.rs
│   └── routes
│       ├── metrics.rs
│       ├── mod.rs
│       └── status.rs
├── odin
│   ├── Cargo.toml
│   ├── README.md
│   ├── build.rs
│   ├── cli.rs
│   ├── commands
│   │   ├── backup.rs
│   │   ├── configure.rs
│   │   ├── install.rs
│   │   ├── install_mod.rs
│   │   ├── logs.rs
│   │   ├── mod.rs
│   │   ├── notify.rs
│   │   ├── start.rs
│   │   ├── status.rs
│   │   ├── stop.rs
│   │   └── update.rs
│   ├── constants.rs
TRUNCATED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;ChatGPT:&lt;/strong&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ok.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;User:&lt;/strong&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;src/odin/server/process.rs has this functionality.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;ChatGPT:&lt;/strong&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ok.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;User:&lt;/strong&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The process is started via this file src/odin/server/startup.rs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;ChatGPT:&lt;/strong&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ok.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;User:&lt;/strong&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pineapple.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;ChatGPT:&lt;/strong&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Given the requirements and the provided code structure, here's a potential solution for monitoring traffic on the specified UDP ports and pausing a process when no activity is detected...&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  The Benefits
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Controlled Flow of Information&lt;/strong&gt;: By using a safe word, I controlled when ChatGPT should start processing the data, ensuring it had all the context needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reduced Overwhelm&lt;/strong&gt;: Breaking down the information into manageable chunks made it easier for both me and ChatGPT to handle complex tasks without missing critical details.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enhanced Focus&lt;/strong&gt;: This method allowed ChatGPT to focus on providing a well-thought-out solution rather than responding prematurely to incomplete information.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Implementing Safe Words in Your Workflow
&lt;/h3&gt;

&lt;p&gt;To incorporate this technique in your workflow, follow these simple steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Define a Safe Word&lt;/strong&gt;: Choose a unique word that you will use to signal ChatGPT to process the information and respond. Ensure it is a word unlikely to appear in your regular communication to avoid accidental triggers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Set the Context&lt;/strong&gt;: Inform ChatGPT at the beginning of your session about the safe word and the process. This helps in aligning the AI's responses to your communication style.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Feed Information Gradually&lt;/strong&gt;: Provide the necessary details step-by-step, confirming each piece of information with a simple "Ok" response from ChatGPT.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use the Safe Word&lt;/strong&gt;: Once you have provided all the required information, use the safe word to signal ChatGPT to start processing and provide a solution.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Now, I will not say this was all daisies. In true GPT fashion it yelled pineapple after a few prompts when it thought it understood everything. It gave me a partial answer which was incorrect, and I had to remind it: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I didn't say pineapple, you did, hold your response until I say pineapple. is that understood?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;However, using safe words with ChatGPT is a powerful technique to solve complex problems effectively. It ensures clear communication, reduces overwhelm, and enhances the quality of the solutions provided by the AI. By implementing this strategy, developers and problem solvers can leverage ChatGPT more efficiently, leading to better outcomes and smoother workflows.&lt;/p&gt;

&lt;p&gt;Try it out in your next complex problem-solving session and experience the difference it makes!&lt;/p&gt;

</description>
      <category>chatgpt</category>
      <category>rust</category>
      <category>devops</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Setting up an Enshrouded Dedicated Server with Docker</title>
      <dc:creator>Michael</dc:creator>
      <pubDate>Sat, 03 Feb 2024 23:50:37 +0000</pubDate>
      <link>https://dev.to/mbround18/setting-up-an-enshrouded-dedicated-server-with-docker-2n1i</link>
      <guid>https://dev.to/mbround18/setting-up-an-enshrouded-dedicated-server-with-docker-2n1i</guid>
      <description>&lt;h2&gt;
  
  
  Sauce
&lt;/h2&gt;

&lt;p&gt;TLDR: &lt;a href="https://github.com/mbround18/enshrouded-docker/blob/main/README.md"&gt;GitHub Repository&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In the realm of gaming, where the digital and the mystical intertwine, setting up a server should not be a task that dampens your spirits. With the advent of Docker, launching an enshrouded server has become as effortless as casting a spell in a world brimming with magic and adventure. This article unveils the arcane secrets to effortlessly deploying your enshrouded server, allowing you to dive into the gameplay without the mundane worries of traditional server setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before You Begin Your Quest
&lt;/h2&gt;

&lt;p&gt;Ensure your toolkit is complete with Docker and Docker Compose installed. These are the wand and spellbook for your journey, essential for summoning your server into existence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Crafting Your Server with Docker Compose
&lt;/h2&gt;

&lt;p&gt;The heart of your server lies within the &lt;code&gt;docker-compose.yml&lt;/code&gt; file—a grimoire where the configurations of your server are inscribed. Here's a snippet to begin conjuring your enshrouded server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;enshrouded&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;mbround18/enshrouded-docker:latest&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
      &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dockerfile&lt;/span&gt;
      &lt;span class="na"&gt;platforms&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;linux/amd64&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;SERVER_NAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;My&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Enshrouded&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Server"&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;15636:15636/udp"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;15636:15636/tcp"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;15637:15637/udp"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;15637:15637/tcp"&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;./data:/home/steam/enshrouded&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this incantation, your server is but a &lt;code&gt;docker-compose up&lt;/code&gt; away from awakening.&lt;/p&gt;

&lt;h3&gt;
  
  
  Beyond the Basic Spell: Custom Configurations
&lt;/h3&gt;

&lt;p&gt;While the initial setup is akin to a basic spell, the true magic lies in customization. Tailor your server's environment variables within the &lt;code&gt;docker-compose.yml&lt;/code&gt; to fit the unique needs of your adventure.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Environment Variable&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Default Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SERVER_NAME&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Name of the server&lt;/td&gt;
&lt;td&gt;"Enshrouded Server"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PASSWORD&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Password for the server&lt;/td&gt;
&lt;td&gt;"" (empty string)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SAVE_DIRECTORY&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Save directory for the game&lt;/td&gt;
&lt;td&gt;"./savegame"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;LOG_DIRECTORY&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Log directory for the server&lt;/td&gt;
&lt;td&gt;"./logs"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SERVER_IP&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;IP address for the server&lt;/td&gt;
&lt;td&gt;"0.0.0.0"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GAME_PORT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Game port for the server&lt;/td&gt;
&lt;td&gt;15636&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;QUERY_PORT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Query port for the server&lt;/td&gt;
&lt;td&gt;15637&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SLOT_COUNT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Number of slots for the server&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Ensuring Your Server Evolves with You
&lt;/h2&gt;

&lt;p&gt;As your quest evolves, so too might your server needs. Updating your server is as simple as adjusting your &lt;code&gt;docker-compose.yml&lt;/code&gt; and restarting the server with a simple down and up command. This ensures your server is always aligned with your latest adventures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Heed the Call for Backup
&lt;/h2&gt;

&lt;p&gt;Before venturing too far into the unknown, heed the wise advice to back up your save files. The realm of Docker and the enshrouded server setup guide offers pathways to integrating auto backups, safeguarding your progress against unforeseen disasters.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/mbround18/enshrouded-docker/blob/main/docs%2Fcompose-with-backups.md"&gt;I highly recommend adding backups, this is an easy method to accomplish that goal.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Joining Forces for the Greater Good
&lt;/h2&gt;

&lt;p&gt;Embark on your journey with the enshrouded server and Docker, and let your gaming adventures be limited only by your imagination. The path is laid out before you; summon your server, customize your realm, and step forth into the adventure that awaits.&lt;/p&gt;

</description>
      <category>enshrouded</category>
      <category>docker</category>
      <category>shell</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Dockerize Your Palworld Server: A Step-by-Step Guide</title>
      <dc:creator>Michael</dc:creator>
      <pubDate>Mon, 22 Jan 2024 07:31:22 +0000</pubDate>
      <link>https://dev.to/mbround18/dockerize-your-palworld-server-a-step-by-step-guide-1d02</link>
      <guid>https://dev.to/mbround18/dockerize-your-palworld-server-a-step-by-step-guide-1d02</guid>
      <description>&lt;h2&gt;
  
  
  Sauce
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/mbround18/palworld-docker"&gt;Checkout the GitHub repo here!&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Are you ready to embark on an adventure in Palworld but dread the tedious server setup? Fear not! In this article, I'll show you how to effortlessly launch your Palworld server using Docker, making your setup process as smooth as sailing the calmest seas 🌊. Whether you're aiming for a casual getaway or a challenging survival experience, this guide is your treasure map 🗺️ to a customized Palworld server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Dockerize Your Palworld Server?
&lt;/h2&gt;

&lt;p&gt;Dockerizing your Palworld server offers several unbeatable advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simplicity&lt;/strong&gt;: Say goodbye to complicated setup processes. With Docker, you can get your server up and running with just a few commands.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistency&lt;/strong&gt;: Docker ensures your server environment is consistent, mitigating the dreaded "it works on my machine" syndrome.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customization&lt;/strong&gt;: Easily switch between different game modes (&lt;code&gt;casual&lt;/code&gt;, &lt;code&gt;normal&lt;/code&gt;, &lt;code&gt;hard&lt;/code&gt;) or fine-tune settings to your heart's content.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before we dive in, make sure you have Docker and Docker Compose installed on your machine. These tools are your Swiss Army knife 🛠️ for managing containerized applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration Options Galore
&lt;/h2&gt;

&lt;p&gt;One of the coolest aspects of dockerizing your Palworld server is the plethora of configuration options at your fingertips. Want to control the speed of time? Adjust the &lt;code&gt;DAY_TIME_SPEED_RATE&lt;/code&gt; and &lt;code&gt;NIGHT_TIME_SPEED_RATE&lt;/code&gt;. Looking to tweak the experience points rate? The &lt;code&gt;EXP_RATE&lt;/code&gt; setting has got you covered.&lt;/p&gt;

&lt;p&gt;And there's more! Customize everything from Pal capture rates to the number of cooperative players allowed. The sky's the limit when it comes to tailoring your Palworld experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's Get Dockerizing!
&lt;/h2&gt;

&lt;p&gt;Here's a simple &lt;code&gt;docker-compose.yml&lt;/code&gt; snippet to start your Palworld server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.8"&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;palworld-server&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;mbround18/palworld-docker:latest&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;PRESET&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;casual"&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;8211:8211"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;27015:27015"&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./data:/home/steam/palworld"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this setup, you're just a &lt;code&gt;docker-compose up&lt;/code&gt; away from your Palworld adventure. Customize the environment variables as you see fit to create your perfect game world.&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom Configuration: Beyond the Presets
&lt;/h3&gt;

&lt;p&gt;While presets are a fantastic way to quickly launch your server, don't forget that you can dive deeper into customization. Modify the &lt;code&gt;docker-compose.yml&lt;/code&gt; to include any specific settings you desire:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;EXP_RATE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.5"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Updating Your Server
&lt;/h2&gt;

&lt;p&gt;To update your server settings, simply adjust your &lt;code&gt;docker-compose.yml&lt;/code&gt; file and restart your server. This flexibility ensures your Palworld server can evolve alongside your adventures.&lt;/p&gt;




&lt;p&gt;Embarking on your Palworld journey has never been easier. With Docker, you're equipped to launch, customize, and manage your server with unprecedented ease. So gather your Pals, set sail for adventure, and remember: in Palworld, your imagination is the only limit! 🚀🌌&lt;/p&gt;

</description>
      <category>docker</category>
      <category>python</category>
      <category>gamedev</category>
      <category>bash</category>
    </item>
    <item>
      <title>The True Price of My Open Source Journey</title>
      <dc:creator>Michael</dc:creator>
      <pubDate>Tue, 21 Nov 2023 19:56:44 +0000</pubDate>
      <link>https://dev.to/mbround18/the-true-price-of-my-open-source-journey-100k</link>
      <guid>https://dev.to/mbround18/the-true-price-of-my-open-source-journey-100k</guid>
      <description>&lt;p&gt;Ever wondered what it costs to be an Open Source Software (OSS) developer? I decided to break down my monthly expenses to give you a glimpse into the financial side of my passion for OSS. While I don't do it for the money, sharing this information might help those considering a similar path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monthly Expenditure Overview
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Tools I Invest In
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;GitHub Pro: $4 USD/month&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Essential for managing numerous repos with added features and higher limits.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;DockerHub Pro: $5 USD/month&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pro features assist in larger projects with vulnerability scanning and image inspections.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Dedicated Servers: $65 USD/month&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Playground for development and hosting production-grade projects, like my &lt;a href="https://github.com/mbround18/valheim-docker"&gt;Valheim project&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;IDE (IntelliJ): $249 USD/year&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unbeatable integrations for efficient development.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Dbeaver: $23 USD/month&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The go-to IDE for databases in my opinion.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Cloud Services (AWS/Azure/Google Cloud/B2 Backblaze): $27 USD/month&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Covers backups, static sites, databases, and more.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Yearly Cost: $1,737 USD&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Cost-Free Tools
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Open Source Tools&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Utilizing free and powerful tools like K8sLens, croc, kubectl, curl, bind-tools (including dig, nc), grep, aria2, terraform, rclone, and many more.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Not Calculated but Still Costs
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Time Investment&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spending an average of 20 hours per week on OSS development.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Living Expenses&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Utilities, housing, and daily sustenance.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Education&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Investing time and money into a Bachelor's and Master's in STEM fields.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Hardware and Technology&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Continuous investment in equipment for development.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why Share This?
&lt;/h2&gt;

&lt;p&gt;While I'm not in it for the money, the true cost of my OSS journey involves much more than what's reflected in these numbers. It's a labor of love, a commitment of time, and a dedication to personal and professional growth. If you're considering the OSS path, remember, the most valuable contributions often go beyond the balance sheet.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>developer</category>
      <category>productivity</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Rapid building with Rust on Windows for WLS2</title>
      <dc:creator>Michael</dc:creator>
      <pubDate>Sun, 08 Oct 2023 05:23:51 +0000</pubDate>
      <link>https://dev.to/mbround18/fast-build-on-windows-for-wls2-9hi</link>
      <guid>https://dev.to/mbround18/fast-build-on-windows-for-wls2-9hi</guid>
      <description>&lt;h2&gt;
  
  
  Fast Build on Windows for WLS2
&lt;/h2&gt;

&lt;p&gt;This is a quick post y'all! less than 2m read!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://markentier.tech/posts/2022/01/speedy-rust-builds-under-wsl2/"&gt;Credit &lt;code&gt;markentier.tech&lt;/code&gt; with their post here!&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;I have been struggling compiling on windows with incremental builds &amp;amp; they take forever. After doing lots of Googling I stumbled across the post from &lt;code&gt;markentier.tech&lt;/code&gt;. After doing some testing my compile times on a &lt;a href="https://github.com/mbround18/valheim-docker"&gt;large project for Valheim&lt;/a&gt; went from 3-5 minutes to 30 seconds. Back to those beautiful compile times like on my Linux dual boot!&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Install &lt;code&gt;make&lt;/code&gt; and &lt;code&gt;rsync&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/mbround18/da7e141f8f75acb40281ac5860a04faf"&gt;Copy the following &lt;code&gt;Makefile&lt;/code&gt; into your repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;make wsl.build&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;This moves your files into a temp directory on your Linux sub-system which allows it to compile directly without the jank of cross system. After compilation it &lt;code&gt;rsyncs&lt;/code&gt; only the outputs needed to your target directory if you are using it docker builds or other.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>windows</category>
      <category>wsl2</category>
      <category>development</category>
    </item>
    <item>
      <title>How to append to GitHub Env via JavaScript Action</title>
      <dc:creator>Michael</dc:creator>
      <pubDate>Sun, 11 Dec 2022 23:02:17 +0000</pubDate>
      <link>https://dev.to/mbround18/how-to-append-to-github-env-via-javascript-action-9nj</link>
      <guid>https://dev.to/mbround18/how-to-append-to-github-env-via-javascript-action-9nj</guid>
      <description>&lt;h2&gt;
  
  
  Prerequsite
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You are creating a JavaScript/TypeScript action for GitHub&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.github.com/en/actions/creating-actions/creating-a-javascript-action"&gt;You already have a repository going. If not follow this tutorial.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Sauce
&lt;/h2&gt;

&lt;h3&gt;
  
  
  DIY
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GITHUB_ENV&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test_var=true&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Core method
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;const core &lt;span class="o"&gt;=&lt;/span&gt; require&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@actions/core'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

core.exportVariable&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"test_var"&lt;/span&gt;, &lt;span class="s2"&gt;"true"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Outcome
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bo3TGVPU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/llplp617w8p2a16riky0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bo3TGVPU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/llplp617w8p2a16riky0.png" alt="Image description" width="375" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This also works for path &amp;amp; step summary :)&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;appendEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GITHUB_ENV&lt;/span&gt;&lt;span class="dl"&gt;"&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="nx"&gt;key&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="nx"&gt;value&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;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;appendPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GITHUB_PATH&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;appendStepSummary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GITHUB_STEP_SUMMARY&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;content&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;



</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>github</category>
    </item>
    <item>
      <title>FoundryVTT - Want a video background on login?</title>
      <dc:creator>Michael</dc:creator>
      <pubDate>Sun, 30 Oct 2022 21:32:46 +0000</pubDate>
      <link>https://dev.to/mbround18/foundryvtt-want-a-video-background-on-login-3khh</link>
      <guid>https://dev.to/mbround18/foundryvtt-want-a-video-background-on-login-3khh</guid>
      <description>&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;It is suggested that you have a way to inject scripts into your foundry instance. I have a tutorial on this via &lt;a href="https://dev.to/mbround18/how-to-hijack-your-head-38dn"&gt;"How to Hijack your head (HTML head tag)" which uses Cloudflare&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Simplified
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open Cloudflare or the method of script injection.&lt;/li&gt;
&lt;li&gt;Add the following injection:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script
  &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://gist.githubusercontent.com/mbround18/e4853df98392eb8569a4fd4042723859/raw/1dcd190a521e35786a43dcce806a588ad0bb2bea/video-background.js"&lt;/span&gt;
  &lt;span class="na"&gt;async&lt;/span&gt;
  &lt;span class="na"&gt;defer&lt;/span&gt;
  &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt;
  &lt;span class="na"&gt;crossorigin=&lt;/span&gt;&lt;span class="s"&gt;"anonymous"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2.1. If you are using the Cloudflare method of injecting it would be something like this:&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ElementHandler&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s2"&gt;`&amp;lt;script src="https://gist.githubusercontent.com/mbround18/e4853df98392eb8569a4fd4042723859/raw/1dcd190a521e35786a43dcce806a588ad0bb2bea/video-background.js" async defer type="text/javascript" crossorigin="anonymous"&amp;gt;&amp;lt;/script&amp;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;html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;injected&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  DIY
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1)&lt;/strong&gt; Head on over to GitHub, if you dont have an account I suggest creating one.&lt;br&gt;
&lt;strong&gt;2)&lt;/strong&gt; Click the plus icon in the upper right-hand corner.&lt;br&gt;
&lt;strong&gt;3)&lt;/strong&gt; Click new Gist&lt;br&gt;
&lt;strong&gt;4)&lt;/strong&gt; Give your gist a title.&lt;br&gt;
&lt;strong&gt;5)&lt;/strong&gt; Create a function:&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;videoBackground&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Next bit of code goes here!&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;videoBackground&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;6)&lt;/strong&gt; Lets first parse out the extension, we will be using a video &amp;amp; source elements which need a type&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;body&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// This bit gives us the body&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;background&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;backgroundImage&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;url("&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;")&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// This parses out the background image.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;7)&lt;/strong&gt; Now with the background accessible and parsed out, lets grab the file extension:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;background&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&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;extension&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&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;8)&lt;/strong&gt; With the extension on hand we need to parse out the type of file it is:&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;extension&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;avi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;video/avi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ogv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;video/ogg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mp4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;video/mp4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;9)&lt;/strong&gt; The bit of code above should give us a few options for video backgrounds.&lt;br&gt;
&lt;strong&gt;10)&lt;/strong&gt; Now, lets append our video background to the body:&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;videoBackground&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#video-background&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// This bit cheks for the element.&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;videoBackground&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// If not exist we create it.&lt;/span&gt;
    &lt;span class="nx"&gt;videoBackground&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;video&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;videoBackground&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;video-background&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;videoBackground&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;autoplay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;videoBackground&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;muted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Turn this to false if you want the audio.&lt;/span&gt;
    &lt;span class="nx"&gt;videoBackground&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;videoBackground&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Append it to the body.&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#video-background source&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Check for the background source.&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;source&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;videoBackground&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Apend source element.&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;background&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Set background&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Set type&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;11)&lt;/strong&gt; &lt;a href="https://gist.github.com/mbround18/e4853df98392eb8569a4fd4042723859"&gt;In the end, it should look a little something like this&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;12)&lt;/strong&gt; Now inject the script using the raw button to get a direct link to the file!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script
  &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"Your link here."&lt;/span&gt;
  &lt;span class="na"&gt;async&lt;/span&gt;
  &lt;span class="na"&gt;defer&lt;/span&gt;
  &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt;
  &lt;span class="na"&gt;crossorigin=&lt;/span&gt;&lt;span class="s"&gt;"anonymous"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>foundryvtt</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Rust &amp; Cross-compiling from Linux to Mac on GitHub Actions</title>
      <dc:creator>Michael</dc:creator>
      <pubDate>Tue, 09 Aug 2022 21:52:12 +0000</pubDate>
      <link>https://dev.to/mbround18/rust-cross-compiling-from-linux-to-mac-on-github-actions-2mj8</link>
      <guid>https://dev.to/mbround18/rust-cross-compiling-from-linux-to-mac-on-github-actions-2mj8</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;So you have a binary that you wish to distribute but you are only able to compile for Windows and Linux at the moment. You have spent hours if not days googling for the appropriate way to cross-compile from Linux to Mac... Well, I am here to tell you I have been there and now provide an easy solution!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Sauce
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Basic Usage
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Setup Rust, use the x86_64-apple-darwin target but the rest can be customized.&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ATiltedTree/setup-rust@v1&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;x86_64-apple-darwin&lt;/span&gt;
    &lt;span class="na"&gt;rust-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nightly&lt;/span&gt; &lt;span class="c1"&gt;# Works both with 'stable' and 'nightly'&lt;/span&gt;

&lt;span class="c1"&gt;# Use the v1 of this action&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mbround18/setup-osxcross@v1&lt;/span&gt;
  &lt;span class="c1"&gt;# This builds executables &amp;amp; sets env variables for rust to consume.&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;osx-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;12.3"&lt;/span&gt;

&lt;span class="c1"&gt;# Checkout your code&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Clone your Code&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;

&lt;span class="c1"&gt;# Build your code for apple-darwin based release&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build Your Code&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cargo build --release --target x86_64-apple-darwin&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation of its Functionality
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;It creates a folder called &lt;code&gt;osxcross&lt;/code&gt; in the github actions working directory. (to avoid interference with any files you might be operating with)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/tpoechtrager/osxcross"&gt;Clones the &lt;code&gt;osxcross&lt;/code&gt; repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/joseluisq/macosx-sdks"&gt;It downloads the SDK matching the version you specified from @joseluisq/macosx-sdks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Checks cache&lt;/li&gt;
&lt;li&gt;Builds if cache wasn't hit&lt;/li&gt;
&lt;li&gt;Sets environment variables for build target &lt;code&gt;x86_64-apple-darwin&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Shoutouts &amp;amp; Thanks yous
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://wapl.es/rust/2019/02/17/rust-cross-compile-linux-to-macos.html"&gt;Thank you James Waples for writing the cross compilation article&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/tpoechtrager/osxcross"&gt;Thank you osxcross for creating the path forward&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/joseluisq/macosx-sdks"&gt;Thank you joseluisq for packaging the SDKs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rust</category>
      <category>linux</category>
      <category>programming</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
