<?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: Matt Miller</title>
    <description>The latest articles on DEV Community by Matt Miller (@matemiller).</description>
    <link>https://dev.to/matemiller</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%2F435309%2F24c157d3-2f9b-4b8d-9790-7744bcb25166.jpeg</url>
      <title>DEV Community: Matt Miller</title>
      <link>https://dev.to/matemiller</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/matemiller"/>
    <language>en</language>
    <item>
      <title>Remix Mini PC: Moving the Whole Operating System Onto the eMMC</title>
      <dc:creator>Matt Miller</dc:creator>
      <pubDate>Sun, 24 May 2026 20:42:49 +0000</pubDate>
      <link>https://dev.to/matemiller/remix-mini-pc-moving-the-whole-operating-system-onto-the-emmc-h3h</link>
      <guid>https://dev.to/matemiller/remix-mini-pc-moving-the-whole-operating-system-onto-the-emmc-h3h</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/r4nd3l/remix_mini_pc_revival_recipe" rel="noopener noreferrer"&gt;Source files: GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The previous post ended with a working cold boot. Plug in power, the BROM loads our TOC0 SPL from sector 16 of the SD card, our U-Boot runs, Armbian comes up to a login prompt. No laptop, no FEL, no manual intervention.&lt;/p&gt;

&lt;p&gt;There was just one cosmetic issue. The SD card was still required.&lt;/p&gt;

&lt;p&gt;If you pulled it out, the device fell straight to FEL because the BROM had nothing else to boot. That's not actually a problem in most usage, but it bothered me. The whole point of internal storage is that you don't need external media. A 16 GB eMMC is sitting right there on the mainboard, untouched since the project began, except for the small TOC0 SPL I had written to its boot partition during placement experiments and which the BROM had never accepted.&lt;/p&gt;

&lt;p&gt;So: one more push. Move everything onto the eMMC, eject the SD card forever.&lt;/p&gt;

&lt;h2&gt;
  
  
  The unknown that wasn't
&lt;/h2&gt;

&lt;p&gt;I had spent a long evening earlier in the project writing TOC0 SPLs to the eMMC's &lt;strong&gt;boot partition&lt;/strong&gt; (&lt;code&gt;/dev/mmcblk2boot0&lt;/code&gt;) at offset 0 and offset 0x2000, both with the same result every time: BROM silent, no SPL banner, device falls to FEL. I had concluded from this that "the eMMC boot partition is not the right place" — but I had never finished the obvious next experiment. I had never written a TOC0 SPL to the &lt;strong&gt;user area&lt;/strong&gt; at sector 16, which is the exact offset that works on SD.&lt;/p&gt;

&lt;p&gt;It is embarrassing how easy this was to test. From inside Armbian (booted from the SD as usual), with the boot partition's read-only flag still in its default state (we don't even need to unlock it because the user area is fully writable):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo dd &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;~/uboot-build/u-boot/u-boot-sunxi-with-spl.bin &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/mmcblk2 &lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;512 &lt;span class="nv"&gt;seek&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;16 &lt;span class="nv"&gt;conv&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;fsync
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Power off. Pull the SD out. Plug power back in. Watch the UART.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;U-Boot SPL 2026.07-rc2-g744cf5d4e398-dirty
DRAM: 2048 MiB
Trying to boot from MMC2
NOTICE:  BL31: ...
NOTICE:  BL31: Found U-Boot DTB at 0x20ad278, model: Remix Mini PC
&lt;/span&gt;&lt;span class="c"&gt;...
&lt;/span&gt;&lt;span class="gp"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The BROM had just loaded our TOC0 SPL from the eMMC user area at sector 16, same offset as SD. The whole "the eMMC boot partition is the special boot device" mental model was wrong. Allwinner BROM on this device treats the eMMC user area and the SD card the same way — it scans them for a TOC0 signature at sector 16 and runs whatever it finds. The boot partitions are a separate eMMC feature the BROM does not use here.&lt;/p&gt;

&lt;p&gt;The U-Boot prompt at the end is just because there is no Linux rootfs on the eMMC yet, so U-Boot has nothing to chain to. But the hard part — getting BROM to accept eMMC — was over the moment I tried the right offset.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rootfs migration
&lt;/h2&gt;

&lt;p&gt;Once the eMMC was a usable boot device, the remaining work was straightforward Linux administration. Create a partition on the eMMC user area starting at 16 MiB (well clear of the SPL at sector 16), format it ext4, rsync the SD's contents over, fix up the bootloader config to point at the new UUID.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;parted &lt;span class="nt"&gt;-s&lt;/span&gt; /dev/mmcblk2 mklabel msdos
&lt;span class="nb"&gt;sudo &lt;/span&gt;parted &lt;span class="nt"&gt;-s&lt;/span&gt; /dev/mmcblk2 mkpart primary ext4 16MiB 100%
&lt;span class="nb"&gt;sudo &lt;/span&gt;partprobe /dev/mmcblk2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then immediately I learned something I had not known about &lt;code&gt;parted&lt;/code&gt;. After running &lt;code&gt;mklabel msdos&lt;/code&gt;, my TOC0 SPL at sector 16 was gone:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo dd &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/mmcblk2 &lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;512 &lt;span class="nv"&gt;skip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;16 &lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 | hexdump &lt;span class="nt"&gt;-C&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;
&lt;span class="go"&gt;00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Zeros. &lt;code&gt;parted&lt;/code&gt; does not just write the 512-byte MBR at sector 0; it zeros some configurable amount of leading sectors to scrub residual filesystem signatures and old SPL data. The exact size depends on parted's version and the device, but on my install it was at least 8 KiB — which is exactly where my SPL lived.&lt;/p&gt;

&lt;p&gt;This was completely recoverable — the SPL file was still on disk, one &lt;code&gt;dd&lt;/code&gt; puts it back at sector 16 — but it's a real gotcha for anyone doing this in the same order I did. The right ordering is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create the partition table &lt;strong&gt;first&lt;/strong&gt; with parted.&lt;/li&gt;
&lt;li&gt;Then write the SPL at sector 16.&lt;/li&gt;
&lt;li&gt;The partition itself starts at sector 32768, so nothing else touches sector 16 again.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After restoring the SPL and verifying, &lt;code&gt;mkfs.ext4 -L armbi_emmc /dev/mmcblk2p1&lt;/code&gt; formats the partition cleanly without touching the bootloader region. &lt;code&gt;rsync -aHAXx / /mnt/emmc/&lt;/code&gt; copies the current SD rootfs over while running on top of it. About 89,000 files and 2.1 GB. Nine minutes at SD-card-speed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The variable substitution trap
&lt;/h2&gt;

&lt;p&gt;Inside the eMMC copy, two files needed editing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/etc/fstab&lt;/code&gt; — the kernel needs to know which device to mount as root.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/boot/armbianEnv.txt&lt;/code&gt; — the U-Boot boot script reads this to pass the &lt;code&gt;root=&lt;/code&gt; parameter to the kernel.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both currently referenced the SD card's UUID. They needed to reference the eMMC partition's UUID instead. Easy substitution, four shell commands:&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="nv"&gt;SD_UUID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;blkid &lt;span class="nt"&gt;-s&lt;/span&gt; UUID &lt;span class="nt"&gt;-o&lt;/span&gt; value /dev/mmcblk0p1&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;EMMC_UUID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;blkid &lt;span class="nt"&gt;-s&lt;/span&gt; UUID &lt;span class="nt"&gt;-o&lt;/span&gt; value /dev/mmcblk2p1&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;sudo sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"s|&lt;/span&gt;&lt;span class="nv"&gt;$SD_UUID&lt;/span&gt;&lt;span class="s2"&gt;|&lt;/span&gt;&lt;span class="nv"&gt;$EMMC_UUID&lt;/span&gt;&lt;span class="s2"&gt;|g"&lt;/span&gt; /mnt/emmc/etc/fstab
&lt;span class="nb"&gt;sudo sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"s|&lt;/span&gt;&lt;span class="nv"&gt;$SD_UUID&lt;/span&gt;&lt;span class="s2"&gt;|&lt;/span&gt;&lt;span class="nv"&gt;$EMMC_UUID&lt;/span&gt;&lt;span class="s2"&gt;|g"&lt;/span&gt; /mnt/emmc/boot/armbianEnv.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I ran the first command. I skipped the second by accident — possibly the multi-line paste cut off, possibly I just didn't notice it. The third and fourth commands ran with &lt;code&gt;$EMMC_UUID&lt;/code&gt; set to an empty string, and &lt;code&gt;sed&lt;/code&gt; happily did exactly what I told it to: replace the SD UUID with nothing. The result was a fstab that read:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;UUID&lt;/span&gt;= / &lt;span class="n"&gt;ext4&lt;/span&gt; &lt;span class="n"&gt;defaults&lt;/span&gt;,&lt;span class="n"&gt;noatime&lt;/span&gt;,...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and an &lt;code&gt;armbianEnv.txt&lt;/code&gt; that read &lt;code&gt;rootdev=UUID=&lt;/code&gt;. The eMMC rootfs would have failed to mount on boot in a way that would have been hard to debug at three in the morning.&lt;/p&gt;

&lt;p&gt;The verify step — printing both files after the substitution — is what caught it. I noticed the UUID column was suddenly empty, looked at the variables, found &lt;code&gt;$EMMC_UUID&lt;/code&gt; was unset, set it explicitly, ran a targeted sed to put the right UUID back. Twenty seconds of fix work because of a verify step that took ten seconds. Always print before and after.&lt;/p&gt;

&lt;h2&gt;
  
  
  The final test
&lt;/h2&gt;

&lt;p&gt;After fixing fstab and armbianEnv, unmounting cleanly, and writing one last &lt;code&gt;sync&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="nb"&gt;sudo &lt;/span&gt;poweroff
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unplug power. Pull SD card out (critical — the BROM tries SD first, and if it finds the SD's TOC0 SPL it'll boot from there regardless of whether the eMMC also has one). Plug power back in.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;U-Boot SPL 2026.07-rc2-g744cf5d4e398-dirty
DRAM: 2048 MiB
Trying to boot from MMC2                          ← eMMC, not SD
NOTICE:  BL31: ...
NOTICE:  BL31: Found U-Boot DTB at 0x20ad278, model: Remix Mini PC

U-Boot 2026.07-rc2 Allwinner Technology
CPU:   Allwinner A64 (SUN50I)
Model: Remix Mini PC
DRAM:  2 GiB
&lt;/span&gt;&lt;span class="c"&gt;...
&lt;/span&gt;&lt;span class="go"&gt;MMC: no card present                              ← SD physically removed
&lt;/span&gt;&lt;span class="c"&gt;...
&lt;/span&gt;&lt;span class="gp"&gt;switch to partitions #&lt;/span&gt;0, OK
&lt;span class="go"&gt;mmc1(part 0) is current device
Scanning mmc 1:1...                               ← eMMC partition 1
Found U-Boot script /boot/boot.scr
&lt;/span&gt;&lt;span class="c"&gt;...
&lt;/span&gt;&lt;span class="go"&gt;Starting kernel ...

Armbian 24.11.1 Bookworm ttyS0

pine64 login:

 v24.11.1 for Pine64 running Armbian Linux 6.6.62-current-sunxi64
 Usage of /:  17% of 15G                          ← root mounted from eMMC
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Full Armbian login. No SD card in the device. No laptop attached. The Remix Mini PC is now genuinely autonomous: plug in power, after about twenty seconds it is running Linux, ready to be SSH'd into or used directly through HDMI and a USB keyboard.&lt;/p&gt;

&lt;p&gt;The boot trace is worth comparing to the previous post's. Same SPL build, same BL31, same U-Boot, same kernel, same rootfs — but the source has shifted from "SD card sector 16" to "eMMC user area sector 16." The SD card is no longer required for any part of the chain.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this finishes
&lt;/h2&gt;

&lt;p&gt;The original project goal — turn the device into something that boots its own operating system from its own internal storage without a host PC — is done. There is a small list of polish items left (the wired Ethernet is still off, the kernel-side device tree is still a patched BananaPi-M64 rather than a true Remix DTS, the eMMC could be using its boot partition more cleverly) but nothing on that list is blocking. The machine works.&lt;/p&gt;

&lt;p&gt;The SD card, freshly imaged and gzip-backed-up at 893 MB, goes into a drawer as a recovery boot media. The two Remix Mini PCs on my desk — one with eMMC, one without — are both functional Linux SBCs as of this evening.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons that I'd put on a sticky note
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Test the obvious-but-untested case before getting deep into the non-obvious ones.&lt;/strong&gt; Writing TOC0 to the eMMC user area at sector 16 — the same offset that works on SD — was the simplest possible experiment, and I never ran it until very late in the project. Hours of "the boot partition won't accept TOC0" investigation could have been compressed into one &lt;code&gt;dd&lt;/code&gt; command.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;parted mklabel&lt;/code&gt; zeros more than just the MBR.&lt;/strong&gt; If you have anything in the first few kilobytes of a disk that you want to keep, write it &lt;em&gt;after&lt;/em&gt; you create the partition table.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Empty shell variables make sed eat data.&lt;/strong&gt; &lt;code&gt;sed 's|X|$Y|g'&lt;/code&gt; with &lt;code&gt;$Y&lt;/code&gt; unset does not error; it silently substitutes X with nothing. Always echo your variables before passing them to sed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Verify steps are not optional.&lt;/strong&gt; Every single bug in this project was caught by either a UART log or a "print the file after editing" command. Every single one was lost time when those verifies were skipped.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Three years between buying the device and getting it to boot on its own. About twenty seconds between power-on and login prompt now. That's the trade I would make again.&lt;/p&gt;




&lt;p&gt;Enjoying the content? If you'd like to support my work and keep the ideas flowing, consider buying me a coffee! Your support means the world to me!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/devcornercrew" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" height="41" width="174"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>pc</category>
      <category>arm</category>
      <category>debian</category>
      <category>android</category>
    </item>
    <item>
      <title>Remix Mini PC: The Same SD Card Boots the No-NAND Variant Too</title>
      <dc:creator>Matt Miller</dc:creator>
      <pubDate>Sun, 24 May 2026 20:39:54 +0000</pubDate>
      <link>https://dev.to/matemiller/remix-mini-pc-the-same-sd-card-boots-the-no-nand-variant-too-4p0h</link>
      <guid>https://dev.to/matemiller/remix-mini-pc-the-same-sd-card-boots-the-no-nand-variant-too-4p0h</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/r4nd3l/remix_mini_pc_revival_recipe" rel="noopener noreferrer"&gt;Source files: GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A short coda to the last three posts.&lt;/p&gt;

&lt;p&gt;I have a second Remix Mini PC on my desk. It looks identical to the first one — same case, same back panel, same ports — except the previous owner had removed the eMMC chip from the mainboard. No internal storage at all. For years I had assumed it was a separate problem to solve, that one day I would need to find a different recipe for the no-NAND variant.&lt;/p&gt;

&lt;p&gt;After getting the first unit cold-booting from an SD card, I wondered: how much of the work is actually unit-specific, and how much is just "this is what an Allwinner H64 with secure boot wants"? The honest answer is, you cannot tell without trying.&lt;/p&gt;

&lt;p&gt;So I pulled the SD card out of the working unit, unplugged the UART wires, and walked them across to the no-NAND machine. Wired everything back up — brown to GND, yellow to RX, orange to TX, leaving VCC unconnected, just like the original unit. Cleared the UART log on my laptop. Plugged in power.&lt;/p&gt;

&lt;p&gt;The boot log that came back was, byte-for-byte, the same as on the unit with eMMC:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;U-Boot SPL 2026.07-rc2-g744cf5d4e398-dirty
DRAM: 2048 MiB
Trying to boot from MMC1
NOTICE:  BL31: Detected Allwinner A64/H64/R18 SoC (1689)
NOTICE:  BL31: Found U-Boot DTB at 0x20ad278, model: Remix Mini PC

U-Boot 2026.07-rc2-g744cf5d4e398-dirty Allwinner Technology

CPU:   Allwinner A64 (SUN50I)
Model: Remix Mini PC
DRAM:  2 GiB
&lt;/span&gt;&lt;span class="c"&gt;...
&lt;/span&gt;&lt;span class="go"&gt;Starting kernel ...

Armbian 24.11.1 Bookworm ttyS0
pine64 login:
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The TOC0 SPL was accepted by the BROM. DRAM training landed on the same 2 GiB. BL31 ran. U-Boot proper announced itself as "Model: Remix Mini PC." The Armbian kernel started. The login prompt appeared. The whole pipeline I described in the previous post worked, unchanged, on a board with one major chip physically absent.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this tells me
&lt;/h2&gt;

&lt;p&gt;A few things, all small but worth recording.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The recipe is the silicon, not the board.&lt;/strong&gt; Once the BROM, the secure-boot fuse, and the DRAM controller are the same, the boot chain does not actually care whether eMMC is present. The Allwinner A64/H64 family has three MMC controllers as part of the SoC itself; U-Boot enumerates all three regardless of what is wired to them. The line&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MMC:   mmc@1c0f000: 0, mmc@1c10000: 2, mmc@1c11000: 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;prints identically on both units. The difference is only at scan time — &lt;code&gt;mmc 2&lt;/code&gt; finds an eMMC card on one unit and finds nothing on the other. The SD card on &lt;code&gt;mmc 0&lt;/code&gt; is the same on both.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One SD card revives any Remix Mini PC.&lt;/strong&gt; That is a useful property for anyone trying this at home. You do not have to characterize the device in front of you to know which recipe applies. Make the SD card once, plug it into whatever Remix you have, power on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The no-NAND unit is the better test bench.&lt;/strong&gt; This is the practical consequence I will probably get the most use out of. The unit with eMMC carries years of accumulated bootloader state in its boot partitions; even after this project, those boot partitions still contain mixed eGON and TOC0 artifacts from my placement experiments. Anything I do to a no-NAND unit, by contrast, can never persist beyond power-off. Pull the SD card, plug a different SD card, fresh state. For experimenting with new U-Boot builds or DT changes, that is significantly safer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No FEL is needed on either unit.&lt;/strong&gt; This was the original goal — boot Linux from cold, no laptop attached, no USB sideload — and now it's true for both machines I have.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this rules out
&lt;/h2&gt;

&lt;p&gt;This post does &lt;em&gt;not&lt;/em&gt; prove that the recipe works on every Remix Mini PC ever sold. There are likely small variations across production runs that I cannot test from here. The CPU stepping, the DDR3 supplier, the exact WiFi module — any of these could differ on someone else's unit and require small tweaks to the defconfig or DTB. The vqmmc-supply patch we did on the bananapi DTB, for example, is a Remix-specific addition; the DRAM clock and ZQ values in the upstream defconfig may not match every unit either.&lt;/p&gt;

&lt;p&gt;What this post does prove is that the &lt;em&gt;two&lt;/em&gt; units I have, despite one of them having a different hardware population, take the same SD card. That's a useful data point for anyone considering the recipe.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I am keeping the no-NAND unit for
&lt;/h2&gt;

&lt;p&gt;This used to be a paperweight. As of this evening, it is a perfectly good 2 GB ARM Linux box that boots from a single SD card and runs unattended. It will probably end up as a permanent home for something — a small monitoring node, a development sandbox for the next project, maybe just a second machine to keep on a shelf for friends who want to see the recipe work in person.&lt;/p&gt;

&lt;p&gt;It is good to have the option.&lt;/p&gt;




&lt;p&gt;Enjoying the content? If you'd like to support my work and keep the ideas flowing, consider buying me a coffee! Your support means the world to me!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/devcornercrew" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" height="41" width="174"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>pc</category>
      <category>arm</category>
      <category>debian</category>
      <category>android</category>
    </item>
    <item>
      <title>Remix Mini PC: The Day It Finally Booted Itself</title>
      <dc:creator>Matt Miller</dc:creator>
      <pubDate>Sun, 24 May 2026 20:37:04 +0000</pubDate>
      <link>https://dev.to/matemiller/remix-mini-pc-the-day-it-finally-booted-itself-o2l</link>
      <guid>https://dev.to/matemiller/remix-mini-pc-the-day-it-finally-booted-itself-o2l</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/r4nd3l/remix_mini_pc_revival_recipe" rel="noopener noreferrer"&gt;Source files: GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more than a year, the Remix Mini PC on my desk could only be brought to life by attaching a laptop and pushing U-Boot into it over USB OTG. Every reboot was a manual ritual: trigger FEL mode, run &lt;code&gt;sunxi-fel uboot ...&lt;/code&gt;, wait. Useful for development; useless as a real machine.&lt;/p&gt;

&lt;p&gt;This is the post about the day that changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap: where we were
&lt;/h2&gt;

&lt;p&gt;The previous post pinned down the wall. The Remix Mini PC has the Allwinner A64 "secure boot" eFuse burned, which makes the BROM refuse standard eGON-format SPLs from both the SD card and the eMMC. There is no ROTPK key fused in, so the BROM doesn't actually check who signed the boot code — it just demands the &lt;strong&gt;TOC0&lt;/strong&gt; wrapper format. A self-signed TOC0 image, signed with any RSA key, will pass.&lt;/p&gt;

&lt;p&gt;That meant the path to a permanent boot was clear: produce a TOC0-wrapped SPL, write it to a place the BROM looks, power-cycle, see what happens.&lt;/p&gt;

&lt;p&gt;Easy to write. Less easy to do.&lt;/p&gt;

&lt;h2&gt;
  
  
  The U-Boot defconfig that wasn't there
&lt;/h2&gt;

&lt;p&gt;The mainline Linux kernel has had a device tree for the Remix Mini PC since 2023, contributed by Andre Przywara at Arm. The same author also submitted a four-patch series for U-Boot in April 2024 to add full board support, including a &lt;code&gt;remix-mini-pc_defconfig&lt;/code&gt; with &lt;code&gt;CONFIG_SPL_IMAGE_TYPE_SUNXI_TOC0=y&lt;/code&gt; — exactly the build switch that produces a TOC0 image.&lt;/p&gt;

&lt;p&gt;Only some of that series actually landed in mainline U-Boot. The device tree file was imported. The defconfig and the Makefile glue were not. So a fresh clone of mainline U-Boot today has the DTS file sitting there, but no way to build it — no defconfig, and no entry in the dtb Makefile to compile it as part of any board build.&lt;/p&gt;

&lt;p&gt;The defconfig is fourteen lines. The Makefile change is one line. Pulling the patch series from &lt;code&gt;lore.kernel.org&lt;/code&gt; and extracting just patch 2/4 (which is the Remix-specific one) gave me both:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;CONFIG_DEFAULT_DEVICE_TREE&lt;/span&gt;=&lt;span class="s2"&gt;"sun50i-h64-remix-mini-pc"&lt;/span&gt;
&lt;span class="n"&gt;CONFIG_SPL&lt;/span&gt;=&lt;span class="n"&gt;y&lt;/span&gt;
&lt;span class="n"&gt;CONFIG_MACH_SUN50I&lt;/span&gt;=&lt;span class="n"&gt;y&lt;/span&gt;
&lt;span class="n"&gt;CONFIG_DRAM_CLK&lt;/span&gt;=&lt;span class="m"&gt;672&lt;/span&gt;
&lt;span class="n"&gt;CONFIG_DRAM_ZQ&lt;/span&gt;=&lt;span class="m"&gt;4013533&lt;/span&gt;
&lt;span class="n"&gt;CONFIG_MMC_SUNXI_SLOT_EXTRA&lt;/span&gt;=&lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="n"&gt;CONFIG_SPL_IMAGE_TYPE_SUNXI_TOC0&lt;/span&gt;=&lt;span class="n"&gt;y&lt;/span&gt;
&lt;span class="n"&gt;CONFIG_SUPPORT_EMMC_BOOT&lt;/span&gt;=&lt;span class="n"&gt;y&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;git am&lt;/code&gt; rejected the patch because the surrounding context in &lt;code&gt;arch/arm/dts/Makefile&lt;/code&gt; had drifted in the two years since the patch was written. So I applied both halves by hand: created the defconfig file directly from the patch's &lt;code&gt;+&lt;/code&gt; lines, and used a small &lt;code&gt;awk&lt;/code&gt; to splice the new DTB filename into the right place in the Makefile.&lt;/p&gt;

&lt;p&gt;That part went smoothly. The rest of the day did not.&lt;/p&gt;

&lt;h2&gt;
  
  
  TF-A is a black hole
&lt;/h2&gt;

&lt;p&gt;The U-Boot build needs ARM Trusted Firmware-A (&lt;code&gt;bl31.bin&lt;/code&gt;) as the EL3 secure monitor. Standard sunxi64 build step: clone TF-A, &lt;code&gt;make PLAT=sun50i_a64 bl31&lt;/code&gt;, point U-Boot at the output.&lt;/p&gt;

&lt;p&gt;TF-A's build did not cooperate. The first attempt failed because I built it with &lt;code&gt;DEBUG=1&lt;/code&gt; and the resulting binary was 472 bytes too big for the A64's BL31 SRAM region. Fine, build release. Release said &lt;code&gt;make: Nothing to be done for 'bl31'&lt;/code&gt;, even after a clean clone in a brand-new directory.&lt;/p&gt;

&lt;p&gt;I spent an embarrassing amount of time on this. The cause turned out to be a name collision: TF-A has both a &lt;code&gt;bl31&lt;/code&gt; makefile target and a &lt;code&gt;bl31/&lt;/code&gt; source directory in the root of the repo. GNU make sometimes interprets &lt;code&gt;make bl31&lt;/code&gt; as "build the directory &lt;code&gt;bl31/&lt;/code&gt;," sees that the directory exists, and concludes there is nothing to do. &lt;code&gt;make -B&lt;/code&gt; didn't override it. &lt;code&gt;make all&lt;/code&gt; didn't produce a bl31. Neither did invoking the absolute path of the output file as a target.&lt;/p&gt;

&lt;p&gt;After about half an hour, I gave up and searched Debian for a pre-built one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;dpkg &lt;span class="nt"&gt;-L&lt;/span&gt; arm-trusted-firmware | &lt;span class="nb"&gt;grep &lt;/span&gt;sun50i
&lt;span class="go"&gt;/usr/lib/arm-trusted-firmware/sun50i_a64
/usr/lib/arm-trusted-firmware/sun50i_a64/bl31.bin
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There it was. Debian's &lt;code&gt;arm-trusted-firmware&lt;/code&gt; package ships pre-built BL31 binaries for many platforms, including sun50i_a64. The version is older than what U-Boot's bleeding-edge build would normally use (TF-A 2.8 from 2022 vs. master), but for our purposes — getting the secure monitor up and getting out of EL3 — it works fine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;BL31&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/lib/arm-trusted-firmware/sun50i_a64/bl31.bin
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/uboot-build/u-boot &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; make &lt;span class="nt"&gt;-j4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The build needed one more thing it had been complaining about earlier: a signing key. TOC0 images are signed; &lt;code&gt;mkimage&lt;/code&gt; looks for &lt;code&gt;root_key.pem&lt;/code&gt; in the build directory. The error message even tells you the cure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkimage (TOC0): info: Try 'openssl genrsa -out root_key.pem'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since the BROM does not check the key against a fused root-of-trust hash, any RSA key works. I generated a 2048-bit one on the spot. Reproducible enough — just keep the file around.&lt;/p&gt;

&lt;p&gt;The build finished. The first eight bytes of &lt;code&gt;u-boot-sunxi-with-spl.bin&lt;/code&gt; were:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;54 4f 43 30 2e 47 4c 48   |TOC0.GLH|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Right magic. Worth trying.&lt;/p&gt;

&lt;h2&gt;
  
  
  The placement experiments
&lt;/h2&gt;

&lt;p&gt;The eMMC's boot partition was the obvious target. PARTITION_CONFIG was already set to 0x48 — boot from boot partition 1 — so writing the new SPL to &lt;code&gt;/dev/mmcblk2boot0&lt;/code&gt; at offset 0 should have been the cleanest possible test.&lt;/p&gt;

&lt;p&gt;Wrote it, power-cycled, watched the UART. Silence. The green LED came on, the BROM accepted no boot code, the device sat in FEL mode waiting for a USB sideload. Same outcome that I had been fighting for a year.&lt;/p&gt;

&lt;p&gt;Tried offset 8 KiB instead — that's where sunxi SPL lives on SD cards. Same silence. (I also discovered that Linux re-applies the eMMC boot partition's read-only flag on every boot, so my "second" write had silently failed. That cost another ten minutes of confusion before I caught the &lt;code&gt;Operation not permitted&lt;/code&gt; in the &lt;code&gt;dd&lt;/code&gt; output.)&lt;/p&gt;

&lt;p&gt;The thing that finally worked was the most embarrassing one: write the same TOC0 to the &lt;strong&gt;SD card&lt;/strong&gt; at sector 16, the standard sunxi SD SPL offset.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo dd &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;u-boot-sunxi-with-spl.bin &lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/mmcblk0 &lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;512 &lt;span class="nv"&gt;seek&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;16 &lt;span class="nv"&gt;conv&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;fsync
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pull power. Plug power. Watch the UART.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;U-Boot SPL 2026.07-rc2-g744cf5d4e398-dirty (May 22 2026 - 22:23:12 +0200)
DRAM: 2048 MiB
Trying to boot from MMC1
NOTICE:  BL31: v2.8(release):
NOTICE:  BL31: Detected Allwinner A64/H64/R18 SoC (1689)
NOTICE:  BL31: Found U-Boot DTB at 0x20ad278, model: Remix Mini PC

U-Boot 2026.07-rc2-g744cf5d4e398-dirty Allwinner Technology

CPU:   Allwinner A64 (SUN50I)
Model: Remix Mini PC
DRAM:  2 GiB
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The one line that meant everything: &lt;code&gt;Model: Remix Mini PC&lt;/code&gt;. For more than a year, every boot of this device — when it booted at all — had announced itself as a BananaPi-M64, because that was the closest mainline U-Boot defconfig I could compile. This time, for the first time, U-Boot reported the device's actual name. The BROM had loaded my self-signed TOC0. The secure boot wall was a key the device was willing to copy off itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  The last small obstacle
&lt;/h2&gt;

&lt;p&gt;U-Boot kept going and tried to boot Linux, but failed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;File /boot/dtb/allwinner/sun50i-h64-remix-mini-pc.dtb does not exists
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The new defconfig sets &lt;code&gt;CONFIG_DEFAULT_DEVICE_TREE="sun50i-h64-remix-mini-pc"&lt;/code&gt;, so when U-Boot's boot script asks the SD card for a kernel device tree, it asks for that filename — but the Armbian image on the card was built for &lt;code&gt;sun50i-a64-bananapi-m64&lt;/code&gt; and doesn't ship the Remix DTB.&lt;/p&gt;

&lt;p&gt;A two-line fix. Mount the SD card on my laptop, append &lt;code&gt;fdtfile=allwinner/sun50i-a64-bananapi-m64.dtb&lt;/code&gt; to &lt;code&gt;armbianEnv.txt&lt;/code&gt;, copy the newly-built remix DTB to &lt;code&gt;/boot/dtb/allwinner/&lt;/code&gt; as a fallback. Reinsert.&lt;/p&gt;

&lt;p&gt;Power-cycle. Without touching the laptop afterwards. The SPL banner scrolled, U-Boot loaded, the boot script ran, the kernel started, Armbian came up, the login prompt appeared.&lt;/p&gt;

&lt;p&gt;Plug power, it runs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this looks like now
&lt;/h2&gt;

&lt;p&gt;The Remix Mini PC is no longer a glorified paperweight. The boot chain is entirely my own:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;silicon BROM
  -&amp;gt; SD sector 16:    TOC0-signed U-Boot SPL (mainline U-Boot, signed with my key)
     -&amp;gt; BL31:         Debian's pre-built TF-A 2.8 for sun50i_a64
        -&amp;gt; U-Boot:    mainline 2026.07-rc2 with remix-mini-pc_defconfig
           -&amp;gt; /boot/boot.scr -&amp;gt; Image + initrd + bananapi-m64 DTB (with my vqmmc patch)
              -&amp;gt; Linux 6.6.62 -&amp;gt; Armbian login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No laptop. No FEL. No magic. Just power.&lt;/p&gt;

&lt;p&gt;There are still loose ends. The Linux side is still using a patched BananaPi-M64 device tree rather than the proper Remix one, because that is what the Armbian kernel package has prebuilt and I have not built a kernel against the upstream Remix DTS yet. The eMMC is unused — the boot chain lives on the SD card, because that is where the BROM is willing to read TOC0. I can probably get the eMMC into the boot path too, but it is no longer urgent now that the device just works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reflections
&lt;/h2&gt;

&lt;p&gt;A few things from the journey worth holding onto.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The wiki was right and I should have believed it sooner.&lt;/strong&gt; The linux-sunxi page for this device says, almost in passing, "the SoC has the secure boot fuse burned, so it will not accept any standard eGON boot media." I read that line a year ago and assumed it was something esoteric and untestable. It was the single most important fact about the device.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Half-merged upstream support is more common than you would think.&lt;/strong&gt; The DTS file for this device sits in mainline Linux &lt;em&gt;and&lt;/em&gt; in mainline U-Boot, but the U-Boot defconfig that ties it together never landed. It is one small patch file on a mailing list, easy to apply by hand once you find it. If you are reviving an obscure SBC, search the mailing list archives before assuming you have to write everything yourself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Old tools are sometimes still right.&lt;/strong&gt; I spent an hour fighting TF-A's build system trying to produce a fresh BL31 binary. The bl31 that ended up being executed is a 2022 build from a Debian package, and the device booted with it the first time I tried. Doing the unfashionable thing was the fastest path.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The diagnostic that mattered was the UART line.&lt;/strong&gt; Once I could see "Model: Remix Mini PC" instead of "BananaPi-M64," I knew exactly what I had done — and what to fix next. Every interesting debugging moment in this project has happened over a serial cable. Buy the cable.&lt;/p&gt;

&lt;p&gt;This was the last big wall. Whatever comes next on this device is application work, not survival work. After more than a year, that feels different in a way that is hard to write down.&lt;/p&gt;

&lt;p&gt;The Remix Mini PC is alive on its own.&lt;/p&gt;




&lt;p&gt;Enjoying the content? If you'd like to support my work and keep the ideas flowing, consider buying me a coffee! Your support means the world to me!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/devcornercrew" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" height="41" width="174"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>pc</category>
      <category>arm</category>
      <category>debian</category>
      <category>android</category>
    </item>
    <item>
      <title>Remix Mini PC: Confirming What Stands Between Us and Cold Boot</title>
      <dc:creator>Matt Miller</dc:creator>
      <pubDate>Sun, 24 May 2026 20:34:40 +0000</pubDate>
      <link>https://dev.to/matemiller/remix-mini-pc-confirming-what-stands-between-us-and-cold-boot-5b12</link>
      <guid>https://dev.to/matemiller/remix-mini-pc-confirming-what-stands-between-us-and-cold-boot-5b12</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/r4nd3l/remix_mini_pc_revival_recipe" rel="noopener noreferrer"&gt;Source files: GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that the eMMC is finally accessible — see the previous post — the project's centre of gravity shifts. The remaining goal is to make the device boot Linux from cold, without needing a USB FEL sideload every time. This post is about a small, quick experiment that pinned down exactly what is in the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we knew
&lt;/h2&gt;

&lt;p&gt;The Allwinner A64 BROM (the immutable mask-ROM in the SoC) tries to find an SPL in this order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;SD card (&lt;code&gt;mmc0&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;eMMC (&lt;code&gt;mmc2&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;SPI NOR flash&lt;/li&gt;
&lt;li&gt;FEL mode over USB OTG&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Up until now my workflow has always been to enter FEL mode and sideload U-Boot from the laptop. That works. But it means the device cannot run headless and standalone — every reboot needs the laptop.&lt;/p&gt;

&lt;p&gt;The Linux-sunxi wiki page for the Remix Mini PC has a paragraph that I had read but not really believed:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The SoC has the "secure boot" fuse burned, so it will not accept any standard eGON boot media on an SD card or eMMC, and instead it expects TOC0 wrapped boot code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;"eGON" is the magic header on standard sunxi SPLs; "TOC0" is a signed-image format with a header structure derived from ARM's Trusted Firmware. The wiki is saying the BROM will refuse anything in the older eGON format.&lt;/p&gt;

&lt;p&gt;That sounded inconvenient enough that I wanted to be sure it was true on my specific unit before doing any work that depended on it. Two minutes of testing can save hours of building.&lt;/p&gt;

&lt;h2&gt;
  
  
  The experiment
&lt;/h2&gt;

&lt;p&gt;The test is trivial:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Boot Armbian normally (via FEL+sideload, as always).&lt;/li&gt;
&lt;li&gt;From inside Armbian, run &lt;code&gt;sudo poweroff&lt;/code&gt; and wait for a clean shutdown.&lt;/li&gt;
&lt;li&gt;Unplug power.&lt;/li&gt;
&lt;li&gt;Plug power back in. Do nothing else — no FEL trigger, no &lt;code&gt;sunxi-fel&lt;/code&gt; command, no key on a keyboard.&lt;/li&gt;
&lt;li&gt;Watch the UART for any sign of life.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the BROM accepts the SPL on the SD card or the eMMC, U-Boot will start printing within a second or two. If it does not, the device will sit silent — the BROM falls back to FEL mode but FEL mode itself is silent until something talks to it over the OTG port.&lt;/p&gt;

&lt;p&gt;I set the SD card to be inserted with a known-working eGON-format SPL on it (the Armbian image's standard layout, dd'd to sector 16). The eMMC boot partition also has an eGON SPL from previous experimentation. If secure boot were not enforced, one of the two should have worked.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happened
&lt;/h2&gt;

&lt;p&gt;The power LED came up green. UART stayed completely silent. After fifteen seconds I checked the USB side:&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="nv"&gt;$ &lt;/span&gt;lsusb | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; allwinner
Bus 001 Device 010: ID 1f3a:efe8 Allwinner Technology sunxi SoC OTG connector &lt;span class="k"&gt;in &lt;/span&gt;FEL/flashing mode
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The board is alive — it is sitting in FEL mode, waiting for a sideload — but it has rejected both candidate SPLs. That is the textbook fingerprint of a BROM with the secure boot eFuse burned and no eGON path accepted.&lt;/p&gt;

&lt;p&gt;For completeness, there is no ROTPK (root-of-trust public key) burned into the chip's eFuses either. That second fact matters: it means the BROM enforces the &lt;em&gt;format&lt;/em&gt; (TOC0) but does not enforce a particular &lt;em&gt;signing key&lt;/em&gt;. Anyone can sign with any key and the BROM will load it. The TOC0 wrapper is a structural requirement, not a cryptographic one.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this rules out, and what it leaves
&lt;/h2&gt;

&lt;p&gt;There were two obvious quick-wins I had been considering for cold-boot, and this test rules out both:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option B: zero the existing eMMC SPL and let the BROM fall through to SD.&lt;/strong&gt;&lt;br&gt;
The hope here was that the eMMC SPL is what is being chosen first, and if we corrupted it the BROM would skip eMMC and use the SD card's SPL instead. The test shows the SD SPL is &lt;em&gt;also&lt;/em&gt; being rejected — both are eGON-format, and both fail the BROM's check. Zeroing the eMMC SPL changes nothing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Just trusting that eMMC-boot already works because there is an eGON SPL on the eMMC boot partition.&lt;/strong&gt;&lt;br&gt;
Looking at the eMMC dump from the previous session, &lt;code&gt;/dev/mmcblk2boot0&lt;/code&gt; already contained an eGON-format SPL (with a header identifying it as a sunxi mainline build). I had briefly hoped this meant the device might already cold-boot from eMMC. It does not. Same rejection.&lt;/p&gt;

&lt;p&gt;What is left, and the only real path forward, is to produce a TOC0-wrapped SPL and write it to either the SD card's sector 16 or the eMMC's boot partition. The mainline U-Boot tree has a defconfig — &lt;code&gt;remix-mini-pc_defconfig&lt;/code&gt;, added by Andre Przywara — that does exactly this. Build it, sign with any key, write it down, cold-boot.&lt;/p&gt;

&lt;h2&gt;
  
  
  A small but useful negative result
&lt;/h2&gt;

&lt;p&gt;The whole exercise took less time than my coffee took to cool down, but it changed the shape of the next chunk of work. Without it I would have been tempted to do something destructive to the eMMC for no benefit. With it I know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TOC0 is mandatory. There is no eGON cold-boot path.&lt;/li&gt;
&lt;li&gt;Both the SD and the eMMC are dead ends for standard sunxi binaries — the &lt;em&gt;medium&lt;/em&gt; is fine, the &lt;em&gt;format&lt;/em&gt; is the problem.&lt;/li&gt;
&lt;li&gt;FEL remains the only entry point until the day a TOC0-wrapped SPL lives on the device.&lt;/li&gt;
&lt;li&gt;Once we have a working TOC0 SPL, putting it on either the SD card or the eMMC boot partition should produce a working cold-boot. We have two independent shots.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;Next session: clone mainline U-Boot, build &lt;code&gt;remix-mini-pc_defconfig&lt;/code&gt;, write the resulting SPL to the eMMC, power-cycle without a laptop attached, and — if the wiki is to be believed — watch the device finally come up on its own.&lt;/p&gt;




&lt;p&gt;Enjoying the content? If you'd like to support my work and keep the ideas flowing, consider buying me a coffee! Your support means the world to me!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/devcornercrew" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" height="100" width="434"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>pc</category>
      <category>arm</category>
      <category>debian</category>
      <category>android</category>
    </item>
    <item>
      <title>Remix Mini PC: After a Year of Dead Ends, the eMMC Finally Talks</title>
      <dc:creator>Matt Miller</dc:creator>
      <pubDate>Sun, 24 May 2026 20:28:55 +0000</pubDate>
      <link>https://dev.to/matemiller/remix-mini-pc-after-a-year-of-dead-ends-the-emmc-finally-talks-16p6</link>
      <guid>https://dev.to/matemiller/remix-mini-pc-after-a-year-of-dead-ends-the-emmc-finally-talks-16p6</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/r4nd3l/remix_mini_pc_revival_recipe" rel="noopener noreferrer"&gt;Source files: GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more than a year I have been chasing the same brick wall on the Remix Mini PC project: I could sideload a working Linux from an SD card, but the internal eMMC was a black box. Every attempt to read from it returned an I/O error. Every theory I tried — write-protect bits, NAND blacklists, hardware reset quirks, lockout states left behind by Android — went nowhere.&lt;/p&gt;

&lt;p&gt;It turns out the cause was none of those things. It was one missing line in a device tree.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup recap
&lt;/h2&gt;

&lt;p&gt;The Remix Mini PC is a 2015-vintage Android desktop box built around an Allwinner SoC (marketed as "H64", which is the same silicon as the much more common A64). Stock firmware was a locked Android variant that the manufacturer abandoned long ago. The project's goal: replace it with Armbian, permanently, on the internal eMMC.&lt;/p&gt;

&lt;p&gt;The state going into this session:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FEL mode sideload of mainline U-Boot works (built with the BananaPi-M64 defconfig).&lt;/li&gt;
&lt;li&gt;SD card boot all the way to a login prompt works (Armbian 24.11.1, kernel 6.6.62).&lt;/li&gt;
&lt;li&gt;Reading from the internal eMMC, however, immediately fails with kernel errors:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sunxi-mmc 1c11000.mmc: data error, sending stop command
sunxi-mmc 1c11000.mmc: send stop command failed
mmc2: cache flush error -110
mmc2: tried to HW reset card, got error -110
mmcblk2: recovery failed!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The kernel sees the chip — it reads its CID, its CSD, its 14.6 GiB capacity, its part name (&lt;code&gt;AGND3R&lt;/code&gt;) — but the moment the host asks for actual data, the bus collapses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Things I tried that did &lt;em&gt;not&lt;/em&gt; matter
&lt;/h2&gt;

&lt;p&gt;I went deep into the device tree binary. Patching it in place with &lt;code&gt;fdtput&lt;/code&gt;, decompiling and recompiling with &lt;code&gt;dtc&lt;/code&gt;. I tested, in order:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Knob&lt;/th&gt;
&lt;th&gt;What I tried&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Bus clock&lt;/td&gt;
&lt;td&gt;150 MHz → 25 MHz → 1 MHz&lt;/td&gt;
&lt;td&gt;identical failure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bus modes&lt;/td&gt;
&lt;td&gt;disabled HS200, HS400, 1.8V signaling&lt;/td&gt;
&lt;td&gt;identical failure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bus width&lt;/td&gt;
&lt;td&gt;8-bit → 4-bit&lt;/td&gt;
&lt;td&gt;identical failure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HW reset capability&lt;/td&gt;
&lt;td&gt;removed &lt;code&gt;cap-mmc-hw-reset&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;identical failure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pin muxing&lt;/td&gt;
&lt;td&gt;dropped the HS400 data-strobe pin&lt;/td&gt;
&lt;td&gt;identical failure&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The failure mode never changed shape. That was the clue I should have read earlier: if signal-rate tweaks don't move the needle at all, the problem is not at the signal layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The breakthrough
&lt;/h2&gt;

&lt;p&gt;A web search turned up something I had not realised existed: &lt;strong&gt;the Remix Mini PC is supported in mainline Linux&lt;/strong&gt;, under the name &lt;code&gt;sun50i-h64-remix-mini-pc.dts&lt;/code&gt;, contributed by Andre Przywara at ARM. The DTS lives in the mainline kernel tree at &lt;code&gt;arch/arm64/boot/dts/allwinner/&lt;/code&gt;. The corresponding U-Boot patch landed in April 2024.&lt;/p&gt;

&lt;p&gt;I pulled the official Remix DTS and put it side by side with the BananaPi-M64 DTS I had been using. The difference for the eMMC block jumped off the screen:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;amp;mmc2 {
    pinctrl-names = "default";
    pinctrl-0 = &amp;lt;&amp;amp;mmc2_pins&amp;gt;, &amp;lt;&amp;amp;mmc2_ds_pin&amp;gt;;
    vmmc-supply = &amp;lt;&amp;amp;reg_dcdc1&amp;gt;;     // chip Vcc, 3.3V — was present
    vqmmc-supply = &amp;lt;&amp;amp;reg_eldo1&amp;gt;;    // I/O voltage, 1.8V — WAS MISSING
    bus-width = &amp;lt;8&amp;gt;;
    non-removable;
    mmc-hs200-1_8v;
    mmc-hs400-1_8v;
    cap-mmc-hw-reset;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The BananaPi-M64 DTB declares only &lt;code&gt;vmmc-supply&lt;/code&gt;, the regulator that powers the eMMC chip itself. It says nothing about &lt;code&gt;vqmmc-supply&lt;/code&gt;, the separate regulator that drives the eMMC bus signal lines.&lt;/p&gt;

&lt;p&gt;eMMC uses two voltage domains. Vcc (the &lt;code&gt;vmmc&lt;/code&gt; rail) powers the chip's internal logic. VccQ (the &lt;code&gt;vqmmc&lt;/code&gt; rail) is the I/O voltage for CLK, CMD, and DAT0–7. On the Remix's PCB, that rail is wired to a different regulator (&lt;code&gt;eldo1&lt;/code&gt;, 1.8V) than the chip's main supply. Without the kernel knowing about that regulator, it never gets enabled — and the data bus lines have no drive voltage.&lt;/p&gt;

&lt;p&gt;That explained everything. The chip's command/response channel runs at different signaling and was already powered, so initialisation worked. The instant the host attempted a data transfer over DAT0–3, the bus collapsed. There was nothing to receive on.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix
&lt;/h2&gt;

&lt;p&gt;I added the missing property to the live DTB on the SD card:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;fdtput &lt;span class="nt"&gt;-t&lt;/span&gt; i /boot/dtb/allwinner/sun50i-a64-bananapi-m64.dtb &lt;span class="se"&gt;\&lt;/span&gt;
    /soc/mmc@1c11000 vqmmc-supply 0x4e
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;0x4e&lt;/code&gt; is the phandle of the &lt;code&gt;eldo1&lt;/code&gt; regulator node in the same DTB, which the BananaPi-M64 board uses for its audio codec but which on the Remix is the eMMC I/O rail. Same regulator hardware; just being repurposed to point at the right consumer.&lt;/p&gt;

&lt;p&gt;Reboot. Sideload U-Boot via FEL. Log in. Type the test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo dd &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/mmcblk2 &lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1M &lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tmp/test.bin &lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;progress
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;1+0 records in
1+0 records out
1048576 bytes (1,0 MB, 1,0 MiB) copied, 0,0482 s, 21,7 MB/s
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A megabyte. In fifty milliseconds. From a chip that had not yielded a single readable byte in over a year.&lt;/p&gt;

&lt;p&gt;For good measure I queried the EXT_CSD register, which uses a different MMC command path than block reads — that worked too. And it revealed something I had not let myself hope for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;BOOT_WP_STATUS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="s"&gt;0x00      // not write-protected&lt;/span&gt;
&lt;span class="py"&gt;BOOT_WP&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;          &lt;span class="s"&gt;0x00      // not write-protected&lt;/span&gt;
&lt;span class="py"&gt;USER_WP&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;          &lt;span class="s"&gt;0x00      // not write-protected&lt;/span&gt;
&lt;span class="py"&gt;BOOT_CONFIG_PROT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0x00      // boot config can be changed&lt;/span&gt;
&lt;span class="py"&gt;PARTITION_SETTING_COMPLETED&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0x00&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The chip is not locked. It has never been locked. The "permanently write-protected" story I had been telling myself based on Linux-level &lt;code&gt;force_ro&lt;/code&gt; flags and observed I/O errors was wrong. The chip is wide open. I just could not see it because the bus could not carry a single byte.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons I want to keep
&lt;/h2&gt;

&lt;p&gt;A few things from this session worth holding onto, in case they are useful to anyone else fighting a similar ghost.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Find the official upstream description of your hardware before you start guessing at it.&lt;/strong&gt; The single most valuable artifact in this debugging session was the official &lt;code&gt;sun50i-h64-remix-mini-pc.dts&lt;/code&gt; file in mainline. Fifteen minutes of reading saved me what would have been days more of DT poking. The fact that the Remix Mini PC has had mainline support since 2023 and I did not know it is on me.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If a tunable does not change the failure mode, the failure is not in that tunable's layer.&lt;/strong&gt; I tried five different knobs across two orders of magnitude in clock speed. None of them moved the symptom. That should have told me immediately that the failure was at a layer below "bus signaling". I kept going because I had no better idea, but in hindsight that was wasted effort.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Distinguish what the chip says about itself from what the host's view of the chip says.&lt;/strong&gt; Linux block-device flags like &lt;code&gt;force_ro&lt;/code&gt; are software-level safety overlays. The chip's actual write protection lives in the EXT_CSD register and is queryable with &lt;code&gt;mmc-utils&lt;/code&gt;. Until I could query that register, every claim about whether the chip was "locked" was guesswork. The reason I could not query it earlier was the same vqmmc problem — &lt;code&gt;mmc extcsd read&lt;/code&gt; also needs a working data bus. The same fix unlocked everything at once.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Two voltage rails. eMMC always has two voltage rails.&lt;/strong&gt; Vcc and VccQ. If you only configure one, the chip will enumerate and then silently refuse all data transfers. This is now permanently lodged in my head.&lt;/p&gt;

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

&lt;p&gt;The eMMC being readable is the milestone, but the project's goal is to make the Remix boot Linux from internal storage &lt;em&gt;without&lt;/em&gt; needing a USB-OTG FEL trigger every time. That is a separate problem — the Allwinner A64 boot ROM on this board enforces a particular signed-image format called TOC0, which standard sunxi U-Boot does not produce by default. There is a mainline U-Boot defconfig (&lt;code&gt;remix-mini-pc_defconfig&lt;/code&gt;) that does, and writing a TOC0-wrapped SPL into the eMMC boot partition should give us a cold-boot path.&lt;/p&gt;

&lt;p&gt;That's the next post.&lt;/p&gt;

&lt;p&gt;For now: after more than a year, the device that I had been treating as half-dead has its biggest organ back. Onward.&lt;/p&gt;




&lt;p&gt;Enjoying the content? If you'd like to support my work and keep the ideas flowing, consider buying me a coffee! Your support means the world to me!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/devcornercrew" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" height="100" width="434"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>pc</category>
      <category>debian</category>
      <category>arm</category>
      <category>android</category>
    </item>
    <item>
      <title>Bridging Both Worlds: Can You Mix Native and Frameworks?</title>
      <dc:creator>Matt Miller</dc:creator>
      <pubDate>Wed, 23 Apr 2025 08:40:00 +0000</pubDate>
      <link>https://dev.to/matemiller/bridging-both-worlds-can-you-mix-native-and-frameworks-kgi</link>
      <guid>https://dev.to/matemiller/bridging-both-worlds-can-you-mix-native-and-frameworks-kgi</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Why choose &lt;strong&gt;one side&lt;/strong&gt; when you can &lt;strong&gt;get the best of both&lt;/strong&gt;?&lt;br&gt;&lt;br&gt;
Today’s tools let us blend native performance with framework convenience—without forcing a binary choice.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6l4uc82jo4rktmb6gl9w.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6l4uc82jo4rktmb6gl9w.jpg" alt="Image by luis gomes from Pexels" width="640" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From &lt;strong&gt;Rust-powered backends for React frontends&lt;/strong&gt;, to &lt;strong&gt;WebAssembly running C++ in the browser&lt;/strong&gt;, this is the era of &lt;strong&gt;hybrid stacks&lt;/strong&gt;. Let's explore how developers are &lt;strong&gt;bridging native and modern frameworks&lt;/strong&gt; in real-world projects.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;1️⃣ The Case for Hybrid Architectures&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Modern apps often have &lt;strong&gt;diverse needs&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Speed in the backend
&lt;/li&gt;
&lt;li&gt;Interactivity in the frontend
&lt;/li&gt;
&lt;li&gt;Hardware control with cross-platform UI
&lt;/li&gt;
&lt;li&gt;Offline capabilities with cloud syncing
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;No single language or framework can do all of that efficiently.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
That’s where mixing comes in.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;2️⃣ Examples of Native + Framework Blends&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  💻 &lt;strong&gt;Tauri + React/Svelte&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Frontend: React or Svelte
&lt;/li&gt;
&lt;li&gt;Backend: Rust
&lt;/li&gt;
&lt;li&gt;Result: A tiny desktop app (3–10 MB!) with full system access&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ Tauri is a lean, secure alternative to Electron&lt;br&gt;&lt;br&gt;
✅ You get web dev DX + Rust performance&lt;br&gt;&lt;br&gt;
✅ Ships to Windows, macOS, Linux  &lt;/p&gt;

&lt;p&gt;🔹 Use case: cross-platform apps that need to interact with files, devices, or the OS&lt;/p&gt;




&lt;h3&gt;
  
  
  🌐 &lt;strong&gt;WebAssembly (WASM) + JS Frameworks&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Write critical logic in &lt;strong&gt;C/C++, Rust, or Go&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Compile to &lt;strong&gt;WASM&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Load it into &lt;strong&gt;Vue, React, or Angular&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ Speed boost where JS is too slow&lt;br&gt;&lt;br&gt;
✅ Perfect for:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Image/video processing
&lt;/li&gt;
&lt;li&gt;Cryptography
&lt;/li&gt;
&lt;li&gt;Emulator-based apps
&lt;/li&gt;
&lt;li&gt;Math-heavy calculations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💡 Tools: &lt;code&gt;wasm-bindgen&lt;/code&gt;, &lt;code&gt;Emscripten&lt;/code&gt;, &lt;code&gt;wasm-pack&lt;/code&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  ⚙️ &lt;strong&gt;Rust or Go Backends + Frontend Frameworks&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Rust (Actix, Axum) or Go (Gin, Fiber) for backend API
&lt;/li&gt;
&lt;li&gt;React/Next.js or Vue/Nuxt for frontend
&lt;/li&gt;
&lt;li&gt;Type-safe, scalable, and secure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹 Use case: High-performance APIs for dashboards, apps, SaaS&lt;/p&gt;

&lt;p&gt;✅ Clean separation of concerns&lt;br&gt;&lt;br&gt;
✅ Native speed, framework interactivity&lt;br&gt;&lt;br&gt;
✅ Modern DX with strong compile-time checks&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;3️⃣ Why Hybrid Is Gaining Popularity&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🟢 Benefits:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance where it counts&lt;/strong&gt;, convenience where it doesn’t
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gradual adoption&lt;/strong&gt;—you can keep your frontend and rewrite the backend piece by piece
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best tool for each job&lt;/strong&gt;, not just one hammer&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🔴 Challenges:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;More complex setup (especially if teams are split)
&lt;/li&gt;
&lt;li&gt;Build pipelines need to handle multiple toolchains
&lt;/li&gt;
&lt;li&gt;Debugging across the boundary (e.g., WASM + JS) can be tricky
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💡 But modern tools (like Vite, Tauri, Deno, Docker, and wasm-pack) &lt;strong&gt;make this surprisingly smooth&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;4️⃣ Real-World Hybrid Examples&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;🔹 &lt;strong&gt;Figma&lt;/strong&gt; – Web frontend + native WASM rendering engine&lt;br&gt;&lt;br&gt;
🔹 &lt;strong&gt;Tauri-based apps&lt;/strong&gt; – Productivity tools, note apps, crypto wallets&lt;br&gt;&lt;br&gt;
🔹 &lt;strong&gt;Photopea&lt;/strong&gt; – Photoshop-like app entirely in browser, with native-powered logic via WASM&lt;br&gt;&lt;br&gt;
🔹 &lt;strong&gt;VS Code&lt;/strong&gt; – Electron frontend + native Node + Rust-based extensions&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;5️⃣ Tips for Making the Blend Work&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Clearly define roles&lt;/strong&gt; between native and framework layers
&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;shared types&lt;/strong&gt; if possible (e.g., TypeScript + Rust typegen)
&lt;/li&gt;
&lt;li&gt;Build with &lt;strong&gt;automation&lt;/strong&gt;—make your CI/CD handle both environments
&lt;/li&gt;
&lt;li&gt;Start with &lt;strong&gt;core logic in native&lt;/strong&gt;, then expose to UI as a service/module&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;💡 Final Thoughts: Don’t Choose—Combine&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;✔ You don’t have to pick &lt;strong&gt;frameworks OR native&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✔ In 2025, the real skill is &lt;strong&gt;knowing how to connect systems&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✔ Use native power where needed (performance, hardware, security)&lt;br&gt;&lt;br&gt;
✔ Use frameworks for rapid UI, dev velocity, and collaboration  &lt;/p&gt;

&lt;p&gt;💬 &lt;strong&gt;Your Thoughts?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Have you built a hybrid project? Or thought about mixing Rust or Go with your favorite frontend stack? Let’s share ideas in the comments!&lt;/p&gt;




&lt;p&gt;Enjoying the content? If you'd like to support my work and keep the ideas flowing, consider buying me a coffee! Your support means the world to me!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/devcornercrew" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>developer</category>
      <category>devcorner</category>
      <category>coding</category>
      <category>learning</category>
    </item>
    <item>
      <title>Build Time, Maintenance &amp; Team Dynamics: Beyond the Code</title>
      <dc:creator>Matt Miller</dc:creator>
      <pubDate>Tue, 22 Apr 2025 08:40:00 +0000</pubDate>
      <link>https://dev.to/matemiller/build-time-maintenance-team-dynamics-beyond-the-code-4kei</link>
      <guid>https://dev.to/matemiller/build-time-maintenance-team-dynamics-beyond-the-code-4kei</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;It’s easy to get caught up in syntax, benchmarks, or feature sets—but let’s zoom out. The true test of any tech stack isn’t just how fast it runs or how cool it is, it’s &lt;strong&gt;how well it holds up over time&lt;/strong&gt;, especially when &lt;strong&gt;real people&lt;/strong&gt; work on it together.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcyuvxwkixywztzpe9uto.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcyuvxwkixywztzpe9uto.jpg" alt="Image by Mikhail Nilov from Pexels" width="640" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this post, we’ll look at how &lt;strong&gt;build complexity, maintainability, onboarding, and team workflows&lt;/strong&gt; differ between &lt;strong&gt;native-first projects&lt;/strong&gt; and &lt;strong&gt;framework-based ones&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;1️⃣ Build Time: From Source to Something You Can Use&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🧱 Native Stacks (Rust, C++, Go)
&lt;/h3&gt;

&lt;p&gt;✅ &lt;strong&gt;Powerful&lt;/strong&gt;, but require:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compilers and toolchains (e.g., Cargo, Make, GCC, Clang)
&lt;/li&gt;
&lt;li&gt;Managing linker flags, build targets, dependencies
&lt;/li&gt;
&lt;li&gt;Cross-compilation setups for Windows/macOS/Linux
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💡 Build times can be long, especially in large C++ codebases. Rust has improved this with incremental builds, but still slower than scripting languages.&lt;/p&gt;




&lt;h3&gt;
  
  
  ⚙️ Framework Stacks (JS, Python, PHP, etc.)
&lt;/h3&gt;

&lt;p&gt;✅ Usually interpreted or transpiled&lt;br&gt;&lt;br&gt;
✅ Easier to get running:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;npm install &amp;amp;&amp;amp; npm run dev&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;python app.py&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💡 You often get &lt;strong&gt;faster feedback loops&lt;/strong&gt; during dev, especially with hot reload or live updates.&lt;/p&gt;




&lt;h3&gt;
  
  
  🔥 Reality Check:
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Native Projects&lt;/th&gt;
&lt;th&gt;Framework Projects&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;First-time setup&lt;/td&gt;
&lt;td&gt;Medium/Hard&lt;/td&gt;
&lt;td&gt;Easy/Instant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compile times&lt;/td&gt;
&lt;td&gt;Long (C++), Moderate (Rust)&lt;/td&gt;
&lt;td&gt;Instant/short (TS/Python)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tooling complexity&lt;/td&gt;
&lt;td&gt;Higher&lt;/td&gt;
&lt;td&gt;Lower&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CI/CD integration&lt;/td&gt;
&lt;td&gt;More config-heavy&lt;/td&gt;
&lt;td&gt;Smoother (out of the box)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;2️⃣ Maintenance Over Time&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Native code tends to be more &lt;strong&gt;durable&lt;/strong&gt;, but also &lt;strong&gt;harder to modify&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Native:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Strong type systems and low-level control = &lt;strong&gt;less technical debt&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;But changes often affect more parts of the system&lt;/li&gt;
&lt;li&gt;Legacy C++ or embedded code can feel like a maze
&lt;/li&gt;
&lt;li&gt;Rust’s compiler fights for correctness (which helps future you)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Framework:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Easy to get started, &lt;strong&gt;but hard to keep clean&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Popular frameworks shift fast—React, Angular, Vue, etc.
&lt;/li&gt;
&lt;li&gt;Can accumulate "magic" abstractions and outdated patterns
&lt;/li&gt;
&lt;li&gt;Refactoring is easier, &lt;strong&gt;unless you're buried in third-party dependencies&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💡 Long-term success = &lt;strong&gt;clear architecture, tests, and documentation&lt;/strong&gt;, no matter what stack you choose.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;3️⃣ Onboarding New Developers&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This is where frameworks often shine.&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚙️ Framework Projects:
&lt;/h3&gt;

&lt;p&gt;✅ Easy to get up and running&lt;br&gt;&lt;br&gt;
✅ Clear conventions (routes, components, folder structure)&lt;br&gt;&lt;br&gt;
✅ Tons of tutorials and guides&lt;/p&gt;

&lt;p&gt;🟡 Downside: Developers may not understand &lt;strong&gt;underlying behavior&lt;/strong&gt;, leading to misuse of abstractions.&lt;/p&gt;




&lt;h3&gt;
  
  
  🧱 Native Projects:
&lt;/h3&gt;

&lt;p&gt;🟠 Steeper learning curve&lt;br&gt;&lt;br&gt;
🟠 Devs need to understand memory, pointers, types, or concurrency primitives&lt;br&gt;&lt;br&gt;
🟠 Tooling/setup may be unfamiliar (especially outside web developers)&lt;/p&gt;

&lt;p&gt;✅ But once they’re onboarded, &lt;strong&gt;native systems tend to be more predictable and robust&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;Tradeoff&lt;/strong&gt;: Shorter ramp-up with frameworks, longer ramp-up but stronger foundations with native.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;4️⃣ Team Collaboration &amp;amp; Scaling&lt;/strong&gt;
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Native Codebases&lt;/th&gt;
&lt;th&gt;Framework-Based Projects&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Collaboration Clarity&lt;/td&gt;
&lt;td&gt;Enforced by strict typing&lt;/td&gt;
&lt;td&gt;Often depends on discipline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tooling Standardization&lt;/td&gt;
&lt;td&gt;Fragmented by OS, compiler&lt;/td&gt;
&lt;td&gt;Mostly unified via NPM/Pip/etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code Reviews&lt;/td&gt;
&lt;td&gt;Harder, but more precise&lt;/td&gt;
&lt;td&gt;Easier, but often surface-level&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scaling Dev Teams&lt;/td&gt;
&lt;td&gt;Better for core systems&lt;/td&gt;
&lt;td&gt;Better for fast-moving feature teams&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;💡 The bigger your team and codebase, the more you need &lt;strong&gt;structure&lt;/strong&gt;. Whether native or framework-based, introduce &lt;strong&gt;linting, testing, CI, and style guides early&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;5️⃣ Who Maintains What? DevOps &amp;amp; Tooling Support&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Native:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Often requires custom build environments
&lt;/li&gt;
&lt;li&gt;Monitoring, logging, deployment tools may be &lt;strong&gt;more manual&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;DevOps must know cross-compilation, packaging, and binary signing&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Framework:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Ready-to-go platforms: Vercel, Netlify, Heroku
&lt;/li&gt;
&lt;li&gt;One-click deploy pipelines
&lt;/li&gt;
&lt;li&gt;Simple Dockerization or serverless options
&lt;/li&gt;
&lt;li&gt;Easy integration with modern tools like Sentry, Datadog, Supabase, Firebase&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💡 Native is powerful for infra/OS teams. Frameworks are powerful for product teams.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;💡 Final Thoughts: It’s Not Just About the Code&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;✔ Developer experience &lt;strong&gt;affects team morale, velocity, and quality&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✔ Native stacks may need more setup, but they age well&lt;br&gt;&lt;br&gt;
✔ Frameworks let teams ship fast, but can become brittle without discipline&lt;br&gt;&lt;br&gt;
✔ Invest in &lt;strong&gt;documentation, conventions, automation, and CI/CD&lt;/strong&gt;—regardless of language&lt;/p&gt;

&lt;p&gt;💬 &lt;strong&gt;Your Thoughts?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Which part of team collaboration or long-term maintenance hits hardest in your projects? Let’s talk in the comments!&lt;/p&gt;




&lt;p&gt;Enjoying the content? If you'd like to support my work and keep the ideas flowing, consider buying me a coffee! Your support means the world to me!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/devcornercrew" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>developer</category>
      <category>devcorner</category>
      <category>coding</category>
      <category>learning</category>
    </item>
    <item>
      <title>Use Case Matchups: Native vs Framework by Project Type</title>
      <dc:creator>Matt Miller</dc:creator>
      <pubDate>Mon, 21 Apr 2025 08:40:00 +0000</pubDate>
      <link>https://dev.to/matemiller/use-case-matchups-native-vs-framework-by-project-type-1poa</link>
      <guid>https://dev.to/matemiller/use-case-matchups-native-vs-framework-by-project-type-1poa</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;There’s no single “best” tool for all jobs, but there are &lt;strong&gt;better tools for specific jobs&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fws5fesul5jnxx8pzmlwf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fws5fesul5jnxx8pzmlwf.jpg" alt="Image by Josh Sorenson from Pexels" width="640" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So instead of asking &lt;em&gt;"Should I go native or use a framework?"&lt;/em&gt;, a smarter question is:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;&lt;em&gt;"What am I building, and which approach fits that use case best?"&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this post, we’ll compare real-world project types—&lt;strong&gt;mobile apps, CLI tools, backends, embedded projects&lt;/strong&gt;, and more—and match them against the &lt;strong&gt;native vs framework&lt;/strong&gt; landscape.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;1️⃣ Mobile Apps&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  📱 Option A: &lt;strong&gt;Native (Swift for iOS / Kotlin for Android)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;✅ Full access to camera, sensors, Bluetooth, OS features&lt;br&gt;&lt;br&gt;
✅ Best performance&lt;br&gt;&lt;br&gt;
✅ Native UI = best look &amp;amp; feel&lt;br&gt;&lt;br&gt;
❌ Double the codebase (iOS + Android)&lt;br&gt;&lt;br&gt;
❌ Slower dev cycle  &lt;/p&gt;

&lt;h3&gt;
  
  
  🌐 Option B: &lt;strong&gt;Cross-Platform Frameworks (Flutter, React Native)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;✅ Write once, run everywhere&lt;br&gt;&lt;br&gt;
✅ Big ecosystem&lt;br&gt;&lt;br&gt;
✅ Faster MVPs, faster iteration&lt;br&gt;&lt;br&gt;
❌ May feel “non-native” in edge cases&lt;br&gt;&lt;br&gt;
❌ Slower access to new OS features  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔥 Verdict:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Use &lt;strong&gt;native&lt;/strong&gt; for long-term, high-performance apps.&lt;br&gt;&lt;br&gt;
Use &lt;strong&gt;frameworks&lt;/strong&gt; for MVPs, startups, or fast cross-platform delivery.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;2️⃣ CLI Tools&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🧱 Option A: &lt;strong&gt;Native (Rust, Go, C++)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;✅ Tiny, fast binaries&lt;br&gt;&lt;br&gt;
✅ No runtime or install dependencies&lt;br&gt;&lt;br&gt;
✅ Runs on almost anything (great for DevOps)&lt;br&gt;&lt;br&gt;
❌ Slightly steeper learning curve&lt;br&gt;&lt;br&gt;
❌ Less dynamic UX  &lt;/p&gt;

&lt;h3&gt;
  
  
  ⚙️ Option B: &lt;strong&gt;Frameworks (Node.js + oclif / Python + Click)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;✅ Easy to write&lt;br&gt;&lt;br&gt;
✅ Faster prototyping&lt;br&gt;&lt;br&gt;
✅ Tons of NPM/PyPI packages available&lt;br&gt;&lt;br&gt;
❌ Slower runtime&lt;br&gt;&lt;br&gt;
❌ Requires interpreter or runtime installed  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔥 Verdict:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Use &lt;strong&gt;native&lt;/strong&gt; when performance or distribution matters.&lt;br&gt;&lt;br&gt;
Use &lt;strong&gt;frameworks&lt;/strong&gt; for internal scripts, tools, or one-off automation.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;3️⃣ Backend APIs &amp;amp; Microservices&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ⚡ Option A: &lt;strong&gt;Native (Go, Rust, Java)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;✅ High-performance, great concurrency&lt;br&gt;&lt;br&gt;
✅ Lightweight microservices&lt;br&gt;&lt;br&gt;
✅ Ideal for large-scale backends&lt;br&gt;&lt;br&gt;
❌ More verbose to build&lt;br&gt;&lt;br&gt;
❌ Harder to iterate quickly  &lt;/p&gt;

&lt;h3&gt;
  
  
  🧩 Option B: &lt;strong&gt;Frameworks (Express, FastAPI, Laravel, NestJS)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;✅ Rapid development&lt;br&gt;&lt;br&gt;
✅ Built-in auth, routing, ORM&lt;br&gt;&lt;br&gt;
✅ Great DX&lt;br&gt;&lt;br&gt;
❌ May not scale as efficiently&lt;br&gt;&lt;br&gt;
❌ Higher memory usage  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔥 Verdict:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Use &lt;strong&gt;native&lt;/strong&gt; for performance-critical APIs or infra tools.&lt;br&gt;&lt;br&gt;
Use &lt;strong&gt;frameworks&lt;/strong&gt; for most web apps, admin dashboards, and MVPs.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;4️⃣ Embedded &amp;amp; IoT&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ⚙️ Option A: &lt;strong&gt;Native (C, C++, Rust)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;✅ Full hardware control&lt;br&gt;&lt;br&gt;
✅ Small binary sizes&lt;br&gt;&lt;br&gt;
✅ No overhead&lt;br&gt;&lt;br&gt;
❌ Manual memory management (except Rust)&lt;br&gt;&lt;br&gt;
❌ Long dev cycles  &lt;/p&gt;

&lt;h3&gt;
  
  
  🧠 Option B: &lt;strong&gt;Frameworks (MicroPython, Johnny-Five + JS)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;✅ Easy to get started&lt;br&gt;&lt;br&gt;
✅ Great for education, prototyping&lt;br&gt;&lt;br&gt;
❌ Limited in speed &amp;amp; precision&lt;br&gt;&lt;br&gt;
❌ Not suitable for production hardware  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔥 Verdict:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Native is the king&lt;/strong&gt; for embedded.&lt;br&gt;&lt;br&gt;
Frameworks = good for early experimentation or teaching.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;5️⃣ Desktop Apps&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  💻 Option A: &lt;strong&gt;Native (C++, Swift, Rust)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;✅ Best performance, native feel&lt;br&gt;&lt;br&gt;
✅ Full access to system APIs&lt;br&gt;&lt;br&gt;
✅ No browser dependency&lt;br&gt;&lt;br&gt;
❌ Platform-specific maintenance&lt;br&gt;&lt;br&gt;
❌ Slower development  &lt;/p&gt;

&lt;h3&gt;
  
  
  🌍 Option B: &lt;strong&gt;Frameworks (Electron, Tauri, Flutter)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;✅ One codebase = all platforms&lt;br&gt;&lt;br&gt;
✅ Leverages web tech&lt;br&gt;&lt;br&gt;
✅ Easy packaging and updates&lt;br&gt;&lt;br&gt;
❌ Electron = large binaries, RAM hungry&lt;br&gt;&lt;br&gt;
❌ UX trade-offs  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔥 Verdict:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Use &lt;strong&gt;native or Tauri&lt;/strong&gt; for lightweight, efficient tools.&lt;br&gt;&lt;br&gt;
Use &lt;strong&gt;Electron or Flutter&lt;/strong&gt; for fast delivery or cross-platform GUI apps.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;6️⃣ Web Frontends (Bonus)&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🧠 Option A: &lt;strong&gt;Vanilla JS/TS&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;✅ Smallest bundle&lt;br&gt;&lt;br&gt;
✅ No dependency bloat&lt;br&gt;&lt;br&gt;
✅ Full control&lt;br&gt;&lt;br&gt;
❌ Slower to build from scratch&lt;br&gt;&lt;br&gt;
❌ More setup, more manual wiring  &lt;/p&gt;

&lt;h3&gt;
  
  
  ⚙️ Option B: &lt;strong&gt;Frameworks (React, Svelte, Vue, etc.)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;✅ Component systems, routers, state mgmt&lt;br&gt;&lt;br&gt;
✅ Huge ecosystems&lt;br&gt;&lt;br&gt;
✅ Best for teams&lt;br&gt;&lt;br&gt;
❌ Abstraction overhead&lt;br&gt;&lt;br&gt;
❌ Bigger bundles by default  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔥 Verdict:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Use &lt;strong&gt;vanilla&lt;/strong&gt; for small/static projects or learning.&lt;br&gt;&lt;br&gt;
Use &lt;strong&gt;frameworks&lt;/strong&gt; for anything interactive, team-based, or scale-ready.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 Final Thoughts: Choose Based on Fit, Not Hype
&lt;/h2&gt;

&lt;p&gt;✔ &lt;strong&gt;Frameworks are great for speed, flexibility, and starting fast&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✔ &lt;strong&gt;Native is unbeatable when you need control, speed, and precision&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✔ Always ask: &lt;em&gt;"What am I building? Who’s using it? How will it grow?"&lt;/em&gt;  &lt;/p&gt;

&lt;p&gt;💬 &lt;strong&gt;Your Thoughts?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Have you ever picked the wrong tech for a project? What’s your favorite use-case combo? Let’s chat in the comments!  &lt;/p&gt;




&lt;p&gt;Enjoying the content? If you'd like to support my work and keep the ideas flowing, consider buying me a coffee! Your support means the world to me!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/devcornercrew" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>developer</category>
      <category>devcorner</category>
      <category>coding</category>
      <category>learning</category>
    </item>
    <item>
      <title>The Framework Appeal: Abstraction, Speed &amp; Dev Experience</title>
      <dc:creator>Matt Miller</dc:creator>
      <pubDate>Fri, 18 Apr 2025 08:40:00 +0000</pubDate>
      <link>https://dev.to/matemiller/the-framework-appeal-abstraction-speed-dev-experience-kmb</link>
      <guid>https://dev.to/matemiller/the-framework-appeal-abstraction-speed-dev-experience-kmb</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;While native languages give you raw power, &lt;strong&gt;frameworks are built for momentum&lt;/strong&gt;. They abstract away the low-level stuff and let you ship faster, focus on features, and avoid reinventing the wheel.  &lt;/p&gt;

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

&lt;p&gt;But what's the real cost of using a framework?&lt;br&gt;&lt;br&gt;
Are you trading control for convenience? Speed for productivity?&lt;br&gt;&lt;br&gt;
Let’s unpack the real reasons devs love frameworks—and the hidden trade-offs you may not realize until later.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;1️⃣ Why Developers (Still) Love Frameworks&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ✅ Rapid Development
&lt;/h3&gt;

&lt;p&gt;Frameworks let you:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spin up projects in minutes
&lt;/li&gt;
&lt;li&gt;Skip boilerplate
&lt;/li&gt;
&lt;li&gt;Get to &lt;strong&gt;"business logic"&lt;/strong&gt; faster&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹 &lt;strong&gt;React&lt;/strong&gt;, &lt;strong&gt;Vue&lt;/strong&gt;, &lt;strong&gt;Svelte&lt;/strong&gt; → Handle UI state, routing, rendering&lt;br&gt;&lt;br&gt;
🔹 &lt;strong&gt;Django&lt;/strong&gt;, &lt;strong&gt;Rails&lt;/strong&gt;, &lt;strong&gt;Laravel&lt;/strong&gt; → Give you ORM, auth, migrations, templating out of the box&lt;br&gt;&lt;br&gt;
🔹 &lt;strong&gt;NestJS&lt;/strong&gt;, &lt;strong&gt;FastAPI&lt;/strong&gt;, &lt;strong&gt;Spring Boot&lt;/strong&gt; → Offer structure + flexibility in backend systems&lt;/p&gt;




&lt;h3&gt;
  
  
  ✅ Developer Experience (DX)
&lt;/h3&gt;

&lt;p&gt;Frameworks often come with:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dev servers with hot reload
&lt;/li&gt;
&lt;li&gt;CLI tools and generators
&lt;/li&gt;
&lt;li&gt;Convention-based routing
&lt;/li&gt;
&lt;li&gt;Built-in testing, linting, bundling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💡 These things &lt;strong&gt;don’t make your app better&lt;/strong&gt;, but they &lt;strong&gt;make your dev life better&lt;/strong&gt;—especially in a team.&lt;/p&gt;




&lt;h3&gt;
  
  
  ✅ Community &amp;amp; Ecosystem
&lt;/h3&gt;

&lt;p&gt;Popular frameworks have:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tons of libraries and plugins
&lt;/li&gt;
&lt;li&gt;Rich documentation and examples
&lt;/li&gt;
&lt;li&gt;Answers on Stack Overflow
&lt;/li&gt;
&lt;li&gt;Community support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹 React + Tailwind + Next.js? You’ll find a tutorial for that.&lt;br&gt;&lt;br&gt;
🔹 Django + Celery + Redis? There’s a whole ecosystem around it.&lt;/p&gt;

&lt;p&gt;📌 &lt;strong&gt;The more popular the framework, the faster you can solve problems&lt;/strong&gt;—without having to become an expert in every subsystem.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;2️⃣ The Real Cost of Frameworks&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ❌ Abstraction = Blind Spots
&lt;/h3&gt;

&lt;p&gt;The more a framework does for you, the &lt;strong&gt;less you understand about what’s actually happening&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;📌 You might know how to use &lt;code&gt;.map()&lt;/code&gt; in React, but not how the &lt;strong&gt;virtual DOM diffing works&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
📌 You might deploy with Django’s ORM, but never learn &lt;strong&gt;how SQL joins really behave&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This makes debugging harder—especially when something breaks &lt;strong&gt;outside the happy path&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  ❌ Performance Overhead
&lt;/h3&gt;

&lt;p&gt;Frameworks add layers—routing, component trees, reflection, decorators…&lt;br&gt;&lt;br&gt;
This can lead to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Slower boot times
&lt;/li&gt;
&lt;li&gt;Larger bundles
&lt;/li&gt;
&lt;li&gt;Memory bloat
&lt;/li&gt;
&lt;li&gt;Event handler sprawl
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹 Example: React apps with 50+ components and 1MB+ of JavaScript before rendering anything.&lt;/p&gt;

&lt;p&gt;📌 Native apps and minimal libraries usually outperform bloated framework stacks.&lt;/p&gt;




&lt;h3&gt;
  
  
  ❌ Dependency Hell &amp;amp; Framework Lock-In
&lt;/h3&gt;

&lt;p&gt;The more you depend on framework-specific tools:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The harder it is to migrate away
&lt;/li&gt;
&lt;li&gt;The more painful updates become
&lt;/li&gt;
&lt;li&gt;The more you have to trust &lt;strong&gt;third-party maintainers&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💥 One breaking change or deprecated package can cost hours (or days) of rework.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;3️⃣ Frameworks Shine in the Right Context&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let’s be fair—frameworks aren’t bad. They just need to fit the &lt;strong&gt;project size, team experience, and long-term goals&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔹 Great Use Cases for Frameworks:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;MVPs and prototyping
&lt;/li&gt;
&lt;li&gt;SaaS dashboards and admin panels
&lt;/li&gt;
&lt;li&gt;Internal tools
&lt;/li&gt;
&lt;li&gt;Rapid iteration with small teams&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🔸 When to Be Cautious:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Low-level performance needs (e.g., game dev, real-time tools)
&lt;/li&gt;
&lt;li&gt;Complex edge cases where framework abstractions fight your logic
&lt;/li&gt;
&lt;li&gt;Large-scale projects with long lifespans and multiple teams&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;4️⃣ Frameworks Keep Evolving&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Frameworks aren’t static—many are trying to &lt;strong&gt;reduce their own complexity&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Modern trends:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Svelte&lt;/strong&gt; → compiles away at build time
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Qwik&lt;/strong&gt; → resumes instead of rehydrating
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTMX&lt;/strong&gt; → goes back to basics with HTML-over-the-wire
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fresh (Deno)&lt;/strong&gt; and &lt;strong&gt;SolidJS&lt;/strong&gt; → prioritize minimalism and DX&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📌 The ecosystem is responding to its own bloat—and trying to bring us closer to the metal again.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;💡 Final Thoughts: Frameworks Are Power Tools—Use Them Wisely&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;✔ Frameworks are amazing for &lt;strong&gt;speed, productivity, and collaboration&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✔ But they come with &lt;strong&gt;abstraction, overhead, and long-term baggage&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✔ Know &lt;strong&gt;what’s under the hood&lt;/strong&gt;, so you’re not helpless when things break&lt;br&gt;&lt;br&gt;
✔ Choose frameworks that &lt;strong&gt;fit the project&lt;/strong&gt;, not just the hype&lt;/p&gt;

&lt;p&gt;💬 &lt;strong&gt;Your Thoughts?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
What’s your go-to framework? Have you ever hit the limits of one and regretted it? Let’s share war stories in the comments!  &lt;/p&gt;




&lt;p&gt;Enjoying the content? If you'd like to support my work and keep the ideas flowing, consider buying me a coffee! Your support means the world to me!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/devcornercrew" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>developer</category>
      <category>coding</category>
      <category>learning</category>
      <category>devcorner</category>
    </item>
    <item>
      <title>From C to Rust to Go: What Native Really Offers Today</title>
      <dc:creator>Matt Miller</dc:creator>
      <pubDate>Thu, 17 Apr 2025 08:50:00 +0000</pubDate>
      <link>https://dev.to/matemiller/from-c-to-rust-to-go-what-native-really-offers-today-1c79</link>
      <guid>https://dev.to/matemiller/from-c-to-rust-to-go-what-native-really-offers-today-1c79</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In the age of frameworks and abstraction, native programming languages might feel like a thing of the past. But truth is—languages like &lt;strong&gt;C, Rust, and Go&lt;/strong&gt; are still powering the core of everything: operating systems, browsers, servers, devices, and now even some parts of the web.&lt;/p&gt;

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

&lt;p&gt;So, when should you reach for native languages instead of JavaScript frameworks, Python backends, or Flutter UIs?&lt;/p&gt;

&lt;p&gt;Let’s explore the &lt;strong&gt;raw power&lt;/strong&gt;, &lt;strong&gt;use cases&lt;/strong&gt;, and &lt;strong&gt;reasons to go native&lt;/strong&gt;, even in 2025.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;1️⃣ What Do We Mean by “Native Languages”?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this context, we're talking about &lt;strong&gt;compiled, low-level, system-access-capable&lt;/strong&gt; languages, like:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;C&lt;/strong&gt; / &lt;strong&gt;C++&lt;/strong&gt; – Classic, close-to-the-metal
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rust&lt;/strong&gt; – Memory-safe, modern alternative to C
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go&lt;/strong&gt; – Fast compile times, simplicity, built for concurrency
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zig&lt;/strong&gt;, &lt;strong&gt;Assembly&lt;/strong&gt;, &lt;strong&gt;Nim&lt;/strong&gt;, etc. – also in the native league&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These languages produce &lt;strong&gt;machine-level binaries&lt;/strong&gt;, not interpreted scripts. They’re used where &lt;strong&gt;performance and control matter most&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;2️⃣ Why Go Native? The Case for Full Control&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🔥 &lt;strong&gt;Raw Speed&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Native languages compile to machine code, resulting in:&lt;br&gt;&lt;br&gt;
✔ Faster execution&lt;br&gt;&lt;br&gt;
✔ Lower memory overhead&lt;br&gt;&lt;br&gt;
✔ Fine-grained performance tuning  &lt;/p&gt;

&lt;p&gt;Use case: Game engines, crypto tools, video processing, embedded firmware  &lt;/p&gt;




&lt;h3&gt;
  
  
  🧠 &lt;strong&gt;System-Level Access&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Want to:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hook into system APIs?
&lt;/li&gt;
&lt;li&gt;Write a kernel module?
&lt;/li&gt;
&lt;li&gt;Access peripherals directly?
Native is the way.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use case: Device drivers, OS development, hardware controllers&lt;/p&gt;




&lt;h3&gt;
  
  
  🛡 &lt;strong&gt;Security &amp;amp; Memory Management&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;✅ &lt;strong&gt;Rust&lt;/strong&gt; in particular is gaining popularity for offering both:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Memory safety (no segfaults, no garbage collector)
&lt;/li&gt;
&lt;li&gt;Blazing-fast performance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💡 Even Microsoft and Google are rewriting some components in &lt;strong&gt;Rust&lt;/strong&gt; for security reasons.&lt;/p&gt;




&lt;h3&gt;
  
  
  🧰 &lt;strong&gt;Tiny Footprints&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;C and Go binaries can be tiny (&amp;lt;1MB)
&lt;/li&gt;
&lt;li&gt;No bloated runtimes or node_modules folders
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Perfect for:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Embedded devices
&lt;/li&gt;
&lt;li&gt;IoT hardware
&lt;/li&gt;
&lt;li&gt;CLI tools and system daemons
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;3️⃣ Where Native Still Dominates&lt;/strong&gt;
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Domain&lt;/th&gt;
&lt;th&gt;Why Native Wins&lt;/th&gt;
&lt;th&gt;Popular Languages&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Operating Systems&lt;/td&gt;
&lt;td&gt;Full system control, drivers&lt;/td&gt;
&lt;td&gt;C, C++, Rust&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Game Development&lt;/td&gt;
&lt;td&gt;Real-time graphics, physics engines&lt;/td&gt;
&lt;td&gt;C++, Rust&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Embedded Systems&lt;/td&gt;
&lt;td&gt;Tight memory, hardware interaction&lt;/td&gt;
&lt;td&gt;C, Rust, Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blockchain / Crypto&lt;/td&gt;
&lt;td&gt;Security, performance, portability&lt;/td&gt;
&lt;td&gt;Rust, Go, C++&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Browsers / Compilers&lt;/td&gt;
&lt;td&gt;Complex, high-performance internals&lt;/td&gt;
&lt;td&gt;C++, Rust&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;📌 Even modern tools like &lt;strong&gt;Chrome, Firefox, Docker, and Kubernetes&lt;/strong&gt; are written (at least partly) in native languages.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;4️⃣ But Native Has Its Downsides…&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let’s be honest—it’s not all roses.&lt;/p&gt;

&lt;h3&gt;
  
  
  ❌ Slower Development
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Boilerplate code
&lt;/li&gt;
&lt;li&gt;Verbose syntax
&lt;/li&gt;
&lt;li&gt;Longer setup &amp;amp; learning curve&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ Memory Management Pain (C/C++)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Manual allocation/deallocation
&lt;/li&gt;
&lt;li&gt;Potential for segmentation faults, leaks, buffer overflows&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ Less Accessible to Beginners
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Steeper learning curve
&lt;/li&gt;
&lt;li&gt;Less forgiving of mistakes
&lt;/li&gt;
&lt;li&gt;Not always beginner-friendly tooling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💡 Tools like &lt;strong&gt;Rust&lt;/strong&gt; and &lt;strong&gt;Go&lt;/strong&gt; aim to fix this—but they still require more upfront discipline than modern frameworks.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;5️⃣ Where Native Is Making a Comeback&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Modern developers are blending native languages with higher-level stacks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rust + React&lt;/strong&gt; → Native-powered backend with a slick frontend
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go + REST/gRPC&lt;/strong&gt; → Super-performant microservices
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tauri (Rust) + Svelte/React&lt;/strong&gt; → Electron alternative with tiny binaries
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WASM (WebAssembly)&lt;/strong&gt; → Run native modules in the browser!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📌 You can write your “core logic” in a native language and expose it via a web or mobile UI.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;💡 Final Thoughts: Native Is Still Relevant—And Powerful&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;✔ Native isn’t dead. It’s just matured.&lt;br&gt;&lt;br&gt;
✔ It’s not always the fastest to build—but it’s often the &lt;strong&gt;fastest to run&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
✔ If performance, control, or safety matters, go native.&lt;br&gt;&lt;br&gt;
✔ And thanks to &lt;strong&gt;WASM&lt;/strong&gt;, &lt;strong&gt;Tauri&lt;/strong&gt;, and modern toolchains—you don’t have to choose one or the other.&lt;/p&gt;

&lt;p&gt;💬 &lt;strong&gt;Your Thoughts?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Are you using a native language in your stack? Or are you curious but hesitant to dive in? Let’s talk about it in the comments!  &lt;/p&gt;




&lt;p&gt;Enjoying the content? If you'd like to support my work and keep the ideas flowing, consider buying me a coffee! Your support means the world to me!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/devcornercrew" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>developer</category>
      <category>coding</category>
      <category>devcorner</category>
      <category>learning</category>
    </item>
    <item>
      <title>When Web Meets Hardware: USB, Serial, and the New Web Frontier</title>
      <dc:creator>Matt Miller</dc:creator>
      <pubDate>Wed, 16 Apr 2025 13:15:00 +0000</pubDate>
      <link>https://dev.to/matemiller/when-web-meets-hardware-usb-serial-and-the-new-web-frontier-bnf</link>
      <guid>https://dev.to/matemiller/when-web-meets-hardware-usb-serial-and-the-new-web-frontier-bnf</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;For years, browsers were walled gardens—great for viewing, interacting, and typing into forms, but &lt;strong&gt;completely isolated from your system hardware&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2gpgovps1cbzj01x5716.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2gpgovps1cbzj01x5716.jpg" alt="Image by Tima Miroshnichenko from Pexels" width="640" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But now, modern browser APIs like &lt;strong&gt;WebUSB&lt;/strong&gt; and &lt;strong&gt;Web Serial&lt;/strong&gt; are breaking those walls down.&lt;br&gt;&lt;br&gt;
The result? The &lt;strong&gt;web can talk to physical devices&lt;/strong&gt;, flash firmware, debug microcontrollers, and even run &lt;strong&gt;remote repair services&lt;/strong&gt;—no desktop app needed.&lt;/p&gt;

&lt;p&gt;Let’s explore how this tech is changing what's possible with web apps—and what it means for tools like &lt;strong&gt;NeedROM&lt;/strong&gt;, &lt;strong&gt;Arduino&lt;/strong&gt;, and more.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;1️⃣ WebUSB: The Browser Gets Its Hands Dirty&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What It Does:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
WebUSB gives JavaScript in your browser the ability to talk to USB devices directly.  &lt;/p&gt;

&lt;p&gt;✅ Read and write to devices&lt;br&gt;&lt;br&gt;
✅ Flash firmware&lt;br&gt;&lt;br&gt;
✅ Send commands, update configs&lt;br&gt;&lt;br&gt;
✅ Fully user-permissioned  &lt;/p&gt;

&lt;h3&gt;
  
  
  🧠 Use Cases:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GrapheneOS Web Installer&lt;/strong&gt;
A full &lt;strong&gt;OS installer for Android phones&lt;/strong&gt;, right from the browser—no command line, no external tools
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;3D printer firmware utilities&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Device management dashboards&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Custom USB tools for embedded engineers&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔗 &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WebUSB_API" rel="noopener noreferrer"&gt;WebUSB on MDN&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;💡 This turns any website into a &lt;strong&gt;platform-specific configuration utility&lt;/strong&gt;. Imagine flashing a router or dev board—&lt;strong&gt;without leaving Chrome&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;2️⃣ Web Serial: Serial Ports, No Terminal Needed&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What It Does:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Web Serial lets a web app open a serial connection (e.g., COM ports, UART, USB-to-Serial converters) and read/write just like PuTTY or Minicom.  &lt;/p&gt;

&lt;p&gt;✅ Log data from microcontrollers&lt;br&gt;&lt;br&gt;
✅ Send CLI-style commands to connected devices&lt;br&gt;&lt;br&gt;
✅ Create serial monitors in the browser&lt;br&gt;&lt;br&gt;
✅ Replaces native terminal tools in many workflows  &lt;/p&gt;

&lt;h3&gt;
  
  
  🧪 Use Cases:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Arduino and ESP-based devices
&lt;/li&gt;
&lt;li&gt;Debugging 3D printers or IoT hardware
&lt;/li&gt;
&lt;li&gt;Bootloader communication
&lt;/li&gt;
&lt;li&gt;Teaching embedded programming—&lt;strong&gt;in-browser!&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔗 &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Serial_API" rel="noopener noreferrer"&gt;Web Serial on MDN&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;💡 The web becomes a &lt;strong&gt;live console&lt;/strong&gt;, perfect for labs, education, and dev tooling.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;3️⃣ The End of "Download This Tool First"&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Think about sites like:&lt;/p&gt;

&lt;p&gt;🔧 &lt;strong&gt;NeedROM.com&lt;/strong&gt; – Offers custom Android firmware&lt;br&gt;&lt;br&gt;
🧩 &lt;strong&gt;Router/modem forums&lt;/strong&gt; – Share flash tools and updates&lt;br&gt;&lt;br&gt;
🖨 &lt;strong&gt;3D printer communities&lt;/strong&gt; – Offer slicers, firmware, config utilities  &lt;/p&gt;

&lt;p&gt;The current flow:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download a ZIP
&lt;/li&gt;
&lt;li&gt;Install custom drivers
&lt;/li&gt;
&lt;li&gt;Run some Windows-only .exe
&lt;/li&gt;
&lt;li&gt;Hope it works on your machine
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  🛠 The Future Flow (with WebUSB):
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open a web page
&lt;/li&gt;
&lt;li&gt;Plug in your device
&lt;/li&gt;
&lt;li&gt;Grant browser permission
&lt;/li&gt;
&lt;li&gt;Flash, configure, done. No drivers. No installs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;💥 With these APIs, the browser becomes a universal installer, debugger, and controller.  &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;4️⃣ Developer Experience: The Stack Behind the Magic&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;✅ WebUSB / Web Serial APIs — Supported in Chrome, Edge, and Chromium-based browsers&lt;br&gt;&lt;br&gt;
✅ JavaScript or TypeScript frontend&lt;br&gt;&lt;br&gt;
✅ Optionally paired with &lt;strong&gt;WebAssembly&lt;/strong&gt; for fast parsing/processing&lt;br&gt;&lt;br&gt;
✅ Can use &lt;strong&gt;Service Workers&lt;/strong&gt; to support offline functionality  &lt;/p&gt;

&lt;h3&gt;
  
  
  💡 Bonus: Pair With WebRTC
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Combine Web Serial with &lt;strong&gt;remote support&lt;/strong&gt; via video + data sharing
&lt;/li&gt;
&lt;li&gt;Offer &lt;strong&gt;"live unbricking" help&lt;/strong&gt; in real time via web tools
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;5️⃣ Limitations &amp;amp; Security Considerations&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;🧱 &lt;strong&gt;Limitations:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not supported in Firefox/Safari (yet)
&lt;/li&gt;
&lt;li&gt;Requires HTTPS (secure origin)
&lt;/li&gt;
&lt;li&gt;Device compatibility must be implemented per vendor
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🛡 &lt;strong&gt;Security:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All access requires explicit user permission
&lt;/li&gt;
&lt;li&gt;Can only interact with allowed devices
&lt;/li&gt;
&lt;li&gt;Great sandboxing compared to native tools&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💡 Still, this is &lt;strong&gt;serious access&lt;/strong&gt;—devs should treat it with the same care as native apps.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;💡 Final Thoughts: Browsers as the New OS for Hardware Tools&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;✔ The web is no longer limited to forms and files&lt;br&gt;&lt;br&gt;
✔ With WebUSB and Web Serial, it’s now a platform for:&lt;br&gt;&lt;br&gt;
→ Device repair&lt;br&gt;&lt;br&gt;
→ Firmware flashing&lt;br&gt;&lt;br&gt;
→ Debugging&lt;br&gt;&lt;br&gt;
→ Hardware education&lt;br&gt;&lt;br&gt;
→ Secure remote support  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Download this tool"&lt;/strong&gt; may soon become &lt;strong&gt;"Open this URL."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;💬 &lt;strong&gt;Your Thoughts?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Have you used any browser-based hardware tools? What would you love to see built with this tech? Let’s chat in the comments!  &lt;/p&gt;




&lt;p&gt;Enjoying the content? If you'd like to support my work and keep the ideas flowing, consider buying me a coffee! Your support means the world to me!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/devcornercrew" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>developer</category>
      <category>coding</category>
      <category>learning</category>
      <category>devcorner</category>
    </item>
    <item>
      <title>Distribution &amp; Dev Workflow: Shipping Software vs Deploying the Web</title>
      <dc:creator>Matt Miller</dc:creator>
      <pubDate>Tue, 15 Apr 2025 13:15:00 +0000</pubDate>
      <link>https://dev.to/matemiller/distribution-dev-workflow-shipping-software-vs-deploying-the-web-2h1d</link>
      <guid>https://dev.to/matemiller/distribution-dev-workflow-shipping-software-vs-deploying-the-web-2h1d</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Building an app is only half the battle—the other half is getting it into users’ hands.  &lt;/p&gt;

&lt;p&gt;Traditional software requires packaging, distribution, and updates. Web apps? You just hit &lt;strong&gt;“deploy”&lt;/strong&gt;, and it’s live for everyone. Sounds like a dream, right?  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4oye3fknztl6c2kzov0h.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4oye3fknztl6c2kzov0h.jpg" alt="Image by Yan Krukau from Pexels" width="640" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s dive into how &lt;strong&gt;software shipping&lt;/strong&gt; compares to &lt;strong&gt;web deployment&lt;/strong&gt;, and why each has its own set of &lt;strong&gt;challenges, benefits, and hidden stress points&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;1️⃣ Shipping Native Software: A Developer’s Checkpoint Hell&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Before a user ever launches a native app, you have to:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build binaries for &lt;strong&gt;multiple OSes (Windows, macOS, Linux)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Package dependencies and installers
&lt;/li&gt;
&lt;li&gt;Sign code with trusted certificates
&lt;/li&gt;
&lt;li&gt;Test across environments
&lt;/li&gt;
&lt;li&gt;Publish to app stores or release platforms
&lt;/li&gt;
&lt;li&gt;Handle &lt;strong&gt;manual updates&lt;/strong&gt;, patches, and version rollbacks&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🧱 Pros:
&lt;/h3&gt;

&lt;p&gt;✔ Works offline&lt;br&gt;&lt;br&gt;
✔ Greater control over system-level resources&lt;br&gt;&lt;br&gt;
✔ No dependency on a browser&lt;/p&gt;
&lt;h3&gt;
  
  
  ❌ Cons:
&lt;/h3&gt;

&lt;p&gt;❌ Slower iteration cycles&lt;br&gt;&lt;br&gt;
❌ High friction updates (especially if users disable auto-update)&lt;br&gt;&lt;br&gt;
❌ Difficult to hotfix once shipped&lt;br&gt;&lt;br&gt;
❌ OS-specific bugs and compatibility issues  &lt;/p&gt;

&lt;p&gt;💡 Native apps feel “finished” when shipped—&lt;strong&gt;which also means more risk if something breaks.&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;2️⃣ Deploying Web Apps: CI/CD Heaven (or Chaos)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Web development shifted everything left. Now, pushing an update is as simple as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"fix: spacing bug"&lt;/span&gt;  
git push  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;…and if you have CI/CD set up:&lt;br&gt;&lt;br&gt;
🎉 It’s live.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔄 Web Deployment Workflow (Typical):
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Code pushed to main
&lt;/li&gt;
&lt;li&gt;CI pipeline runs tests, builds assets
&lt;/li&gt;
&lt;li&gt;Auto-deploy to staging/production
&lt;/li&gt;
&lt;li&gt;Changes reflect &lt;strong&gt;instantly&lt;/strong&gt; (or within minutes)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🟢 Pros:
&lt;/h3&gt;

&lt;p&gt;✔ Ship features quickly&lt;br&gt;&lt;br&gt;
✔ Fix bugs without user intervention&lt;br&gt;&lt;br&gt;
✔ A/B test and roll back in real-time&lt;br&gt;&lt;br&gt;
✔ Platform-agnostic—one deployment for all users&lt;/p&gt;

&lt;h3&gt;
  
  
  🔴 Cons:
&lt;/h3&gt;

&lt;p&gt;❌ Instant = risky if untested&lt;br&gt;&lt;br&gt;
❌ Breaking changes affect &lt;em&gt;everyone&lt;/em&gt;, all at once&lt;br&gt;&lt;br&gt;
❌ Requires strong CI/CD discipline&lt;br&gt;&lt;br&gt;
❌ Browser cache issues can delay updates&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;Summary:&lt;/strong&gt; Web deploys are fast—but demand confidence, automation, and rollback plans.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;3️⃣ Update Philosophy: Versioning vs Streaming&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🖥️ Native Apps
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Traditional versioning (v1.0.1, v1.1, etc.)&lt;/li&gt;
&lt;li&gt;Users manually download or auto-update&lt;/li&gt;
&lt;li&gt;Backward compatibility is crucial&lt;/li&gt;
&lt;li&gt;Apps may live on for &lt;strong&gt;years&lt;/strong&gt; without being updated&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🌍 Web Apps
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Continuous delivery—often no visible version
&lt;/li&gt;
&lt;li&gt;Small updates shipped daily or weekly
&lt;/li&gt;
&lt;li&gt;Users always on the &lt;strong&gt;latest build&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Easy to A/B test different UI flows or feature toggles
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📌 &lt;strong&gt;Dev takeaway:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Web is great for &lt;strong&gt;iteration&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Software needs to be &lt;strong&gt;rock solid&lt;/strong&gt; before shipping&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;4️⃣ Shipping Tools: Software vs Web DevOps Stack&lt;/strong&gt;
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Native Stack&lt;/th&gt;
&lt;th&gt;Web Stack&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Building&lt;/td&gt;
&lt;td&gt;Make/CMake, MSBuild, Xcode&lt;/td&gt;
&lt;td&gt;Webpack, Vite, esbuild&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Testing&lt;/td&gt;
&lt;td&gt;XCTest, Google Test, NUnit&lt;/td&gt;
&lt;td&gt;Vitest, Jest, Cypress, Playwright&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Packaging&lt;/td&gt;
&lt;td&gt;NSIS, Inno Setup, Electron Builder&lt;/td&gt;
&lt;td&gt;Vercel, Netlify, Docker (for APIs)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deployment&lt;/td&gt;
&lt;td&gt;App Stores, GitHub Releases&lt;/td&gt;
&lt;td&gt;CI/CD: GitHub Actions, GitLab, Vercel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rollbacks&lt;/td&gt;
&lt;td&gt;Manual (revert &amp;amp; release again)&lt;/td&gt;
&lt;td&gt;Instant (revert commit or redeploy)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;💡 Native apps often require &lt;strong&gt;heavier infrastructure&lt;/strong&gt; and more &lt;strong&gt;platform-specific tooling&lt;/strong&gt;. Web thrives on &lt;strong&gt;automation and cloud-first tooling&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;5️⃣ Team Workflow Differences&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Native Teams:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;QA, Dev, Release, Ops often &lt;strong&gt;separated&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Feature cycles take &lt;strong&gt;weeks to months&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Releases are &lt;strong&gt;rare and coordinated&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Web Teams:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;More agile and iterative
&lt;/li&gt;
&lt;li&gt;Developers often own the full delivery pipeline
&lt;/li&gt;
&lt;li&gt;Releases happen &lt;strong&gt;daily or even multiple times per day&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💡 In web, &lt;strong&gt;"move fast and fix things"&lt;/strong&gt; is the norm. In software, it’s &lt;strong&gt;"measure twice, ship once."&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;💡 Final Thoughts: Pick Your Pipeline Wisely&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;✔ Web makes &lt;strong&gt;shipping faster&lt;/strong&gt;, but demands tighter feedback loops and CI/CD discipline&lt;br&gt;&lt;br&gt;
✔ Native software gives you &lt;strong&gt;more control&lt;/strong&gt;, but slows down iteration&lt;br&gt;&lt;br&gt;
✔ In both cases, delivery is a key part of product success—not just an afterthought  &lt;/p&gt;

&lt;p&gt;💬 &lt;strong&gt;Your Thoughts?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
What’s your preferred workflow: versioned, packaged software—or fast, continuous deployment? Let’s chat in the comments!  &lt;/p&gt;




&lt;p&gt;Enjoying the content? If you'd like to support my work and keep the ideas flowing, consider buying me a coffee! Your support means the world to me!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/devcornercrew" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>developer</category>
      <category>devcorner</category>
      <category>coding</category>
      <category>learning</category>
    </item>
  </channel>
</rss>
