<?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: niixolabs</title>
    <description>The latest articles on DEV Community by niixolabs (@niixolabs).</description>
    <link>https://dev.to/niixolabs</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%2F3897852%2F6a7b1c38-72dd-4eb4-8f40-9d53860095e3.png</url>
      <title>DEV Community: niixolabs</title>
      <link>https://dev.to/niixolabs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/niixolabs"/>
    <language>en</language>
    <item>
      <title>We shipped a camera app where you record the shutter sound yourself</title>
      <dc:creator>niixolabs</dc:creator>
      <pubDate>Wed, 24 Jun 2026 23:04:33 +0000</pubDate>
      <link>https://dev.to/niixolabs/we-shipped-a-camera-app-where-you-record-the-shutter-sound-yourself-508o</link>
      <guid>https://dev.to/niixolabs/we-shipped-a-camera-app-where-you-record-the-shutter-sound-yourself-508o</guid>
      <description>&lt;p&gt;Voicame (ボイカメ) is a camera app we published for iPhone. Here's the honest account of what it does, how we built it, and where it falls short.&lt;/p&gt;

&lt;h2&gt;
  
  
  The idea
&lt;/h2&gt;

&lt;p&gt;The starting point was simple: what if the shutter click was yours to choose?&lt;/p&gt;

&lt;p&gt;iOS 17.2 shipped &lt;code&gt;AVCaptureEventInteraction&lt;/code&gt; — an API that lets apps hook into the hardware shutter button event. We used it to play back any recorded audio at the exact moment of capture. So instead of the default click, you hear whatever you recorded: a name, a word, a short clip.&lt;/p&gt;

&lt;p&gt;Recordings export via AirDrop. We kept coming back to one use case while building this: recording a child's name, then passing that recording to a partner's phone in a couple of taps so both phones make the same sound.&lt;/p&gt;

&lt;h2&gt;
  
  
  The symmetry side
&lt;/h2&gt;

&lt;p&gt;The app also has six real-time symmetry modes — horizontal, vertical, diagonal, quad, kaleidoscope, and swirl — applied to both photo and video with a live preview. Under the hood: CoreImage's &lt;code&gt;CIKaleidoscope&lt;/code&gt;, a Metal rendering pass, and &lt;code&gt;AVAssetWriter&lt;/code&gt; for video output. Everything runs on-device; no frames or audio leave the phone.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we'd change
&lt;/h2&gt;

&lt;p&gt;Symmetry cameras are not a new idea. Kaleidoscope and mirror camera apps already exist in the App Store. The differentiator here is the audio customization, not the symmetry alone.&lt;/p&gt;

&lt;p&gt;Shutter volume is tied to the system media volume — there's no separate slider in the app. That's a friction point we haven't resolved yet. The app also requires iOS 17.2+; no Android version exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing
&lt;/h2&gt;

&lt;p&gt;Free to download. Symmetry effects unlock with a one-time ¥250 in-app purchase.&lt;/p&gt;

&lt;p&gt;App Store: &lt;a href="https://apps.apple.com/jp/app/id6768058856" rel="noopener noreferrer"&gt;https://apps.apple.com/jp/app/id6768058856&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>swift</category>
      <category>avfoundation</category>
      <category>indiedev</category>
    </item>
    <item>
      <title>We built an app where the AI invents its own generators — MakerMaker by Niixo</title>
      <dc:creator>niixolabs</dc:creator>
      <pubDate>Tue, 23 Jun 2026 23:03:13 +0000</pubDate>
      <link>https://dev.to/niixolabs/we-built-an-app-where-the-ai-invents-its-own-generators-makermaker-by-niixo-47gn</link>
      <guid>https://dev.to/niixolabs/we-built-an-app-where-the-ai-invents-its-own-generators-makermaker-by-niixo-47gn</guid>
      <description>&lt;h2&gt;
  
  
  The core idea
&lt;/h2&gt;

&lt;p&gt;Point your camera at someone. MakerMaker returns a fictional 'Corporate Operations Manual v3.2' about them — AI-written text formatted like a real document, paired with an AI-generated image. That's the first of three hand-crafted generators in the app.&lt;/p&gt;

&lt;p&gt;The second produces a fake product spec sheet with fabricated stats. The third writes a mock breaking-news article. All three run the same pipeline: photo → Gemini 2.5 Flash for text → Pollinations.ai for image → displayed in a themed document skin.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part we didn't plan
&lt;/h2&gt;

&lt;p&gt;After shipping those three, the obvious question came up: what if the AI designed a new generator itself?&lt;/p&gt;

&lt;p&gt;So we built a fourth mode. Tap it and the AI invents a brand-new generator on the spot — selecting genre, tone, output format, and color palette from a parameter space that works out to roughly 95 million combinations. Each run feels different from the last.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we're honest about
&lt;/h2&gt;

&lt;p&gt;About 30% of outputs are flat. Generative variance is hard to tune out entirely, especially for entertainment where the success condition is 'make someone laugh' rather than 'return the right answer.' We surface this rather than overselling.&lt;/p&gt;

&lt;p&gt;The UI is Japanese-only. MakerMaker targets the Japanese market, where this flavor of absurdist corporate parody has an audience. Expanding to other languages isn't on the roadmap yet.&lt;/p&gt;

&lt;p&gt;Photos aren't stored. Firebase Functions (asia-northeast1) process each request and drop the image immediately — no reason to accumulate strangers' faces for a joke app.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Text: Gemini 2.5 Flash&lt;/li&gt;
&lt;li&gt;Images: Pollinations.ai&lt;/li&gt;
&lt;li&gt;Backend: Firebase Functions, asia-northeast1&lt;/li&gt;
&lt;li&gt;iOS 17+&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pricing
&lt;/h2&gt;

&lt;p&gt;Free download. Point packs from 10pt / ¥100. Premium pass at ¥480/month.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apps.apple.com/jp/app/id6762560561" rel="noopener noreferrer"&gt;https://apps.apple.com/jp/app/id6762560561&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>firebase</category>
      <category>generativeai</category>
      <category>appdev</category>
    </item>
    <item>
      <title>Off By One: a calm puzzle about finding what's slightly wrong</title>
      <dc:creator>niixolabs</dc:creator>
      <pubDate>Mon, 22 Jun 2026 23:03:17 +0000</pubDate>
      <link>https://dev.to/niixolabs/off-by-one-a-calm-puzzle-about-finding-whats-slightly-wrong-3ioi</link>
      <guid>https://dev.to/niixolabs/off-by-one-a-calm-puzzle-about-finding-whats-slightly-wrong-3ioi</guid>
      <description>&lt;h2&gt;
  
  
  The problem we were solving
&lt;/h2&gt;

&lt;p&gt;Most puzzle games are anxiety games in disguise. The mechanic is fine, but a timer layer, a combo meter, or a decaying score turns what should be observation into a race. You stop looking and start rushing.&lt;/p&gt;

&lt;p&gt;We wanted to build the opposite.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the app does
&lt;/h2&gt;

&lt;p&gt;Off By One shows a grid of geometric shapes. They all look identical — but one is slightly off. A different form, a subtly different decoration, a slight rotation. Your job is to find it and tap it.&lt;/p&gt;

&lt;p&gt;No timer. No countdown. No penalty for being slow. Just observation.&lt;/p&gt;

&lt;p&gt;There are 35 stages across Easy, Normal, and Hard difficulty. Shapes and decorations are procedurally generated from about 133,200 combinations, so the board stays varied across sessions. Built on SwiftUI's Canvas API, iOS 16+. Game Center is integrated with 17 achievements — structured to reward progress without leaning on score pressure.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we learned shipping it
&lt;/h2&gt;

&lt;p&gt;The hardest part wasn't the procedural generation. It was the App Store preview. You get a few seconds of footage to convince someone to install, and a near-static puzzle screen that's deliberately calm is genuinely difficult to sell in motion. The appeal lives inside the experience, not in watching it scroll by.&lt;/p&gt;

&lt;p&gt;We also haven't implemented IAP yet. The app is free with reward ads only — which puts a ceiling on how we reach puzzle players who'd pay to remove ads. That's on the list.&lt;/p&gt;

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

&lt;p&gt;Free on the App Store: &lt;a href="https://apps.apple.com/jp/app/id6762133251" rel="noopener noreferrer"&gt;https://apps.apple.com/jp/app/id6762133251&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hard difficulty is harder than it looks in the first few stages. Curious whether that curve lands right.&lt;/p&gt;

</description>
      <category>ios</category>
      <category>swiftui</category>
      <category>puzzle</category>
      <category>indiedev</category>
    </item>
    <item>
      <title>Why Chromium/CEF apps render a black window under Wine (and how to fix it with macOS IOSurface)</title>
      <dc:creator>niixolabs</dc:creator>
      <pubDate>Mon, 22 Jun 2026 06:49:32 +0000</pubDate>
      <link>https://dev.to/niixolabs/why-chromiumcef-apps-render-a-black-window-under-wine-and-how-to-fix-it-with-macos-iosurface-3ckn</link>
      <guid>https://dev.to/niixolabs/why-chromiumcef-apps-render-a-black-window-under-wine-and-how-to-fix-it-with-macos-iosurface-3ckn</guid>
      <description>&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;I was trying to run a Windows-only Steam game on an Apple Silicon Mac using a self-built Wine + DXMT (D3D11→Metal) stack — no commercial CrossOver. The last wall: the window opens, but its contents stay completely black.&lt;/p&gt;

&lt;p&gt;The same symptom shows up with the Steam client itself and with many apps that embed CEF (Chromium Embedded Framework). This post explains why it happens and the idea behind fixing it with macOS IOSurface — focused on the "why" and "what to bridge," not full code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Symptom: the window appears, the contents stay black
&lt;/h2&gt;

&lt;p&gt;The window frame is created, but the inside is black. No crash. No fatal error in the logs. "It runs but doesn't render" — that's what made this hard to track down.&lt;/p&gt;

&lt;h2&gt;
  
  
  Root cause: the process that draws and the process that owns the window are different
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Modern Chromium/CEF is designed to always run GPU compositing in a separate process&lt;/li&gt;
&lt;li&gt;The GPU process draws; the browser process owns the window&lt;/li&gt;
&lt;li&gt;They need a "present path" to transfer the composited frame between them&lt;/li&gt;
&lt;li&gt;But mainline Wine has no equivalent of this cross-process present, and the D3D→Metal layer (DXMT) returns "cross-process swapchain not supported"&lt;/li&gt;
&lt;li&gt;Result: the window is created, but no frame ever arrives → black&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why &lt;code&gt;-cef-disable-gpu&lt;/code&gt; is a cop-out
&lt;/h2&gt;

&lt;p&gt;Disabling GPU compositing falls back to software rendering, which does show something. But performance tanks and it's unusable for a game. I decided to build the frame-transfer path properly instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix: bridge the processes with IOSurface
&lt;/h2&gt;

&lt;p&gt;macOS has IOSurface, which lets processes share GPU memory. The approach:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;GPU process: blit the composited frame into a Metal texture backed by an IOSurface&lt;/li&gt;
&lt;li&gt;Pass a global IOSurfaceID between the processes (via IPC/file)&lt;/li&gt;
&lt;li&gt;Window process: &lt;code&gt;IOSurfaceLookup(id)&lt;/code&gt; to get the surface, attach it to the visible layer's contents&lt;/li&gt;
&lt;li&gt;Put a ~16ms (60fps) poll timer on the consumer side and call &lt;code&gt;setNeedsDisplay&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Settings that mattered
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Set &lt;code&gt;IOSurfaceIsGlobal = YES&lt;/code&gt; in the &lt;code&gt;IOSurfaceCreate&lt;/code&gt; dictionary — without it, another process cannot Lookup the surface&lt;/li&gt;
&lt;li&gt;On the producer side, key it by the root HWND from &lt;code&gt;GetAncestor(hWnd, GA_ROOT)&lt;/code&gt; — keying per child window mismatches&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The transparency wall
&lt;/h3&gt;

&lt;p&gt;By default you get opaque compositing and overlaps break. I had to flip the &lt;code&gt;opaque&lt;/code&gt; flag to non-opaque in three places across DXMT and winemac.&lt;/p&gt;

&lt;h2&gt;
  
  
  How "unusual" is this, honestly
&lt;/h2&gt;

&lt;p&gt;This isn't a finished product and has known limitations. CrossOver is genuinely well-engineered — this was an exercise in "how far can you get without paying for it."&lt;/p&gt;

&lt;h2&gt;
  
  
  Full patch and build steps
&lt;/h2&gt;

&lt;p&gt;This post sticks to the concept. The full patch, self-built Wine steps, launch scripts and staged verification are written up in detail (in Japanese, but the commands/configs translate cleanly):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Concept article (free): &lt;a href="https://zenn.dev/niixolabs/articles/wine-cef-cross-process-present" rel="noopener noreferrer"&gt;https://zenn.dev/niixolabs/articles/wine-cef-cross-process-present&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The full story (free): &lt;a href="https://zenn.dev/niixolabs/articles/m1-mac-steam-wine-story" rel="noopener noreferrer"&gt;https://zenn.dev/niixolabs/articles/m1-mac-steam-wine-story&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Complete step-by-step (paid book, ¥800; 3 of 7 chapters free): &lt;a href="https://zenn.dev/niixolabs/books/m1-mac-steam-wine-build" rel="noopener noreferrer"&gt;https://zenn.dev/niixolabs/books/m1-mac-steam-wine-build&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>architecture</category>
      <category>opensource</category>
      <category>programming</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>We built a mahjong tile-danger predictor calibrated on 4.97M real discards</title>
      <dc:creator>niixolabs</dc:creator>
      <pubDate>Sun, 21 Jun 2026 23:04:01 +0000</pubDate>
      <link>https://dev.to/niixolabs/we-built-a-mahjong-tile-danger-predictor-calibrated-on-497m-real-discards-1743</link>
      <guid>https://dev.to/niixolabs/we-built-a-mahjong-tile-danger-predictor-calibrated-on-497m-real-discards-1743</guid>
      <description>&lt;p&gt;The idea came from a specific moment at a real mahjong table: one tile in hand, not sure if it's safe to discard. OkkanaiPai is the app Niixo built for that.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;Open the app, swipe to the player you're reading, tap in their discards. The app color-codes all 34 tiles by danger level — no numbers to parse under pressure, just color.&lt;/p&gt;

&lt;p&gt;The model is rule-based danger logic calibrated against actual Tenhou Houou-takujo data: 16 days, 4.97 million discards from the top tier of Japanese online mahjong. The calibration coefficients ship as a JSON file bundled with the app. No ML engine runs at inference time. Fully offline.&lt;/p&gt;

&lt;h2&gt;
  
  
  On the accuracy number
&lt;/h2&gt;

&lt;p&gt;AUC 0.83 on the test set. Mahjong danger prediction has a noisy label problem — "ron" is the only ground-truth signal, and a tile can be dangerous but never called. The number is honest but it has a built-in ceiling.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it doesn't cover
&lt;/h2&gt;

&lt;p&gt;East round / East seat only — hardcoded, not a config option. Meld (furo) efficiency is out of scope. Three-player (sanma) isn't supported. These are scope decisions. One well-defined setting working reliably comes before expanding coverage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not on-device ML?
&lt;/h2&gt;

&lt;p&gt;We considered CoreML. The coefficient-in-JSON approach is simpler, faster to load, and easier to audit. The tradeoff: calibration is static — it won't adapt to shifts in playing style without a new release. For a reference tool, static and transparent beats dynamic and opaque.&lt;/p&gt;

&lt;h2&gt;
  
  
  Free, offline, no ads
&lt;/h2&gt;

&lt;p&gt;iOS 17+. No network requests. No in-app purchase. No ads. For a tool you pull out at a table, the friction of an ad at the wrong moment makes it useless.&lt;/p&gt;

&lt;p&gt;App Store: &lt;a href="https://apps.apple.com/jp/app/id6762544982" rel="noopener noreferrer"&gt;https://apps.apple.com/jp/app/id6762544982&lt;/a&gt;&lt;/p&gt;

</description>
      <category>mahjong</category>
      <category>ios</category>
      <category>statistics</category>
      <category>showdev</category>
    </item>
    <item>
      <title>We shipped a weather app that learns your personal cold threshold — no ML, just percentiles</title>
      <dc:creator>niixolabs</dc:creator>
      <pubDate>Sat, 20 Jun 2026 23:04:31 +0000</pubDate>
      <link>https://dev.to/niixolabs/we-shipped-a-weather-app-that-learns-your-personal-cold-threshold-no-ml-just-percentiles-11cb</link>
      <guid>https://dev.to/niixolabs/we-shipped-a-weather-app-that-learns-your-personal-cold-threshold-no-ml-just-percentiles-11cb</guid>
      <description>&lt;p&gt;There's a gap between knowing the temperature and knowing whether to grab a coat. 14°C means very different things depending on whether you run cold, dress light year-round, or fall sick every season change. Generic forecast apps don't capture that.&lt;/p&gt;

&lt;p&gt;Samukunai — 'are you cold?' in Japanese — is Niixo's attempt to close that gap without reaching for a machine learning model.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;After stepping outside, you tap one of three options: 'felt cold,' 'felt fine,' or 'felt warm.' After 10 of those taps, an on-device statistics module we call ComfortEngine computes your personal 75th and 25th percentile comfort thresholds.&lt;/p&gt;

&lt;p&gt;From that point forward, your morning push notification shifts from '14°C' to 'on the cold side for you' — or 'about right' — based on where today's forecast lands in your personal range. Processing stays on-device via SwiftData, with CloudKit sync across devices. Weather data comes from WeatherKit.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we're honest about
&lt;/h2&gt;

&lt;p&gt;Until you hit 10 taps, the experience is strictly worse than a standard weather app. You get less functionality without the personalization that justifies the extra interaction. No home screen widget yet. iOS 26+ only, which is a real constraint given where adoption sits today.&lt;/p&gt;

&lt;p&gt;We shipped it anyway. The core problem — cold-tolerance is personal, raw temperature numbers don't capture it — doesn't disappear because the MVP has rough edges. Pure percentile statistics turned out to be a clean enough approach that we could ship without server-side inference or training data.&lt;/p&gt;

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

&lt;p&gt;WeatherKit handles real-time conditions. SwiftData + CloudKit manages persistence and cross-device sync. ComfortEngine is a local statistics module — the one novel piece, with no external dependencies. The UI runs iOS 26 Liquid Glass.&lt;/p&gt;

&lt;p&gt;Free. No ads. No in-app purchases.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apps.apple.com/jp/app/id6762537476" rel="noopener noreferrer"&gt;https://apps.apple.com/jp/app/id6762537476&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>swift</category>
      <category>weather</category>
      <category>ux</category>
    </item>
    <item>
      <title>We built an app that counts your leg fidgets — the NEAT science and the CoreMotion implementation</title>
      <dc:creator>niixolabs</dc:creator>
      <pubDate>Fri, 19 Jun 2026 23:04:46 +0000</pubDate>
      <link>https://dev.to/niixolabs/we-built-an-app-that-counts-your-leg-fidgets-the-neat-science-and-the-coremotion-implementation-46hd</link>
      <guid>https://dev.to/niixolabs/we-built-an-app-that-counts-your-leg-fidgets-the-neat-science-and-the-coremotion-implementation-46hd</guid>
      <description>&lt;p&gt;Most people have never thought to count how often their leg bounces during a day. We hadn't either — until we built BinBot to measure it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The scientific premise
&lt;/h2&gt;

&lt;p&gt;Levine's research on Non-Exercise Activity Thermogenesis (NEAT) found that incidental motion like fidgeting can account for up to 350 kcal/day difference between people. Not formal exercise — the constant background micro-movement of someone who simply can't sit still. That number is the reason BinBot exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens under the hood
&lt;/h2&gt;

&lt;p&gt;The core is CoreMotion sampled at 100Hz, passed through a 3-9Hz IIR bandpass filter. Walking cadence sits around 2Hz; most ambient vibration is above 10Hz. The 3-9Hz window isolates the frequency range where leg-bounce typically lives.&lt;/p&gt;

&lt;p&gt;Above the filter, a five-stage rhythm classifier distinguishes three motion types: bounce, jump, and spin. Every session writes its count to HealthKit, so fidget data appears in the same Health app timeline as steps and heart rate. The app also supports Apple Watch, a home screen widget, and Live Activity for the lock screen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it's imperfect
&lt;/h2&gt;

&lt;p&gt;Walking cadence and car vibration occasionally land in the 3-9Hz range and trigger false positives. The filter reduces this but doesn't eliminate it. Watch-to-iPhone sync is currently one-way. Very low-amplitude fidgets may fall below the detection threshold.&lt;/p&gt;

&lt;p&gt;We're naming these upfront because the gap between "interesting motion data" and "clinical accuracy" is real. BinBot is firmly in the first category.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why free with ads
&lt;/h2&gt;

&lt;p&gt;We wanted to see the real variance in fidget counts across different people more than we wanted subscription revenue. Free removes the barrier. The trade-off is ads.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apps.apple.com/jp/app/id6760091302" rel="noopener noreferrer"&gt;https://apps.apple.com/jp/app/id6760091302&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>swift</category>
      <category>fitness</category>
      <category>coremotion</category>
    </item>
    <item>
      <title>We built a kitten care app where the guidance adapts to your cat's actual age</title>
      <dc:creator>niixolabs</dc:creator>
      <pubDate>Thu, 18 Jun 2026 23:04:30 +0000</pubDate>
      <link>https://dev.to/niixolabs/we-built-a-kitten-care-app-where-the-guidance-adapts-to-your-cats-actual-age-5ge1</link>
      <guid>https://dev.to/niixolabs/we-built-a-kitten-care-app-where-the-guidance-adapts-to-your-cats-actual-age-5ge1</guid>
      <description>&lt;p&gt;The problem with kitten care advice online is that most of it is technically correct and practically out of context.&lt;/p&gt;

&lt;p&gt;"Feed 3–4 times a day." Sure — but for a 6-week-old or a 4-month-old? "Vaccinate early." When exactly? The answers exist, but matching them to your specific cat's current age, on the day you need them, is the actual friction.&lt;/p&gt;

&lt;p&gt;That's the gap we built Nekososdate to close.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;Register your kitten's birthdate. The app calculates their current age and surfaces care guidance calibrated to this stage — not a static checklist, but the information that's relevant right now.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's inside:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;54 care guides across development stages&lt;/li&gt;
&lt;li&gt;48 troubleshooting topics&lt;/li&gt;
&lt;li&gt;34 breed profiles&lt;/li&gt;
&lt;li&gt;A 15-question diagnostic that maps your cat to a personality type and adjusts guidance accordingly&lt;/li&gt;
&lt;li&gt;Growth and symptom records&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Content is bundled as assets/JSON so it works offline. Built with Flutter and Firebase, subscriptions via StoreKit 2. Free to start, ¥200/month unlocks the full guide library.&lt;/p&gt;

&lt;h2&gt;
  
  
  The record feature mattered more than we expected
&lt;/h2&gt;

&lt;p&gt;We initially thought the growth record was a nice-to-have. Then we thought about the vet visit.&lt;/p&gt;

&lt;p&gt;"When did this start?" Most cat owners guess. With a symptom log in hand, you answer with an actual date. That specificity changes what the checkup can accomplish — and it's the kind of thing you only appreciate in the moment you need it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest limitation
&lt;/h2&gt;

&lt;p&gt;iOS only. No Android version. No family sharing — if two people are raising the same kitten, only one device holds the record. That's a real gap for co-owners, and we know it.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://apps.apple.com/jp/app/%E3%81%AD%E3%81%93%E3%81%9D%E3%81%A0%E3%81%A6/id6761289306" rel="noopener noreferrer"&gt;Nekososdate on the App Store&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>flutter</category>
      <category>indiedev</category>
      <category>appdev</category>
    </item>
    <item>
      <title>We built a braille camera that never sends your photos anywhere</title>
      <dc:creator>niixolabs</dc:creator>
      <pubDate>Wed, 17 Jun 2026 23:05:00 +0000</pubDate>
      <link>https://dev.to/niixolabs/we-built-a-braille-camera-that-never-sends-your-photos-anywhere-2104</link>
      <guid>https://dev.to/niixolabs/we-built-a-braille-camera-that-never-sends-your-photos-anywhere-2104</guid>
      <description>&lt;h2&gt;
  
  
  We built a braille camera that never sends your photos anywhere
&lt;/h2&gt;

&lt;p&gt;A lot of braille translation tools start from the wrong place. You type in the Unicode braille characters, you get a reading. Useful for developers building accessibility pipelines, less useful for someone standing at a train station wondering what the handrail says.&lt;/p&gt;

&lt;p&gt;TenjiScan does one thing: point your iPhone camera at braille, get text. On-device, offline, no account, no photo upload.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the on-device constraint matters
&lt;/h2&gt;

&lt;p&gt;The privacy consideration wasn't an afterthought. When you're photographing a pill box, a medication label, or something on a person's belongings, you probably don't want those images going to an external API. As of v4.0.0, the entire pipeline runs on-device — nothing leaves your phone.&lt;/p&gt;

&lt;p&gt;We built on top of Vision with a custom two-signal pipeline for detecting and interpreting braille dot patterns. The app handles Japanese braille (JIS standard) and English braille (UEB Grade 1) — the everyday kind you find on train handrails, elevator buttons, and product packaging.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it doesn't do yet
&lt;/h2&gt;

&lt;p&gt;Grade 2 contracted braille — the kind that uses abbreviations to compress meaning into fewer cells — isn't supported. Grade 1 only, standard cell-by-cell transcription.&lt;/p&gt;

&lt;p&gt;Accuracy also depends on lighting and angle. Flat surface, even lighting, camera roughly parallel to the surface: that's the sweet spot. Steep angles and harsh shadows degrade results noticeably. We document this in the app description rather than glossing over it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The actual use case
&lt;/h2&gt;

&lt;p&gt;The people who find it most useful usually aren't studying braille. They're curious. A commuter who's ridden the same line for years and finally wants to know what the handrail says. Someone at a pharmacy wondering what's on the side of the box.&lt;/p&gt;

&lt;p&gt;Ambient curiosity about text that's been there all along — that's the use case. Narrow, but real.&lt;/p&gt;

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

&lt;p&gt;Free to download. One-time ad-removal purchase, no subscription.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apps.apple.com/jp/app/id6759526188" rel="noopener noreferrer"&gt;https://apps.apple.com/jp/app/id6759526188&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>a11y</category>
      <category>swift</category>
      <category>makerlog</category>
    </item>
    <item>
      <title>We built an app for Japanese neighborhood associations — and the handover notebook turned out to matter most</title>
      <dc:creator>niixolabs</dc:creator>
      <pubDate>Tue, 16 Jun 2026 23:04:12 +0000</pubDate>
      <link>https://dev.to/niixolabs/we-built-an-app-for-japanese-neighborhood-associations-and-the-handover-notebook-turned-out-to-lgi</link>
      <guid>https://dev.to/niixolabs/we-built-an-app-for-japanese-neighborhood-associations-and-the-handover-notebook-turned-out-to-lgi</guid>
      <description>&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Every year in Japan, a small group of volunteers runs the local 自治会 (neighborhood association). They circulate bulletins, collect dues, check in on elderly residents, run votes at general meetings, and maintain the annual schedule. At year's end, they hand the role over — usually with a folder of paper, or nothing at all.&lt;/p&gt;

&lt;p&gt;Nobody tracks who did what. Nobody measures the actual workload. So when it's time to recruit the next round of officers, no one can honestly answer "how much work is it?" And the handover is always rough.&lt;/p&gt;

&lt;p&gt;That's the loop Musubiba is trying to break.&lt;/p&gt;

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

&lt;p&gt;Musubiba covers the full 自治会 / 町内会 cycle in one app: bulletin routing, dues collection, safety checks, general meeting votes, annual schedule, and a handover notebook.&lt;/p&gt;

&lt;p&gt;The handover notebook ended up being the feature that resonated most. Officers change annually in most associations — and institutional memory typically walks out the door with them. Making that transition structured means the next person starts from somewhere real, not from scratch.&lt;/p&gt;

&lt;p&gt;Members join via QR code. Web-based accounting input is supported for committees that prefer to keep some tasks on desktop. The stack is Flutter (iOS + Android) + Firebase, with Stripe + IAP for billing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest limitation
&lt;/h2&gt;

&lt;p&gt;Musubiba is purpose-built for Japanese 自治会 and 町内会. The workflows, terminology, and community context are Japan-specific — it's not a horizontal tool for HOAs or resident associations outside Japan.&lt;/p&gt;

&lt;p&gt;Pricing: free up to 15 members, ¥1,500/month for unlimited.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to get it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;App Store: &lt;a href="https://apps.apple.com/jp/app/musubiba/id6759871374" rel="noopener noreferrer"&gt;https://apps.apple.com/jp/app/musubiba/id6759871374&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Google Play: &lt;a href="https://play.google.com/store/apps/details?id=com.htor.musubiba" rel="noopener noreferrer"&gt;https://play.google.com/store/apps/details?id=com.htor.musubiba&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>productivity</category>
      <category>ios</category>
      <category>flutter</category>
      <category>community</category>
    </item>
    <item>
      <title>We built a budgeting app that skips the bank login — here's the trade-off</title>
      <dc:creator>niixolabs</dc:creator>
      <pubDate>Mon, 15 Jun 2026 23:04:14 +0000</pubDate>
      <link>https://dev.to/niixolabs/we-built-a-budgeting-app-that-skips-the-bank-login-heres-the-trade-off-4375</link>
      <guid>https://dev.to/niixolabs/we-built-a-budgeting-app-that-skips-the-bank-login-heres-the-trade-off-4375</guid>
      <description>&lt;p&gt;Most budgeting apps open with the same onboarding step: connect your bank account. For a certain group of people, that's where the process ends — not because they can't, but because they won't hand over those credentials to a third-party app.&lt;/p&gt;

&lt;p&gt;moneasy is Niixo's attempt to design around that constraint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two ways in
&lt;/h2&gt;

&lt;p&gt;The app has two entry points. First: point your camera at a receipt. Apple Vision Framework and Gemini 2.5 Flash handle the OCR — line items, amounts, categories. Second: say "moneasy 記録" to Siri. Apple Speech picks it up, the transaction logs.&lt;/p&gt;

&lt;p&gt;No bank login. No OAuth flow. No third-party service in the data path.&lt;/p&gt;

&lt;h2&gt;
  
  
  The trade-off
&lt;/h2&gt;

&lt;p&gt;There's no bank API. Transactions don't pull in automatically. If you need that, moneasy isn't the right fit — and it's better to say that plainly than have someone frustrated after paying.&lt;/p&gt;

&lt;p&gt;CSV import is the alternative. For people who already manage finances in a spreadsheet, that manual step is probably already part of the routine.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Voice input: Apple Speech&lt;/li&gt;
&lt;li&gt;Receipt OCR: Gemini 2.5 Flash + Vision framework&lt;/li&gt;
&lt;li&gt;Storage and sync: SwiftData + CloudKit (private, device-to-device via Apple ID)&lt;/li&gt;
&lt;li&gt;Languages: 25&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CloudKit sync keeps everything private — no external server in the data path. The architecture fits the design intent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest take
&lt;/h2&gt;

&lt;p&gt;It's built for people who track spending manually and want to lower the friction, not outsource the decision-making. The absence of bank sync is the feature for the intended user and a dealbreaker for everyone else. That's a fine trade-off, as long as it's stated up front.&lt;/p&gt;

&lt;p&gt;¥450/month or ¥5,000/year, 30-day free trial.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apps.apple.com/jp/app/moneasy/id6742516728" rel="noopener noreferrer"&gt;https://apps.apple.com/jp/app/moneasy/id6742516728&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>swift</category>
      <category>productivity</category>
      <category>finance</category>
    </item>
    <item>
      <title>We made a camera app where the shutter sound is your own voice</title>
      <dc:creator>niixolabs</dc:creator>
      <pubDate>Sun, 14 Jun 2026 23:33:56 +0000</pubDate>
      <link>https://dev.to/niixolabs/we-made-a-camera-app-where-the-shutter-sound-is-your-own-voice-ph</link>
      <guid>https://dev.to/niixolabs/we-made-a-camera-app-where-the-shutter-sound-is-your-own-voice-ph</guid>
      <description>&lt;p&gt;The default iPhone shutter click is fine. It's neutral, functional, and completely impersonal. Voicame (ボイカメ) is Niixo's attempt to change that in the smallest possible way.&lt;/p&gt;

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

&lt;p&gt;Open the app, tap record, say something — a name, a word, a sound that means something to you — and that clip becomes your shutter trigger for every photo and video you take. Recorded sounds can be AirDropped to others so they can use the same clip. Everything runs on-device; nothing is uploaded.&lt;/p&gt;

&lt;p&gt;Beyond the voice shutter, six symmetry modes run live in the viewfinder: horizontal, vertical, diagonal, quad, kaleidoscope (built on Core Image's CIKaleidoscope), and swirl. They work for photos and video both, and the preview is real-time so you frame the shot before committing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it needed iOS 17.2
&lt;/h2&gt;

&lt;p&gt;The shutter replacement relies on &lt;code&gt;AVCaptureEventInteraction&lt;/code&gt;, an API Apple introduced in iOS 17.2. Before that release, swapping the system shutter sound through official channels wasn't achievable. That API landing was what made the app feasible in the first place.&lt;/p&gt;

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

&lt;p&gt;Symmetry camera apps are not rare. Kaleidoscope modes, mirror effects — there's existing competition in the category. The voice shutter is the piece that makes Voicame different, and whether that hook lands depends entirely on the user.&lt;/p&gt;

&lt;p&gt;Other limits worth knowing: iOS only, no Android, no Apple Watch support. Shutter volume follows the device media volume — there's no independent in-app control.&lt;/p&gt;

&lt;h2&gt;
  
  
  Availability
&lt;/h2&gt;

&lt;p&gt;Free to download. A one-time ¥250 in-app purchase unlocks all six symmetry modes. Requires iOS 17.2+.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apps.apple.com/jp/app/id6768058856" rel="noopener noreferrer"&gt;https://apps.apple.com/jp/app/id6768058856&lt;/a&gt;&lt;/p&gt;

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