<?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: Nova Lumen Labs</title>
    <description>The latest articles on DEV Community by Nova Lumen Labs (@novalumenlabs).</description>
    <link>https://dev.to/novalumenlabs</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4238888%2Fddf635d5-6ebd-411d-abcd-6977a4d3a17f.jpg</url>
      <title>DEV Community: Nova Lumen Labs</title>
      <link>https://dev.to/novalumenlabs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/novalumenlabs"/>
    <language>en</language>
    <item>
      <title>What happens to your domains and cloud logins if you disappear? Building an encrypted vault for solo founders</title>
      <dc:creator>Nova Lumen Labs</dc:creator>
      <pubDate>Wed, 11 Nov 2026 10:57:00 +0000</pubDate>
      <link>https://dev.to/novalumenlabs/what-happens-to-your-domains-and-cloud-logins-if-you-disappear-building-an-encrypted-vault-for-2k7f</link>
      <guid>https://dev.to/novalumenlabs/what-happens-to-your-domains-and-cloud-logins-if-you-disappear-building-an-encrypted-vault-for-2k7f</guid>
      <description>&lt;p&gt;If you run a company alone, a lot of it lives in one head: the registrar login, the payment processor, the cloud account, the app store accounts. If something happens to you, nobody knows those exist, let alone how to get in. I built Heirloom: Founder Vault to deal with that, and this post covers the design choices.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;You record the important accounts and assets, and name up to 5 beneficiaries who get read-only access only when you can't respond. That's the whole idea. It's closer to a binder for your successors than a password manager.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stack
&lt;/h2&gt;

&lt;p&gt;React Native with Expo (no native folders checked in), WatermelonDB for local storage, Expo SecureStore and local authentication for biometrics, Supabase on the backend, RevenueCat for purchases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Encryption of exports
&lt;/h2&gt;

&lt;p&gt;For encrypted exports I use AES-256-GCM, which is authenticated encryption, so tampering is detected rather than silently decrypting to garbage. The key comes from your passphrase through PBKDF2-HMAC-SHA256 with 210,000 iterations (OWASP's 2023 guidance for that KDF) and a random 16-byte salt per export. The libraries are &lt;code&gt;@noble/ciphers&lt;/code&gt; and &lt;code&gt;@noble/hashes&lt;/code&gt;, which are audited and pure JS, so there's no native crypto module to maintain. The KDF parameters are stored beside the ciphertext so older exports stay readable if I raise the iteration count later.&lt;/p&gt;

&lt;h2&gt;
  
  
  The hard part is not crypto
&lt;/h2&gt;

&lt;p&gt;The hard question is the trigger: how do you decide someone really can't answer, without false alarms and without being gameable? The app is built around a regular check-in: you confirm you're fine, and access only opens when check-ins stop. I would not call the trigger design solved. I'd like opinions from people who have thought about dead-man's-switch design.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links (I'm the developer)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;iOS: &lt;a href="https://apps.apple.com/us/app/heirloom-founder-vault/id6779351428?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=heirloom_vault" rel="noopener noreferrer"&gt;https://apps.apple.com/us/app/heirloom-founder-vault/id6779351428?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=heirloom_vault&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Site: &lt;a href="https://lumenlabs.works/heirloom?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=heirloom_vault" rel="noopener noreferrer"&gt;https://lumenlabs.works/heirloom?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=heirloom_vault&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I used an AI assistant to help draft and edit this post; the technical details come from the app's source code.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>reactnative</category>
      <category>expo</category>
      <category>indiedev</category>
    </item>
    <item>
      <title>Building a document scanner where OCR never leaves the phone (VisionKit + Vision + PDFKit)</title>
      <dc:creator>Nova Lumen Labs</dc:creator>
      <pubDate>Wed, 11 Nov 2026 10:49:45 +0000</pubDate>
      <link>https://dev.to/novalumenlabs/building-a-document-scanner-where-ocr-never-leaves-the-phone-visionkit-vision-pdfkit-f63</link>
      <guid>https://dev.to/novalumenlabs/building-a-document-scanner-where-ocr-never-leaves-the-phone-visionkit-vision-pdfkit-f63</guid>
      <description>&lt;p&gt;Most free document scanners upload your pages to a server for text recognition. Passports, tax forms and receipts included. There's no technical need for that on a modern phone, so I built LumenScan as an experiment in doing all of it locally. This is how it's put together.&lt;/p&gt;

&lt;h2&gt;
  
  
  The stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Capture:&lt;/strong&gt; &lt;code&gt;VNDocumentCameraViewController&lt;/code&gt; from VisionKit, the same component Apple Notes uses. You get live edge detection, auto-capture, multi-page flow and a corner editor for free. I first wrote a custom AVFoundation camera, then dropped it as the main path; it now only runs on simulators or devices without Apple's scanner.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OCR:&lt;/strong&gt; the Vision framework's text recognition, on device. I set it up to cover English plus Hindi, Tamil and Telugu, since the first target market was India.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PDF:&lt;/strong&gt; PDFKit builds the output and handles annotation and signing. The recognized text is laid under the page image so the PDF is searchable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;History:&lt;/strong&gt; SwiftData.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Purchases:&lt;/strong&gt; RevenueCat, with prices read from StoreKit so the storefront currency shows correctly instead of being hard-coded.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Analytics without betraying the pitch
&lt;/h2&gt;

&lt;p&gt;If the pitch is that nothing leaves the phone, analytics has to be careful. I send only a fixed list of explicit event names, with no autocapture, no session replay, and never document content. The analytics SDK does nothing at all until a real key is configured.&lt;/p&gt;

&lt;h2&gt;
  
  
  One bug worth sharing
&lt;/h2&gt;

&lt;p&gt;Cancelling Apple's scanner sheet used to open my fallback camera right behind it, so users saw a second camera after backing out. The fix was to treat cancel as closing the whole scan flow. Obvious in hindsight; I only found it by using the app like a user rather than by reading code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Business model, honestly
&lt;/h2&gt;

&lt;p&gt;Free scans each day, with Pro for unlimited scans, Word export, password-protected PDFs and signing. There is a 7-day trial. Prices vary by storefront.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feedback wanted
&lt;/h2&gt;

&lt;p&gt;If you've shipped Vision OCR for non-Latin scripts, I'd like to compare notes on accuracy with low light and skewed pages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Links&lt;/strong&gt; (I'm the developer):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;iOS: &lt;a href="https://apps.apple.com/us/app/lumenscan-private-pdf-scanner/id6773876117?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=lumenscan_ondevice" rel="noopener noreferrer"&gt;https://apps.apple.com/us/app/lumenscan-private-pdf-scanner/id6773876117?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=lumenscan_ondevice&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Android: &lt;a href="https://play.google.com/store/apps/details?id=works.lumenlabs.lumenscan&amp;amp;utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=lumenscan_ondevice" rel="noopener noreferrer"&gt;https://play.google.com/store/apps/details?id=works.lumenlabs.lumenscan&amp;amp;utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=lumenscan_ondevice&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Site: &lt;a href="https://lumenlabs.works/lumenscan?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=lumenscan_ondevice" rel="noopener noreferrer"&gt;https://lumenlabs.works/lumenscan?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=lumenscan_ondevice&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I used an AI assistant to help draft and edit this post; the technical details come from the app's source code.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>swift</category>
      <category>privacy</category>
      <category>indiedev</category>
    </item>
    <item>
      <title>Why a plain FFT tuner locks onto the wrong note, and what I used instead (McLeod Pitch Method on iOS)</title>
      <dc:creator>Nova Lumen Labs</dc:creator>
      <pubDate>Wed, 11 Nov 2026 10:49:10 +0000</pubDate>
      <link>https://dev.to/novalumenlabs/why-a-plain-fft-tuner-locks-onto-the-wrong-note-and-what-i-used-instead-mcleod-pitch-method-on-18c2</link>
      <guid>https://dev.to/novalumenlabs/why-a-plain-fft-tuner-locks-onto-the-wrong-note-and-what-i-used-instead-mcleod-pitch-method-on-18c2</guid>
      <description>&lt;p&gt;I'm a solo developer at a small studio, and I recently shipped a guitar tuner and metronome called Maestro. The tuner was the part I got wrong first, so this post is about that.&lt;/p&gt;

&lt;h2&gt;
  
  
  The naive approach fails on real instruments
&lt;/h2&gt;

&lt;p&gt;The obvious way to build a tuner: take a window of microphone samples, run an FFT, pick the tallest peak, convert to a note. It works on a sine wave. On a real guitar it doesn't, because the loudest bin is often the 2nd or 3rd harmonic, not the fundamental. A low E (about 82 Hz) will happily read as the E an octave up, or as a B, depending on the pluck.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I used: the McLeod Pitch Method (MPM)
&lt;/h2&gt;

&lt;p&gt;MPM computes a normalized square-difference autocorrelation of the window. Instead of looking for the biggest peak in frequency space, it looks for repeating structure in time, and normalizes by signal energy at each lag so quiet tails don't lose to loud attacks. Then it picks the first strong peak, which is the fundamental, and refines it with parabolic interpolation for sub-sample precision (this is what gets you to a fraction of a cent).&lt;/p&gt;

&lt;p&gt;A few practical details from the implementation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Range: roughly 30 Hz to 2 kHz, so a 5-string bass low B and a violin's top register both fit. A 4096-frame buffer holds more than two periods at 30 Hz, which keeps the autocorrelation meaningful.&lt;/li&gt;
&lt;li&gt;Two gates before accepting a result: an RMS floor (so digital silence and room hiss don't run the expensive part) and a clarity threshold on the normalized peak height (I use 0.6) so breath noise doesn't show a phantom pitch.&lt;/li&gt;
&lt;li&gt;The heavy loops go through Accelerate's vDSP, so analysis fits inside one tap callback (about 93 ms of audio) even on older phones.&lt;/li&gt;
&lt;li&gt;The detector is a pure function: samples plus sample rate in, optional frequency plus clarity out. That made it easy to unit test against synthesized sine waves, with no microphone involved. Smoothing and note-name math live in a separate tracker.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The metronome and the rest
&lt;/h2&gt;

&lt;p&gt;The metronome covers 40 to 240 BPM with tap tempo and haptics, and there is a practice log with streaks. The tuner and basic metronome are free; a Pro tier adds extra tunings, insights and export. It is on iOS and Android.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd still like feedback on
&lt;/h2&gt;

&lt;p&gt;Percussive, very low notes on cheap phone mics are the hardest case for me. If you build audio tools and have seen better gating for that, I'd like to hear it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Links&lt;/strong&gt; (I'm the developer):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;iOS: &lt;a href="https://apps.apple.com/us/app/maestro-tuner-metronome/id6778955271?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=maestro_mpm" rel="noopener noreferrer"&gt;https://apps.apple.com/us/app/maestro-tuner-metronome/id6778955271?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=maestro_mpm&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Android: &lt;a href="https://play.google.com/store/apps/details?id=works.lumenlabs.maestro&amp;amp;utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=maestro_mpm" rel="noopener noreferrer"&gt;https://play.google.com/store/apps/details?id=works.lumenlabs.maestro&amp;amp;utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=maestro_mpm&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Site: &lt;a href="https://lumenlabs.works/maestro?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=maestro_mpm" rel="noopener noreferrer"&gt;https://lumenlabs.works/maestro?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=maestro_mpm&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I used an AI assistant to help draft and edit this post; the technical details come from the app's source code.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>swift</category>
      <category>audio</category>
      <category>indiedev</category>
    </item>
  </channel>
</rss>
