<?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: Kareem Al-Farsi</title>
    <description>The latest articles on DEV Community by Kareem Al-Farsi (@kareem_harimexj_5efa2258e).</description>
    <link>https://dev.to/kareem_harimexj_5efa2258e</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%2F3866346%2F307c5058-3746-4fc4-b22e-284b9c6bc765.png</url>
      <title>DEV Community: Kareem Al-Farsi</title>
      <link>https://dev.to/kareem_harimexj_5efa2258e</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kareem_harimexj_5efa2258e"/>
    <language>en</language>
    <item>
      <title>How to show weather on your personal website in 3 lines of JavaScript (no API key needed)</title>
      <dc:creator>Kareem Al-Farsi</dc:creator>
      <pubDate>Thu, 28 May 2026 15:31:24 +0000</pubDate>
      <link>https://dev.to/kareem_harimexj_5efa2258e/how-to-show-weather-on-your-personal-website-in-3-lines-of-javascript-no-api-key-needed-4lb6</link>
      <guid>https://dev.to/kareem_harimexj_5efa2258e/how-to-show-weather-on-your-personal-website-in-3-lines-of-javascript-no-api-key-needed-4lb6</guid>
      <description>&lt;p&gt;I got tired of explaining to people why their "simple weather widget" needed an API key, a signup form, and a credit card.&lt;/p&gt;

&lt;p&gt;So I built a weather API that doesn't need any of that.&lt;/p&gt;

&lt;p&gt;Here's how you can add live weather to your personal website, portfolio, or side project in about 60 seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  The old way (painful)
&lt;/h2&gt;

&lt;p&gt;Most weather APIs make you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create an account&lt;/li&gt;
&lt;li&gt;Verify your email&lt;/li&gt;
&lt;li&gt;Generate an API key&lt;/li&gt;
&lt;li&gt;Paste that key into your code&lt;/li&gt;
&lt;li&gt;Worry about rate limits&lt;/li&gt;
&lt;li&gt;Get an email when your "free tier" expires&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a weather widget on a personal site? That's overkill.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Nimbus way (one fetch, done)
&lt;/h2&gt;

&lt;p&gt;I made a public API that doesn't need keys. Just call it.&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="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://nimbus-api-gxuc.onrender.com/api/v1/weather?city=Berlin&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;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&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="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. No headers. No tokens. No signup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real example: Put it on your site
&lt;/h2&gt;

&lt;p&gt;Here's a working snippet you can drop into any HTML page right now:&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;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"weather-widget"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Loading weather...&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://nimbus-api-gxuc.onrender.com/api/v1/weather?city=Berlin&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;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;weatherHtml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;temp_celsius&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;°C • &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;br&amp;gt;Wind: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;wind_speed_kmh&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; km/h • Humidity: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;humidity_percent&lt;/span&gt; &lt;span class="o"&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="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;weather-widget&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;/strong&amp;gt;&amp;lt;br&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;weatherHtml&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;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&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;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;weather-widget&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;p&amp;gt;Weather not available right now&amp;lt;/p&amp;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="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change &lt;code&gt;Berlin&lt;/code&gt; to any city. It works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why did I build this?
&lt;/h2&gt;

&lt;p&gt;Because I got tired of closed source APIs that change their pricing every 6 months.&lt;/p&gt;

&lt;p&gt;Nimbus is open source. The code is on GitHub. You can read it, fork it, or run your own version if you don't trust me. The API is free because hosting a weather endpoint costs me almost nothing, and I'd rather lose money than put up a paywall.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it right now
&lt;/h2&gt;

&lt;p&gt;Open 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;curl https://nimbus-api-gxuc.onrender.com/api/v1/weather?city&lt;span class="o"&gt;=&lt;/span&gt;London
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No API key. No signup. Just weather.&lt;/p&gt;




&lt;p&gt;P.S. The geocoding API is coming soon. If you want to convert city names to coordinates without another API key, watch the repo.&lt;/p&gt;

</description>
      <category>api</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Building Hyperonix: A Minimalist Research Archive for the Modern Scholar</title>
      <dc:creator>Kareem Al-Farsi</dc:creator>
      <pubDate>Sat, 11 Apr 2026 12:04:25 +0000</pubDate>
      <link>https://dev.to/kareem_harimexj_5efa2258e/building-hyperonix-a-minimalist-research-archive-for-the-modern-scholar-54fd</link>
      <guid>https://dev.to/kareem_harimexj_5efa2258e/building-hyperonix-a-minimalist-research-archive-for-the-modern-scholar-54fd</guid>
      <description>&lt;h1&gt;
  
  
  Building Hyperonix: A Minimalist Research Archive for the Modern Scholar 📜
&lt;/h1&gt;

&lt;p&gt;In an era of information overload, we don't just need more search results—we need &lt;strong&gt;synthesis&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Today, I’m excited to showcase &lt;strong&gt;Hyperonix&lt;/strong&gt;, a high-fidelity research interface designed to turn the chaos of the web into a structured, editorial experience. Built with a focus on speed, precision, and an academic aesthetic, Hyperonix is more than a search engine; it's a digital journal for your inquiries.&lt;/p&gt;

&lt;h2&gt;
  
  
  🏛️ The Vision: Digital Minimalism meets AI Intelligence
&lt;/h2&gt;

&lt;p&gt;The goal for Hyperonix was simple: create a search tool that feels like reading a prestige journal. While most AI tools focus on "chatting," Hyperonix focuses on &lt;strong&gt;archiving&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;We moved away from the typical "neon-dark-mode" tech aesthetic and embraced an editorial, print-inspired design. Think high-contrast typography, muted archive tones, and a layout that breathes.&lt;/p&gt;

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

&lt;p&gt;To achieve real-time synthesis without the lag, we leveraged a modern, high-performance stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt;: &lt;a href="https://react.dev/" rel="noopener noreferrer"&gt;React 19&lt;/a&gt; + &lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;Vite&lt;/a&gt; for an ultra-fast developer experience and lean production builds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Styling&lt;/strong&gt;: &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind CSS v4&lt;/a&gt; for a cutting-edge, future-proof CSS architecture.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Intelligence&lt;/strong&gt;: &lt;a href="https://groq.com/" rel="noopener noreferrer"&gt;Groq SDK&lt;/a&gt; (running &lt;strong&gt;Llama 3.3 70B&lt;/strong&gt;) for near-instant response generation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Search Engine&lt;/strong&gt;: &lt;a href="https://tavily.com/" rel="noopener noreferrer"&gt;Tavily API&lt;/a&gt; for optimized research-grade web results.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistence&lt;/strong&gt;: &lt;a href="https://firebase.google.com/" rel="noopener noreferrer"&gt;Firebase&lt;/a&gt; for seamless Google Authentication and session management.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment&lt;/strong&gt;: &lt;a href="https://render.com/" rel="noopener noreferrer"&gt;Render&lt;/a&gt; for streamlined CI/CD and hosting.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔬 Core Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Real-Time intelligence Synthesis
&lt;/h3&gt;

&lt;p&gt;Hyperonix doesn't just give you links. It scans the top results, extracts the most relevant data nodes, and synthesizes them into a structured report with full citations.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Deep Research Protocol
&lt;/h3&gt;

&lt;p&gt;For complex queries, the &lt;strong&gt;Deep Research&lt;/strong&gt; mode allows for multi-step scanning, ensuring you get the full context of a topic, from quantum computing breakthroughs to commercial space logistics.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The Scholar Interface
&lt;/h3&gt;

&lt;p&gt;The UI is built to be "invisible." The focus is entirely on the text, with smooth transitions and a responsive sidebar that keeps your research archive organized and accessible.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Deployment in Seconds
&lt;/h2&gt;

&lt;p&gt;One of the project's highlights is its deployment workflow. Using &lt;strong&gt;Render Blueprints&lt;/strong&gt; (&lt;code&gt;render.yaml&lt;/code&gt;), you can go from local code to a global production URL in minutes. It handles the build environment, static publishing, and environment variable management out of the box.&lt;/p&gt;

&lt;h2&gt;
  
  
  🌍 Open for Synthesis
&lt;/h2&gt;

&lt;p&gt;Hyperonix is built for the curious. Whether you're a developer looking for a reference implementation of Groq and Tavily, or a researcher looking for a cleaner way to scan the web, the project is ready for you.&lt;/p&gt;

&lt;p&gt;Check it out live: &lt;a href="https://hyperonixsearch.onrender.com/" rel="noopener noreferrer"&gt;hyperonixsearch.onrender.com&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  What's next?
&lt;/h3&gt;

&lt;p&gt;I'm looking into adding PDF export for research reports and multi-user collaborative journals. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;What would you use a minimalist research archive for? Let me know in the comments!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>website</category>
      <category>typescript</category>
      <category>ai</category>
    </item>
    <item>
      <title>Building Photon: A Hybrid Ray Tracer That Builds for Windows, Linux, and macOS</title>
      <dc:creator>Kareem Al-Farsi</dc:creator>
      <pubDate>Tue, 07 Apr 2026 19:02:25 +0000</pubDate>
      <link>https://dev.to/kareem_harimexj_5efa2258e/building-photon-a-hybrid-ray-tracer-that-builds-for-windows-linux-and-macos-12nn</link>
      <guid>https://dev.to/kareem_harimexj_5efa2258e/building-photon-a-hybrid-ray-tracer-that-builds-for-windows-linux-and-macos-12nn</guid>
      <description>&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://github.com/GordonFreeman21/photon/tree/main" rel="noopener noreferrer"&gt;Photon on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Photon is a C-based adaptive hybrid ray tracer built to explore real-time rendering techniques without locking the project to one platform. The goal was simple: make a renderer that can grow into something serious, while still being practical to build, test, and ship across Windows, Linux, and macOS.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Photon is
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/GordonFreeman21/photon/tree/main" rel="noopener noreferrer"&gt;Photon&lt;/a&gt; is a modular ray tracing engine written in C17. It combines several rendering ideas into one pipeline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;BVH-based ray traversal&lt;/li&gt;
&lt;li&gt;hybrid raster + ray tracing structure&lt;/li&gt;
&lt;li&gt;denoising passes&lt;/li&gt;
&lt;li&gt;probe-based indirect lighting&lt;/li&gt;
&lt;li&gt;adaptive ray budgeting&lt;/li&gt;
&lt;li&gt;build-time shader compilation support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The project is designed to run in a stub mode when full GPU dependencies are missing, which makes it easier to develop and test even on machines without a full Vulkan setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I built it this way
&lt;/h2&gt;

&lt;p&gt;I wanted a renderer that was more than a demo or a single-file experiment. &lt;a href="https://github.com/GordonFreeman21/photon/tree/main" rel="noopener noreferrer"&gt;Photon&lt;/a&gt; is organized like an actual engine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;include/&lt;/code&gt; holds the core types and API&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/&lt;/code&gt; contains the implementation&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;shaders/&lt;/code&gt; contains the compute and graphics shaders&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.github/workflows/&lt;/code&gt; handles CI and releases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That structure makes it easier to extend later, whether that means better materials, real Vulkan integration, texture loading, or more advanced global illumination.&lt;/p&gt;

&lt;h2&gt;
  
  
  What makes it different
&lt;/h2&gt;

&lt;p&gt;A few things stand out in Photon:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Adaptive rendering
&lt;/h3&gt;

&lt;p&gt;Instead of firing a fixed amount of rays every frame, Photon uses a budget system that can adjust quality depending on performance needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Hybrid pipeline
&lt;/h3&gt;

&lt;p&gt;The renderer is built to combine rasterization and ray tracing ideas instead of relying on one approach only. That gives more flexibility for future features.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Denoising
&lt;/h3&gt;

&lt;p&gt;Rendering noisy paths is normal in ray tracing, so Photon includes denoise stages like temporal and spatial filtering to make the output more stable.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Cross-platform release workflow
&lt;/h3&gt;

&lt;p&gt;One of the biggest goals was not just "build on my machine," but "build everywhere." The workflow now produces packaged releases for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Windows: &lt;code&gt;.exe&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Ubuntu/Debian: &lt;code&gt;.deb&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Fedora: &lt;code&gt;.rpm&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Arch Linux: &lt;code&gt;.tar.gz&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of them are collected into one GitHub release.&lt;/p&gt;

&lt;h2&gt;
  
  
  The hard part
&lt;/h2&gt;

&lt;p&gt;The renderer itself was not the only challenge. A lot of the work went into making the project reliable on CI and different systems.&lt;/p&gt;

&lt;p&gt;Some of the issues I hit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Apple Silicon macOS runners do not support x86 SIMD headers like &lt;code&gt;immintrin.h&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;RPM packaging needed the binary path fixed so the installer could find the built executable&lt;/li&gt;
&lt;li&gt;GitHub Actions artifact actions had deprecated versions that broke builds&lt;/li&gt;
&lt;li&gt;Release creation needed proper permissions in workflow settings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those were not just build issues - they shaped how the project had to be structured.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;A few useful lessons came out of this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Portability matters early, not later&lt;/li&gt;
&lt;li&gt;CI breaks fast when platform assumptions are too narrow&lt;/li&gt;
&lt;li&gt;Packaging is part of the product&lt;/li&gt;
&lt;li&gt;A renderer is more than graphics code - it's build scripts, release automation, and platform support too&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is next
&lt;/h2&gt;

&lt;p&gt;Photon still has room to grow. The next steps are likely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;real Vulkan backend integration&lt;/li&gt;
&lt;li&gt;better material and texture support&lt;/li&gt;
&lt;li&gt;improved scene loading&lt;/li&gt;
&lt;li&gt;more accurate indirect lighting&lt;/li&gt;
&lt;li&gt;cleaner packaging for Linux distributions&lt;/li&gt;
&lt;li&gt;more sample scenes and validation tests&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/GordonFreeman21/photon/tree/main" rel="noopener noreferrer"&gt;Photon&lt;/a&gt; started as a ray tracer project, but it became a full cross-platform rendering pipeline with CI, release packaging, and platform-specific build support. That made it much more than "just code" - it became a small engine that can actually be built, shipped, and iterated on.&lt;/p&gt;

&lt;p&gt;If you're into rendering, engine architecture, or cross-platform build systems, Photon is a good example of how quickly those worlds overlap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Explore the repo:&lt;/strong&gt; &lt;a href="https://github.com/GordonFreeman21/photon/tree/main" rel="noopener noreferrer"&gt;https://github.com/GordonFreeman21/photon/tree/main&lt;/a&gt;&lt;/p&gt;

</description>
      <category>raytracing</category>
      <category>c</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
