<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Rob Roy</title>
	<atom:link href="https://www.robert-e-roy.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.robert-e-roy.com</link>
	<description>Apple Platform Developer</description>
	<lastBuildDate>Mon, 27 Apr 2026 17:38:44 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://i0.wp.com/www.robert-e-roy.com/wp-content/uploads/2017/12/cropped-IMG_3585.jpg?fit=32%2C32&#038;ssl=1</url>
	<title>Rob Roy</title>
	<link>https://www.robert-e-roy.com</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">56422216</site>	<item>
		<title>CorpusKit Studio: Building a RAG Corpus Pipeline Without the Python Tax</title>
		<link>https://www.robert-e-roy.com/corpuskit-studio-building-a-rag-corpus-pipeline-without-the-python-tax/</link>
		
		<dc:creator><![CDATA[robroy]]></dc:creator>
		<pubDate>Mon, 27 Apr 2026 14:13:39 +0000</pubDate>
				<category><![CDATA[Mac OS]]></category>
		<category><![CDATA[Software]]></category>
		<guid isPermaLink="false">https://www.robert-e-roy.com/?p=2425</guid>

					<description><![CDATA[If you&#8217;ve spent any time building RAG applications, you know the drill. Before your app can do anything useful, you need a pipeline: extract text from PDFs, chunk it, run it through an embedding model, store the vectors somewhere. If you&#8217;re lucky, you&#8217;ve got a Python environment that isn&#8217;t broken. If you&#8217;re not, you&#8217;re debugging ... <a title="CorpusKit Studio: Building a RAG Corpus Pipeline Without the Python Tax" class="read-more" href="https://www.robert-e-roy.com/corpuskit-studio-building-a-rag-corpus-pipeline-without-the-python-tax/" aria-label="Read more about CorpusKit Studio: Building a RAG Corpus Pipeline Without the Python Tax">Read more</a>]]></description>
										<content:encoded><![CDATA[
<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>If you&#8217;ve spent any time building RAG applications, you know the drill. Before your app can do anything useful, you need a pipeline: extract text from PDFs, chunk it, run it through an embedding model, store the vectors somewhere. If you&#8217;re lucky, you&#8217;ve got a Python environment that isn&#8217;t broken. If you&#8217;re not, you&#8217;re debugging dependency conflicts at 11pm wondering why you wanted to do this.</p>



<p>I built CorpusKit Studio because I wanted to build RAG-powered iOS apps and I didn&#8217;t want a Python pipeline in the loop.</p>



<h2 class="wp-block-heading">What It Does</h2>



<p>CorpusKit Studio is a native Mac app. You drag in a PDF. The app extracts the text, chunks it, generates embeddings using an on-device Core ML model, and exports a signed&nbsp;<code>.corpus</code>&nbsp;bundle that any CorpusKit iOS app can consume directly.</p>



<p>No Python. No API keys. No data leaving your machine.</p>



<p>That last part matters more than it sounds, especially if you&#8217;re working with sensitive documents — legal filings, medical records, proprietary research. The embedding step, which normally means sending your text to an external API, happens entirely on your Mac using Apple&#8217;s Neural Engine.</p>



<h2 class="wp-block-heading">The Technical Decisions Worth Talking About</h2>



<p><strong>PDF extraction via PDFKit</strong></p>



<p>The obvious choice for a Mac app, and it mostly just works. The edge case worth knowing: some PDFs are image-based scans with no extractable text layer. CorpusKit Studio checks for this and warns you if the page character count is suspiciously low. OCR is outside scope — I&#8217;m not going to bundle a third-party OCR engine when there are good dedicated tools for that job. Extract the text first, then bring it into the app.</p>



<p><strong>Running MiniLM on Core ML</strong></p>



<p>This was the interesting part. MiniLM-L6-v2 is the embedding model that&#8217;s become a standard for RAG applications — small, fast, good quality for retrieval tasks. Getting it running natively on macOS via Core ML meant converting the model and implementing the WordPiece tokenizer in Swift, which doesn&#8217;t exist anywhere off the shelf.</p>



<p>The result: embedding a typical PDF runs in seconds on Apple Silicon. The Neural Engine handles it efficiently and the model is identical to what the iOS CorpusKit apps use, which matters for consistency between where you build the corpus and where you query it.</p>



<p><strong>NSDocument architecture</strong></p>



<p>I used NSDocument as the foundation rather than building a custom persistence layer from scratch. That decision gave me File &gt; Open Recent, autosave, and document versioning essentially for free. It&#8217;s one of those AppKit decisions that feels like overhead until you realize how much work it saves.</p>



<p><strong>Cosine similarity search via Accelerate</strong></p>



<p>No vector database. The corpus sizes I&#8217;m targeting — a few hundred to a few thousand chunks from a typical book or document — don&#8217;t need one. Accelerate&#8217;s vDSP handles cosine similarity over that scale trivially fast. Adding a vector DB dependency would introduce complexity with no real benefit at this scale.</p>



<h2 class="wp-block-heading">The Part That Isn&#8217;t Just Engineering</h2>



<p>There&#8217;s a piece of CorpusKit Studio that goes beyond the mechanical pipeline: the curator layer.</p>



<p>Raw text extraction treats every chunk as equal. But if you&#8217;ve actually read the document, you know that&#8217;s not true. Some passages are central to the subject. Others are footnotes, boilerplate, chapter openers that don&#8217;t contain useful retrieval content.</p>



<p>CorpusKit Studio lets you read the source document inside the app, highlight passages, and rate their importance. Those curator signals travel with the exported corpus. When the iOS app retrieves results, importance ratings can influence ranking. Eventually — as apps accumulate usage data — real retrieval signals (which chunks actually led to good conversations) can feed back into the corpus weighting.</p>



<p>The idea is that a corpus curated by someone who actually understands the content should outperform one that was just mechanically chunked. That&#8217;s the bet.</p>



<h2 class="wp-block-heading">It Teaches You How RAG Actually Works</h2>



<p>Something I didn&#8217;t fully anticipate: CorpusKit Studio turns out to be a genuinely good way to understand retrieval-augmented generation at a mechanical level.</p>



<p>Most developers interact with RAG through an API or a framework that hides the steps. You send text in, you get responses back, and the middle is a black box. That&#8217;s fine for shipping product, but it means you&#8217;re guessing when something doesn&#8217;t work — when results are irrelevant, when the model seems to miss obvious answers, when response quality is inconsistent.</p>



<p>CorpusKit Studio makes the whole pipeline visible. You can see exactly how your document gets chunked. You can adjust chunk size and overlap and immediately see how the boundaries change. You can run a query against your corpus and see the ranked results — with cosine similarity scores — before any LLM is involved. That score tells you whether retrieval is finding the right passages. If it isn&#8217;t, you know the problem is in the corpus, not the model.</p>



<p>When you highlight a passage and mark it as high importance, you&#8217;re making a decision about signal vs. noise that a pure pipeline never asks you to make. When you run a test query and see a mediocre chunk ranking above a better one, you learn something real about how embedding similarity works — and you can fix it by adjusting your chunking strategy or adding more representative content.</p>



<p>If you&#8217;re learning RAG or trying to build intuition about why your retrieval quality varies, building a corpus in CorpusKit Studio is more instructive than reading about it. The feedback loop is immediate and concrete.</p>



<h2 class="wp-block-heading">What&#8217;s Coming</h2>



<p>CorpusKit Studio is coming to the Mac App Store. The product page is live now at robroy.online if you want to read more about what it does.</p>



<p>If you&#8217;re building RAG applications on Apple platforms and you&#8217;ve been tolerating the Python pipeline, I&#8217;d be curious what your setup looks like. Drop me a line at contact@robroy.online.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p><em>CorpusKit Studio is a Mac app that builds semantic search corpora from PDF documents using on-device Core ML embeddings.&nbsp;<a href="https://robroy.online/corpuskitstudio/">Learn more →</a></em></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2425</post-id>	</item>
		<item>
		<title>Building a Private On-Device AI Companion: What I Learned</title>
		<link>https://www.robert-e-roy.com/building-a-private-on-device-ai-companion-what-i-learned/</link>
		
		<dc:creator><![CDATA[robroy]]></dc:creator>
		<pubDate>Sat, 18 Apr 2026 22:36:10 +0000</pubDate>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[iOS apps]]></category>
		<category><![CDATA[Mac OS]]></category>
		<category><![CDATA[Software]]></category>
		<guid isPermaLink="false">https://www.robert-e-roy.com/?p=2423</guid>

					<description><![CDATA[The starting question Rob Roy · robroy.online · April 2026 A few weeks ago I asked a simple question: could I take a small language model and teach it about one specific domain? That question led me through a full modern AI engineering stack — retrieval-augmented generation, embedding models, on-device inference, Core ML conversion, Apple ... <a title="Building a Private On-Device AI Companion: What I Learned" class="read-more" href="https://www.robert-e-roy.com/building-a-private-on-device-ai-companion-what-i-learned/" aria-label="Read more about Building a Private On-Device AI Companion: What I Learned">Read more</a>]]></description>
										<content:encoded><![CDATA[
<h1 class="wp-block-heading">The starting question</h1>



<p><em>Rob Roy · robroy.online · April 2026</em></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>A few weeks ago I asked a simple question: could I take a small language model and teach it about one specific domain?</p>



<p>That question led me through a full modern AI engineering stack — retrieval-augmented generation, embedding models, on-device inference, Core ML conversion, Apple Foundation Models — and eventually to a working iOS app that runs entirely on the device with no network calls. Along the way I changed direction several times, discarded entire architectures, and learned what actually matters versus what just sounds impressive in a roadmap.</p>



<p>This is a record of the journey, including the parts where I was wrong.</p>



<h2 class="wp-block-heading">The project</h2>



<p>The app is called Big Book via LLM. It provides a private, on-device conversational interface to the 1939 first edition of the Alcoholics Anonymous Big Book — a text that is firmly in the public domain in the United States. The app retrieves relevant passages from the text in response to user queries and generates warm, concise responses grounded in those passages. Every answer cites its source. Nothing leaves the device.</p>



<p>The project had three honest goals from the start:</p>



<p>Learn the current AI engineering stack deeply enough to be professionally fluent in it. Build something that might serve a community I care about. Produce work that demonstrates real capability, not just familiarity with buzzwords.</p>



<p>Commercial scale was never the primary goal. That turned out to matter, because it freed me to make good technical decisions instead of defensive market positioning.</p>



<h2 class="wp-block-heading">Starting with the wrong architecture</h2>



<p>My first instinct was to bundle everything into the app. Download a small LLM, index the Big Book corpus, run inference locally, ship it. Privacy would be the pitch. On-device would be the differentiator.</p>



<p>That architecture started falling apart almost immediately.</p>



<p>The first problem was model size. Phi-4 Mini quantized to Q4 is about 2.3 GB. Apple&#8217;s On-Demand Resource system caps individual asset packs at 512 MB. The workaround was splitting the GGUF file into chunks and downloading both, but the real issue surfaced first: a 2.3 GB download before the user sees any value is a terrible first experience. Most users abandon apps in the first 60 seconds. A progress bar is not an experience.</p>



<p>The second problem was memory. A 2.3 GB model needs roughly 3 GB of RAM to load with overhead. iPhones with 4 GB of RAM physically cannot run it. That cut off iPhone 12 and 13 users — a significant slice of exactly the demographic most likely to benefit from this app.</p>



<p>The third problem was stability. llama.cpp integration via Swift bindings involved C++ interop, manual KV cache management, and a class of bugs that don&#8217;t exist in pure Swift. I spent days chasing hard crashes before realizing the architecture was fighting the platform.</p>



<p>The lesson: elegance on the developer&#8217;s MacBook is not the same as elegance on the user&#8217;s iPhone.</p>



<h2 class="wp-block-heading">Changing direction</h2>



<p>I made three architectural changes in quick succession, each one forced by a problem I should have anticipated:</p>



<p>Switched from Phi-4 Mini to Gemma 3 1B. Smaller model, more devices supported, smaller download. Response quality for RAG is largely driven by the retrieval layer, not the model&#8217;s raw capabilities — the LLM is primarily framing retrieved passages rather than generating from scratch. A 1 billion parameter model does this task surprisingly well.</p>



<p>Replaced llama.cpp with Apple Foundation Models. When iOS 26 shipped with native on-device LLM support, the entire custom inference stack became unnecessary. No download, no GGUF files, no C++ bridge, no ODR splitting. A single Swift API that uses the Neural Engine directly. The tradeoff was setting iOS 26 as the minimum deployment target, which sounds restrictive but according to Apple&#8217;s data covers 66% of all active iPhones and 74% of devices from the last four years. The users I&#8217;d exclude were mostly on hardware that couldn&#8217;t run the app well regardless.</p>



<p>Built a Mac companion app to handle corpus preparation. My original workflow used Python scripts that only I could run. That&#8217;s a workflow for exactly one person. I built CorpusKit Studio as a native Mac app that accepts PDFs, chunks them, generates embeddings via Core ML, lets curators highlight important passages, tests retrieval live, and exports a deployable corpus bundle. No terminal required. No Python. Same code patterns as the iOS app, same embedding model, consistent results across both.</p>



<h2 class="wp-block-heading">The RAG architecture that worked</h2>



<p>With the right pieces in place, the final architecture is conceptually simple:</p>



<p>A corpus is prepared by CorpusKit Studio on a Mac. The Big Book PDF goes in. PDFKit extracts the text. A chunker splits it into overlapping 200-word segments with metadata preserved. A Core ML converted version of all-MiniLM-L6-v2 generates a 384-dimensional semantic embedding for each chunk. Important passages get curator importance weights set via a highlighting interface. The whole thing exports as a bundle containing chunks.json and embeddings.npy.</p>



<p>The iOS app bundles this corpus along with the same MiniLM Core ML model. At query time: the user&#8217;s question is expanded using a domain-specific vocabulary dictionary (&#8220;step 4&#8221; becomes &#8220;searching and fearless moral inventory personal housecleaning list resentments fears&#8221;), embedded using the same model that created the corpus, compared against all chunk embeddings via cosine similarity, weighted by chapter and importance, and the top three chunks are retrieved. Those chunks are assembled into a prompt with a tight three-part response structure. Apple Foundation Models streams a warm, brief response. The UI renders the response text alongside passage cards showing the specific cited sentences.</p>



<p>End to end, a query takes about 800 milliseconds on an iPhone 15 Pro. No network. No server. No user data leaving the device.</p>



<h2 class="wp-block-heading">Three design decisions I&#8217;d make again</h2>



<p>The three-part response structure. Rather than letting the LLM generate whatever it wanted, I constrained responses to: one sentence acknowledging what the person is bringing, one sentence pointing to where the book addresses it, and one question that opens reflection. Under 50 words total. This makes the app feel like a thoughtful companion rather than a chatbot. The text is just connective tissue — the UI renders actual book passages as citation cards.</p>



<p>Sentence-level citation extraction. Chunks are 200 words because that&#8217;s what works for retrieval. But showing 200 words as a citation is overwhelming. At display time, I embed each sentence within the retrieved chunk and show only the single most relevant sentence with its page number. &#8220;Resentment is the number one offender. — Big Book, p. 64&#8221; is more useful than a paragraph of context the user didn&#8217;t ask for.</p>



<p>Treating authority as a first-class concept. Not every document in a library is equally authoritative. In law, the Constitution outweighs a law review article. In recovery, the Big Book first edition outweighs commentary. CorpusKit Studio lets curators set authority weights per corpus, stamped into every chunk at export time. The iOS app multiplies similarity by authority, so a passage from a primary source wins over a loosely relevant passage from a secondary one. This encodes domain expertise directly into retrieval rather than hoping the model figures it out.</p>



<h2 class="wp-block-heading">Three decisions I got wrong first</h2>



<p>I initially wanted the app to rely on a local Flask server for embeddings during development. This worked in the simulator but created a dependency that couldn&#8217;t ship to actual users. I should have prioritized Core ML embedding conversion from day one rather than using it as a placeholder.</p>



<p>I tried to bundle the model inline with the app. Apple&#8217;s ODR system and memory constraints made this painful. The real answer was either a smaller model that fits within reasonable constraints, or Apple&#8217;s own Foundation Models when available. Fighting the platform on model delivery was wasted effort.</p>



<p>I considered competing with NotebookLM on features. That would have been a losing strategy. Google&#8217;s free, works-everywhere tool wins on raw capability. What my app can offer that theirs cannot is specialization — domain-tuned query expansion, citation-first UI, crisis awareness appropriate for recovery literature, a warm tone deliberately shaped for the community it serves. General tools cannot credibly be all things to all domains. Specificity is defensible.</p>



<h2 class="wp-block-heading">What I learned about RAG</h2>



<p>The retrieval layer matters more than the model. A well-tuned retrieval pipeline with a mediocre LLM outperforms a great LLM with naive retrieval. I spent a disproportionate amount of time on chunk size, overlap, chapter weights, query expansion, and importance scoring — and that&#8217;s where most of the quality came from.</p>



<p>Domain knowledge encoded as data beats domain knowledge expected from the model. Rather than hoping the LLM knows that &#8220;step 4&#8221; means a moral inventory, I wrote a query expansion dictionary. Rather than hoping it weights the Constitution higher than a law review article, I stamp authority weights directly onto chunks. The model does not need to be an expert in your domain if your retrieval layer already is.</p>



<p>Evaluation is the hardest part. It&#8217;s easy to build RAG that returns something. It&#8217;s hard to know whether it returned the right thing. I built a verification script that runs a set of representative queries and prints the retrieved chunks with scores. Watching those scores move as I tuned chunk size and chapter weights was how I actually knew the system was improving. Without that feedback loop, you&#8217;re flying blind.</p>



<h2 class="wp-block-heading">What I learned about shipping on-device AI</h2>



<p>iOS 26 and Apple Foundation Models changed the calculus significantly. Before iOS 26, shipping an on-device LLM meant downloading gigabytes and managing memory pressure yourself. After iOS 26, it&#8217;s a Swift API. For anyone building in this space today, that transition is the single most important development.</p>



<p>Core ML conversion has sharp edges. The coremltools package has known issues with Python 3.13, requires specific coremltools versions that support various model architectures, and the documentation assumes you already know what you&#8217;re doing. The path that worked for me was Python 3.11, direct PyTorch-to-CoreML conversion skipping ONNX entirely, FP16 precision, and verifying cosine similarity above 0.999 between the PyTorch reference and the converted Core ML output before trusting anything.</p>



<p>Privacy is not automatically a competitive advantage but it is table stakes for certain domains. Generic users don&#8217;t care much about where their queries go. Users dealing with recovery, therapy, legal issues, medical information, or any topic they consider sensitive care a great deal. Choosing domains where privacy matters makes on-device architecture valuable. Choosing domains where it doesn&#8217;t makes on-device architecture expensive and complicated with no upside.</p>



<h2 class="wp-block-heading">Where this goes next</h2>



<p>CorpusKit Studio is the more interesting long-term product than the iOS app. It&#8217;s infrastructure — a tool for producing deployable RAG corpora from any PDF, with curator controls for importance, authority, and query expansion. The same engine that produces the Big Book corpus can produce a corpus from any closed body of text. Recovery literature, legal documents, medical education, sacred texts, personal libraries.</p>



<p>The iOS app is one consumer of the output. The Mac app is the workshop. The corpus bundle is the portable artifact that connects them. A publisher, a clinician, a sponsor, a curator — none of them needs to touch a terminal to produce a high-quality RAG corpus. That accessibility is what turns this from a personal project into something potentially useful to other people.</p>



<p>I plan to release the Big Book corpus package publicly under a permissive license. The corpus derivation is my work; the source text is public domain; the resulting index is something any CorpusKit-compatible application can consume. The recovery community should have access to this kind of tool, and one app cannot reach everyone — but a well-made corpus can work inside any tool that knows how to read it.</p>



<h2 class="wp-block-heading">The skills this built</h2>



<p>I was explicit with myself at the start that one of the goals was professional skill development. Working through this project end-to-end, I can now credibly speak to:</p>



<p>Retrieval-augmented generation architecture: chunk sizing, overlap, embedding model selection, vector similarity search, query expansion, chapter and importance weighting, evaluation methodology.</p>



<p>On-device LLM inference: model quantization tradeoffs, memory constraints on mobile devices, llama.cpp integration, Apple Foundation Models, Core ML model conversion from PyTorch, FP16 precision considerations.</p>



<p>Production iOS development with AI: SwiftUI architecture, async token streaming, Core ML integration, proper error handling around AI pipelines, the difference between simulator and device behavior, iOS 26 Foundation Models API specifics.</p>



<p>Product decisions in the AI space: when to use RAG versus fine-tuning, how to handle crisis scenarios in sensitive domains, the tradeoffs of closed-source versus open models, cloud versus on-device architectures, the actual versus perceived value of privacy-first design.</p>



<p>The deeper lesson is that doing this work is different from reading about it. I could have spent the same weeks watching tutorials and finished with less real understanding than I got from hitting actual problems and solving them. The errors — the crashes, the zero-vector embeddings, the Python version mismatches, the Core ML conversion failures, the response length that wouldn&#8217;t shorten — were where the learning lived.</p>



<h2 class="wp-block-heading">A note on direction changes</h2>



<p>Looking back, I changed direction in significant ways roughly five times across this project. Each time it felt like a setback. Each time it was actually the right call.</p>



<p>Changing direction is often treated as a failure mode. In software it usually is not. The information you have at the start of a project is always incomplete. The information you have three weeks in is substantially better. Refusing to incorporate new information out of commitment to a plan is a worse outcome than revising the plan honestly.</p>



<p>The original architecture had Phi-4 Mini running via llama.cpp with ODR-split GGUF files, a Flask embedding server during development, and a Python corpus pipeline that only I could run. The final architecture has Apple Foundation Models, Core ML embeddings, a Mac app that any curator can use, and a corpus format designed for portability. The final version is dramatically better than the original plan — and I could not have arrived at it without starting somewhere and paying attention.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p><em>Rob Roy is an independent iOS developer based in Maine. His work and contact are at robroy.online.</em></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2423</post-id>	</item>
		<item>
		<title>Netsolver: What 37 Years of DevOps Taught Me to Build</title>
		<link>https://www.robert-e-roy.com/netsolver-what-37-years-of-devops-taught-me-to-build/</link>
		
		<dc:creator><![CDATA[robroy]]></dc:creator>
		<pubDate>Sun, 22 Mar 2026 17:27:06 +0000</pubDate>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[iOS apps]]></category>
		<guid isPermaLink="false">https://www.robert-e-roy.com/?p=2414</guid>

					<description><![CDATA[After nearly four decades in systems administration and DevOps — including stints at IBM and Disney — I&#8217;ve managed a lot of infrastructure. Racks of servers, sprawling networks, machines spread across time zones. The tools we used were powerful, expensive, and designed for teams. Then I left enterprise. Now I run a home lab with ... <a title="Netsolver: What 37 Years of DevOps Taught Me to Build" class="read-more" href="https://www.robert-e-roy.com/netsolver-what-37-years-of-devops-taught-me-to-build/" aria-label="Read more about Netsolver: What 37 Years of DevOps Taught Me to Build">Read more</a>]]></description>
										<content:encoded><![CDATA[
<h1 class="wp-block-heading"></h1>



<p>After nearly four decades in systems administration and DevOps — including stints at IBM and Disney — I&#8217;ve managed a lot of infrastructure. Racks of servers, sprawling networks, machines spread across time zones. The tools we used were powerful, expensive, and designed for teams.</p>



<p>Then I left enterprise. Now I run a home lab with a handful of Linux boxes, a NAS, a Raspberry Pi or two, and a Mac Mini acting as a server. Nothing exotic. But the same problems I had at IBM still show up at 11pm when something goes quietly offline and I&#8217;m nowhere near a desk.</p>



<p>I wanted one app on my iPhone that could tell me what was happening on my network. Not a cloud dashboard with per-seat pricing. Not a terminal emulator with no context. Something purpose-built for the person who runs a small fleet of machines they actually own.</p>



<p>So I built Netsolver.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">The problem with existing tools</h2>



<p>Enterprise RMM tools — NinjaRMM, ConnectWise, Atera — are genuinely excellent if you&#8217;re managing hundreds of endpoints for paying clients. But they start at per-agent pricing that makes no sense for eight machines in your basement. The onboarding alone assumes you have an IT team.</p>



<p>On the other end, there are SSH clients. Good ones. I&#8217;ve used them for years. But an SSH client is a blank terminal. It doesn&#8217;t know what&#8217;s on your network, it doesn&#8217;t alert you when something goes down, and it doesn&#8217;t integrate with the rest of your phone.</p>



<p>There&#8217;s a gap between &#8220;full enterprise RMM&#8221; and &#8220;just SSH.&#8221; That gap is exactly where most home lab operators and small businesses live. That&#8217;s what Netsolver is for.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">What it does</h2>



<h3 class="wp-block-heading">LAN scanning that actually tells you something</h3>



<p>When you open Netsolver, it scans your local network and finds every device. But it doesn&#8217;t just list IP addresses — it probes each host for running services. SSH on port 22. SMB on 445. DNS on 53. RDP on 3389. MySQL on 3306.</p>



<p>The result is an immediate picture of your network. You can filter hosts by detected service — tap &#8220;SSH&#8221; and see every machine you can log into. Tap &#8220;RDP&#8221; and see your Windows boxes. This is information I used to piece together from nmap output and spreadsheets. Now it&#8217;s on my phone in seconds.</p>



<h3 class="wp-block-heading">SSH with saved commands</h3>



<p>Connecting to a host takes one tap. You can run any command and see the output. But where it gets useful is saved commands — per-host shortcuts for the things you run all the time. <code>df -h /</code> to check disk. <code>uptime</code> to see load. <code>systemctl status nginx</code> to check a service.</p>



<p>On iPad, saved commands sit in a persistent panel alongside the terminal. On iPhone, they live in a strip above the keyboard. No more retyping the same commands every session.</p>



<h3 class="wp-block-heading">Agent deployment and monitoring</h3>



<p>This is where Netsolver goes beyond an SSH client.</p>



<p>You can deploy a lightweight monitoring agent to any Linux or Mac host directly from the app. One tap — Netsolver connects via SSH, uploads the agent, and installs it as a system service. The agent phones home and starts reporting CPU, memory, and disk usage.</p>



<p>You set the thresholds. CPU above 85%? Disk above 90%? The agent fires a push notification to your iPhone via APNs. No polling, no background refresh, no battery drain. The server tells your phone something is wrong.</p>



<h3 class="wp-block-heading">Alerts that actually do something</h3>



<p>Here&#8217;s the part that genuinely surprised me when I built it.</p>



<p>iOS Shortcuts integration means an alert isn&#8217;t just a notification — it can trigger an action. When a monitored host hits a CPU threshold, Netsolver can fire a Shortcut. That Shortcut can send you a message on a specific channel, log the event to a spreadsheet, kick off a webhook, or run any automation you&#8217;ve already built on your phone.</p>



<p>I&#8217;ve worked with monitoring systems that cost thousands of dollars a month and didn&#8217;t have this kind of flexibility. The fact that it&#8217;s available to a home lab operator for the price of an iOS app still seems remarkable to me.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">What I learned building it</h2>



<p>This is my first production iOS app after 37 years of infrastructure work. A few things surprised me.</p>



<p><strong>The hard part wasn&#8217;t the network code.</strong> LAN scanning, SSH, SFTP — this is the stuff I know. The hard part was SwiftUI. Specifically, building an adaptive layout that works well on iPhone <em>and</em> iPad <em>and</em> adapts gracefully when the user rotates, changes window size, or uses split view. Apple&#8217;s <code>NavigationSplitView</code> is elegant once you understand it, but it took me a while to understand it.</p>



<p><strong>Privacy-first design is harder than it sounds.</strong> I wanted zero cloud, zero account, credentials in the Keychain only. That&#8217;s the right decision for an app that handles SSH keys. But it means solving problems that cloud sync would solve for free — like keeping inventory in sync across your iPhone and iPad. SwiftData with CloudKit private database turned out to be the right answer, but getting there took research.</p>



<p><strong>The Shortcuts integration was genuinely fun.</strong> I&#8217;ve been writing automation scripts my whole career. Hooking into iOS Shortcuts and watching a server alert trigger a cascade of phone-side automation felt like two worlds I care about finally talking to each other.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Who it&#8217;s for</h2>



<p>Netsolver is built for three kinds of people:</p>



<p><strong>Home lab operators</strong> running 3–10 machines. You have a NAS, a Pi or two, maybe a repurposed desktop. You want to know they&#8217;re up, and you want to SSH in without hunting for credentials.</p>



<p><strong>Small business owners</strong> with a handful of servers or sites to watch. You don&#8217;t want to pay enterprise RMM pricing for eight machines. You want a native iOS app that just works.</p>



<p><strong>Freelance developers and web designers</strong> who SSH into client servers regularly. You want saved commands, SFTP access, and a way to know immediately if a client site goes dark.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Coming soon</h2>



<p>Netsolver is in final development. The core is working: scanning, SSH, SFTP, agent deployment, APNs alerts, and Shortcuts integration. I&#8217;m working through the UI polish and App Store submission process now.</p>



<p>If you run a home lab or manage a small fleet of machines, this is being built for you.</p>



<p>I&#8217;ll post an update here when it&#8217;s available on the App Store. In the meantime, you can find my other apps and development work at <a href="https://robroy.online">robroy.online</a>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p><em>Rob Roy is an indie iOS and macOS developer based in Maine with 37 years of software development experience, including DevOps and systems administration roles at IBM and Disney.</em></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2414</post-id>	</item>
		<item>
		<title>Xcode Debugging hint</title>
		<link>https://www.robert-e-roy.com/xcode-debugging-hint/</link>
		
		<dc:creator><![CDATA[robroy]]></dc:creator>
		<pubDate>Sun, 15 Mar 2026 16:26:04 +0000</pubDate>
				<category><![CDATA[Articles]]></category>
		<guid isPermaLink="false">https://www.robert-e-roy.com/?p=2412</guid>

					<description><![CDATA[A lightweight, zero-cost debugging utility for Swift projects that automatically strips debug statements from release builds. ## Overview The `DebugHelpers.swift` file provides debug logging macros that are completely removed during release builds, ensuring zero performance impact in production. ## Features &#8211; **Zero runtime cost in release builds** &#8211; All debug code is stripped at compile ... <a title="Xcode Debugging hint" class="read-more" href="https://www.robert-e-roy.com/xcode-debugging-hint/" aria-label="Read more about Xcode Debugging hint">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p data-wp-context---core-fit-text="core/fit-text::{&quot;fontSize&quot;:&quot;&quot;}" data-wp-init---core-fit-text="core/fit-text::callbacks.init" data-wp-interactive data-wp-style--font-size="core/fit-text::context.fontSize" class="has-fit-text">A lightweight, zero-cost debugging utility for Swift projects that automatically strips debug statements from release builds.</p>



<p>## Overview</p>



<p>The `DebugHelpers.swift` file provides debug logging macros that are completely removed during release builds, ensuring zero performance impact in production.</p>



<p>## Features</p>



<p>&#8211; **Zero runtime cost in release builds** &#8211; All debug code is stripped at compile time</p>



<p>&#8211; **Simple API** &#8211; Drop-in replacement for `print()`</p>



<p>&#8211; **File and line tracking** &#8211; Optional detailed logging with source location</p>



<p>&#8211; **Debug assertions** &#8211; Catch issues early in development</p>



<p>## Usage</p>



<p>### Basic Debug Logging</p>



<p>Replace `print()` with `DLOG()`:</p>



<p>&#8220;`swift</p>



<p>// Old way (appears in release builds):</p>



<p>print(&#8220;User logged in:&#8221;, username)</p>



<p>// New way (stripped from release builds):</p>



<p>DLOG(&#8220;User logged in:&#8221;, username)</p>



<p>&#8220;`</p>



<p>### Debug Logging with Source Location</p>



<p>When you need to know exactly where a log came from:</p>



<p>&#8220;`swift</p>



<p>DLOG_TRACE(&#8220;Error occurred&#8221;)</p>



<p>// Output: [ViewController.swift:42] Error occurred</p>



<p>&#8220;`</p>



<p>### Debug Assertions</p>



<p>Catch programming errors during development:</p>



<p>&#8220;`swift</p>



<p>DASSERT(user.age &gt; 0, &#8220;User age must be positive&#8221;)</p>



<p>// Only fires in DEBUG builds</p>



<p>// In release: completely removed</p>



<p>&#8220;`</p>



<p>## API Reference</p>



<p>### `DLOG(_ items: Any&#8230;, separator: String = &#8221; &#8220;, terminator: String = &#8220;\n&#8221;)`</p>



<p>Basic debug print that works exactly like Swift&#8217;s `print()` but only in DEBUG builds.</p>



<p>**Parameters:**</p>



<p>&#8211; `items` &#8211; Values to print</p>



<p>&#8211; `separator` &#8211; String to separate values (default: &#8221; &#8220;)</p>



<p>&#8211; `terminator` &#8211; String to end the line (default: &#8220;\n&#8221;)</p>



<p>**Example:**</p>



<p>&#8220;`swift</p>



<p>DLOG(&#8220;Processing&#8221;, itemCount, &#8220;items&#8221;)</p>



<p>&#8220;`</p>



<p>### `DLOG_TRACE(_ items: Any&#8230;, file: String = #file, line: Int = #line)`</p>



<p>Debug print with file and line number information.</p>



<p>**Parameters:**</p>



<p>&#8211; `items` &#8211; Values to print</p>



<p>&#8211; `file` &#8211; Source file (automatically captured)</p>



<p>&#8211; `line` &#8211; Line number (automatically captured)</p>



<p>**Example:**</p>



<p>&#8220;`swift</p>



<p>DLOG_TRACE(&#8220;Unexpected state&#8221;)</p>



<p>// Output: [MyView.swift:127] Unexpected state</p>



<p>&#8220;`</p>



<p>### `DASSERT(_ condition: Bool, _ message: String = &#8220;&#8221;, file: String = #file, line: Int = #line)`</p>



<p>Debug-only assertion that crashes the app if condition is false.</p>



<p>**Parameters:**</p>



<p>&#8211; `condition` &#8211; Boolean condition to check</p>



<p>&#8211; `message` &#8211; Description of the assertion</p>



<p>&#8211; `file` &#8211; Source file (automatically captured)</p>



<p>&#8211; `line` &#8211; Line number (automatically captured)</p>



<p>**Example:**</p>



<p>&#8220;`swift</p>



<p>DASSERT(array.count &gt; 0, &#8220;Array should not be empty&#8221;)</p>



<p>&#8220;`</p>



<p>## How It Works</p>



<p>The macros use Swift&#8217;s `#if DEBUG` preprocessor directive:</p>



<p>&#8220;`swift</p>



<p>func DLOG(_ items: Any&#8230;) {</p>



<p>&nbsp; &nbsp; #if DEBUG</p>



<p>&nbsp; &nbsp; print(items)</p>



<p>&nbsp; &nbsp; #endif</p>



<p>}</p>



<p>&#8220;`</p>



<p>When you build for release (without the DEBUG flag), the compiler completely removes all code inside `#if DEBUG` blocks. This means:</p>



<p>&#8211; No runtime overhead</p>



<p>&#8211; No string allocations</p>



<p>&#8211; No function calls</p>



<p>&#8211; Zero bytes in the binary</p>



<p>## Setting Up in New Projects</p>



<p>### Option 1: File Template</p>



<p>1. Create the template directory:</p>



<p>&#8220;`bash</p>



<p>mkdir -p ~/Library/Developer/Xcode/Templates/File\ Templates/Custom/Debug\ Helper.xctemplate</p>



<p>&#8220;`</p>



<p>2. Copy the template files to that directory</p>



<p>3. Restart Xcode</p>



<p>4. New file → Custom → Debug Helper</p>



<p>### Option 2: Code Snippet</p>



<p>1. In Xcode, select the `DebugHelpers.swift` code</p>



<p>2. Right-click → Create Code Snippet</p>



<p>3. Set completion shortcut: `debughelpers`</p>



<p>4. In any project, type `debughelpers` + Enter</p>



<p>### Option 3: Manual Copy</p>



<p>Simply drag `DebugHelpers.swift` into your new project.</p>



<p>## Best Practices</p>



<p>### DO:</p>



<p>&#8211; Use `DLOG()` for temporary debugging during development</p>



<p>&#8211; Use `DLOG_TRACE()` when you need to track execution flow</p>



<p>&#8211; Use `DASSERT()` to catch programming errors early</p>



<p>&#8211; Remove debug statements once issues are resolved</p>



<p>### DON&#8217;T:</p>



<p>&#8211; Don&#8217;t use for production logging (use OSLog or a logging framework)</p>



<p>&#8211; Don&#8217;t log sensitive information (even in debug builds)</p>



<p>&#8211; Don&#8217;t use as a permanent logging solution</p>



<p>## Benefits Over `print()`</p>



<p>| Feature | `print()` | `DLOG()` |</p>



<p>|&#8212;&#8212;&#8212;|&#8212;&#8212;&#8212;&#8211;|&#8212;&#8212;&#8212;-|</p>



<p>| Works in DEBUG | <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> | <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> |</p>



<p>| Works in RELEASE | <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> | <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> (intentional) |</p>



<p>| Runtime cost in release | <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Yes | <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Zero |</p>



<p>| Binary size impact | <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Increases | <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> None |</p>



<p>| String evaluation cost | <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Always | <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> DEBUG only |</p>



<p>## Migration Guide</p>



<p>### Finding print statements to replace:</p>



<p>&#8220;`bash</p>



<p># Find all print() calls in Swift files</p>



<p>grep -r &#8220;print(&#8221; &#8211;include=&#8221;*.swift&#8221; .</p>



<p>&#8220;`</p>



<p>### Replace with DLOG:</p>



<p>&#8220;`swift</p>



<p>// Before:</p>



<p>print(&#8220;Loading data&#8230;&#8221;)</p>



<p>print(&#8220;Items:&#8221;, items.count)</p>



<p>print(&#8220;Error:&#8221;, error.localizedDescription)</p>



<p>// After:</p>



<p>DLOG(&#8220;Loading data&#8230;&#8221;)</p>



<p>DLOG(&#8220;Items:&#8221;, items.count)</p>



<p>DLOG(&#8220;Error:&#8221;, error.localizedDescription)</p>



<p>&#8220;`</p>



<p>## Advanced Usage</p>



<p>### Custom Debug Helpers</p>



<p>You can extend the pattern for specific needs:</p>



<p>&#8220;`swift</p>



<p>#if DEBUG</p>



<p>func DLOG_NETWORK(_ url: URL, _ response: HTTPURLResponse?) {</p>



<p>&nbsp; &nbsp; print(&#8220;<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f310.png" alt="🌐" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Network: \(url)&#8221;)</p>



<p>&nbsp; &nbsp; if let status = response?.statusCode {</p>



<p>&nbsp; &nbsp; &nbsp; &nbsp; print(&#8221; &nbsp; Status: \(status)&#8221;)</p>



<p>&nbsp; &nbsp; }</p>



<p>}</p>



<p>#else</p>



<p>func DLOG_NETWORK(_ url: URL, _ response: HTTPURLResponse?) {}</p>



<p>#endif</p>



<p>&#8220;`</p>



<p>### Conditional Compilation Flags</p>



<p>Check your build configuration:</p>



<p>&#8211; Xcode → Target → Build Settings → Swift Compiler &#8211; Custom Flags</p>



<p>&#8211; DEBUG should be in &#8220;Other Swift Flags&#8221; for Debug configuration: `-D DEBUG`</p>



<p>## Troubleshooting</p>



<p>### &#8220;DLOG is showing in release builds&#8221;</p>



<p>Check your build configuration:</p>



<p>1. Select your target</p>



<p>2. Build Settings → Swift Compiler &#8211; Custom Flags</p>



<p>3. Debug configuration should have `-D DEBUG`</p>



<p>4. Release configuration should NOT have `-D DEBUG`</p>



<p>### &#8220;Cannot find DLOG in scope&#8221;</p>



<p>Make sure `DebugHelpers.swift` is included in your target&#8217;s compile sources:</p>



<p>1. Select the file in project navigator</p>



<p>2. File Inspector → Target Membership</p>



<p>3. Check your app target</p>



<p>## Performance Notes</p>



<p>In DEBUG builds, these macros have the same performance as `print()`.</p>



<p>In RELEASE builds:</p>



<p>&#8211; **Zero CPU cost** &#8211; Code doesn&#8217;t exist</p>



<p>&#8211; **Zero memory cost** &#8211; Strings not allocated</p>



<p>&#8211; **Zero binary size** &#8211; Completely stripped</p>



<p>Example binary size comparison on a real project:</p>



<p>&#8211; With 100 `print()` statements: +8KB</p>



<p>&#8211; With 100 `DLOG()` statements: +0KB i</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2412</post-id>	</item>
		<item>
		<title>Introducing Flying Moose Alchemy</title>
		<link>https://www.robert-e-roy.com/introducing-flying-moose-alchemy/</link>
		
		<dc:creator><![CDATA[robroy]]></dc:creator>
		<pubDate>Fri, 06 Mar 2026 18:01:15 +0000</pubDate>
				<category><![CDATA[Articles]]></category>
		<guid isPermaLink="false">https://www.robert-e-roy.com/?p=2399</guid>

					<description><![CDATA[I&#8217;ve been building websites for over two decades — starting with hand-coded HTML long before WordPress existed, and growing with the web ever since. Alongside my app development work, I take on web design projects for small businesses that need a real web presence without a big agency price tag. Why I Do This Same ... <a title="Introducing Flying Moose Alchemy" class="read-more" href="https://www.robert-e-roy.com/introducing-flying-moose-alchemy/" aria-label="Read more about Introducing Flying Moose Alchemy">Read more</a>]]></description>
										<content:encoded><![CDATA[
<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>I&#8217;ve been building websites for over two decades — starting with hand-coded HTML long before WordPress existed, and growing with the web ever since. Alongside my app development work, I take on web design projects for small businesses that need a real web presence without a big agency price tag.</p>



<h2 class="wp-block-heading">Why I Do This</h2>



<p>Same reason I build free apps for the recovery community — I like helping people. Small business owners are usually great at what they do and deserve a website that reflects that. What they don&#8217;t always have is the time, budget, or technical background to make it happen. That&#8217;s where I come in.</p>



<p>A recent example is <a href="https://flyingmoosealchemy.com" target="_blank" rel="noreferrer noopener">Flying Moose Alchemy</a>, a unique art and craft business I built a site for. Every business has its own story — the job is making sure the website tells it.</p>



<h2 class="wp-block-heading">WordPress, So You Stay Independent</h2>



<p>Every site I build is on WordPress, and that&#8217;s a deliberate choice. A lot of web designers hand you a finished site and then you&#8217;re dependent on them for every small change. I don&#8217;t work that way. WordPress means you can log in and update your own content — add a new product, change your hours, post an announcement — without calling anyone or paying for a simple edit. You own your site and you can run it yourself.</p>



<p>Twenty years of working with WordPress also means I know it well enough to build something clean and fast, not just something that technically works.</p>



<h2 class="wp-block-heading">For Businesses That Are a Little Different</h2>



<p>I&#8217;m particularly drawn to unique small businesses — the ones that don&#8217;t fit a template. Cookie-cutter sites work fine for cookie-cutter businesses. If what you do is distinctive, your website should reflect that. I take the time to understand what makes your business worth talking about and build something that actually communicates it.</p>



<h2 class="wp-block-heading">Affordable by Design</h2>



<p>I&#8217;m a solo developer working lean, which means my overhead is low and I can offer real value at a price that makes sense for a small business. You&#8217;re not paying for a sales team, account managers, or a fancy office. You&#8217;re paying for two decades of experience and someone who actually cares whether your site works for you.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>If you&#8217;re a small business owner thinking about a new site or a redesign, get in touch at <a href="mailto:contact@robroy.online">contact@robroy.online</a>. I&#8217;m happy to talk through what you need before you commit to anything.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2399</post-id>	</item>
		<item>
		<title>Introducing 12and12 — A Free Widget App for Anyone in Recovery</title>
		<link>https://www.robert-e-roy.com/introducing-12and12-a-free-widget-app-for-anyone-in-recovery/</link>
		
		<dc:creator><![CDATA[robroy]]></dc:creator>
		<pubDate>Fri, 06 Mar 2026 17:41:00 +0000</pubDate>
				<category><![CDATA[iOS apps]]></category>
		<category><![CDATA[Software]]></category>
		<guid isPermaLink="false">https://www.robert-e-roy.com/?p=2396</guid>

					<description><![CDATA[Not every app I build is about solving a technical problem. Sometimes it&#8217;s about giving something back. 12and12 is a free iOS app that puts daily recovery readings right on your home screen and lock screen as widgets. No subscriptions, no ads, no catch. I built it because the recovery community has given a lot ... <a title="Introducing 12and12 — A Free Widget App for Anyone in Recovery" class="read-more" href="https://www.robert-e-roy.com/introducing-12and12-a-free-widget-app-for-anyone-in-recovery/" aria-label="Read more about Introducing 12and12 — A Free Widget App for Anyone in Recovery">Read more</a>]]></description>
										<content:encoded><![CDATA[
<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>Not every app I build is about solving a technical problem. Sometimes it&#8217;s about giving something back.</p>



<p>12and12 is a free iOS app that puts daily recovery readings right on your home screen and lock screen as widgets. No subscriptions, no ads, no catch. I built it because the recovery community has given a lot of people — including people I care about — something invaluable, and this was a way I could contribute something back using the skills I have.</p>



<h2 class="wp-block-heading">What It Does</h2>



<p>The app provides home screen and lock screen widgets with daily readings drawn from the 12 Steps and 12 Traditions. The idea is simple: keep your recovery front and center throughout the day, right where you&#8217;re already looking. You don&#8217;t have to open an app, navigate a menu, or remember to check in. The reading is just there.</p>



<h2 class="wp-block-heading">Why Widgets</h2>



<p>A lot of recovery apps ask you to open them daily, which adds friction. Widgets work differently — they&#8217;re part of your phone&#8217;s background, something you see naturally as you go about your day. A brief reminder on your lock screen when you pick up your phone in the morning costs nothing and takes no effort. That low friction felt right for something meant to support a daily practice.</p>



<h2 class="wp-block-heading">It&#8217;s Completely Free</h2>



<p>There&#8217;s no paid version, no premium tier, no in-app purchases. 12and12 is free because that&#8217;s the point. Recovery communities are built on people helping people without expectation of anything in return. This app is my version of that.</p>



<h2 class="wp-block-heading">How to Get It</h2>



<p>12and12 is available now on the App Store for iPhone. After you download it, add a widget to your home screen or lock screen through the standard iOS widget menu — press and hold your home screen, tap the + button, and search for 12and12.</p>



<p><a href="https://apps.apple.com/app/12-and-12/id6758464299">Download 12and12 on the App Store</a></p>



<p>If it&#8217;s useful to you or someone you know, I&#8217;m glad. That&#8217;s enough.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2396</post-id>	</item>
		<item>
		<title>I Used Claude Code to Build SmartFiler — Here&#8217;s the Honest Truth</title>
		<link>https://www.robert-e-roy.com/i-used-claude-code-to-build-smartfiler-heres-the-honest-truth/</link>
		
		<dc:creator><![CDATA[robroy]]></dc:creator>
		<pubDate>Fri, 06 Mar 2026 17:31:05 +0000</pubDate>
				<category><![CDATA[Articles]]></category>
		<guid isPermaLink="false">https://www.robert-e-roy.com/?p=2389</guid>

					<description><![CDATA[When I started building SmartFiler, I decided to use Claude Code throughout the development process. Not as a curiosity, but as a real part of my workflow. I&#8217;m an indie developer — solo, no team — so anything that moves the needle on speed matters. After shipping the app, here&#8217;s what I actually found. What ... <a title="I Used Claude Code to Build SmartFiler — Here&#8217;s the Honest Truth" class="read-more" href="https://www.robert-e-roy.com/i-used-claude-code-to-build-smartfiler-heres-the-honest-truth/" aria-label="Read more about I Used Claude Code to Build SmartFiler — Here&#8217;s the Honest Truth">Read more</a>]]></description>
										<content:encoded><![CDATA[
<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>When I started building SmartFiler, I decided to use Claude Code throughout the development process. Not as a curiosity, but as a real part of my workflow. I&#8217;m an indie developer — solo, no team — so anything that moves the needle on speed matters. After shipping the app, here&#8217;s what I actually found.</p>



<h2 class="wp-block-heading">What Claude Code Is (Quick Version)</h2>



<p>Claude Code is an AI coding assistant you run from the command line. Unlike a chatbot you paste code into, it operates directly in your project — reading files, writing code, running commands. It&#8217;s aware of your actual codebase, not just whatever snippet you hand it.</p>



<h2 class="wp-block-heading">Where It Really Helped</h2>



<h3 class="wp-block-heading">Getting a Prototype Running Fast</h3>



<p>This is where Claude Code genuinely impressed me. I could describe what I wanted — a file organizer with rule-based sorting, duplicate detection, batch renaming — and get a working prototype up and running much faster than I would have alone. Not perfect code, but running code. For a solo developer trying to validate an idea quickly, that&#8217;s valuable. The early momentum it created was real.</p>



<h3 class="wp-block-heading">Algorithms</h3>



<p>Some of the more specific algorithms in SmartFiler — the SHA-256 duplicate detection, the fuzzy filename matching — Claude Code handled well. Give it a clear problem with defined inputs and outputs and it produces solid, correct implementations. I didn&#8217;t have to spend hours digging through documentation or working out the logic from scratch. Describe the problem clearly, review the output carefully, and you&#8217;re in good shape.</p>



<h2 class="wp-block-heading">Where It Fell Short</h2>



<h3 class="wp-block-heading">Architecture — Don&#8217;t Trust It Here</h3>



<p>This is the big one. Left to its own devices, Claude Code does not naturally write modular, maintainable code. It tends to produce code that works but is tangled — logic that belongs in separate modules ends up in one place, responsibilities bleed across files, things get hard to follow fast. On a small prototype that doesn&#8217;t matter much. On a real app you&#8217;re going to maintain and extend, it matters a lot.</p>



<p>My fix: I explicitly prompted it to rewrite sections in the most modular form possible. That instruction has to come from you — it won&#8217;t volunteer it. Once I started treating &#8220;make this more modular&#8221; as a standard part of my workflow, the output got significantly better. But you have to know to ask.</p>



<h3 class="wp-block-heading">It Needs Guidance, Not Just Requests</h3>



<p>The mental model that helped me most: Claude Code is a skilled contractor, not a senior architect. If you hand a good contractor a clear spec, they&#8217;ll execute it well. If you ask them to figure out the structure of the whole project, you&#8217;ll get something that technically works but probably isn&#8217;t how you&#8217;d have done it yourself. The guidance still has to come from you.</p>



<h2 class="wp-block-heading">The Most Valuable Use I Found</h2>



<p>Code review — but not the way you might expect. I reviewed the code myself, identified what needed improving, and then directed Claude Code to make specific changes based on my assessment. As a solo developer you don&#8217;t have a teammate to bounce ideas off, so having something that can execute your improvement suggestions quickly is genuinely useful. The critical thinking still came from me. Claude Code handled the implementation.</p>



<p>My workflow became: write or generate code → review it myself → direct Claude Code on what to fix or improve → repeat. That loop worked well, and it kept me in control of where the codebase was heading.</p>



<h2 class="wp-block-heading">My Honest Take for Indie Developers</h2>



<p>Claude Code is a real productivity tool, not just hype — but it&#8217;s not a shortcut to skip thinking about your software. The developers who will get the most out of it are the ones who already know what good code looks like and can evaluate what it produces. If you&#8217;re experienced enough to recognize when it&#8217;s going sideways, it&#8217;ll speed you up considerably. If you&#8217;re not yet at that point, it could just as easily lead you in a bad direction faster.</p>



<p>For SmartFiler, it accelerated the early stages significantly and helped me punch above my weight as a solo dev. I&#8217;ll use it on my next project. But I&#8217;ll be the one making the architectural decisions.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>SmartFiler is currently under App Store review. You can read more about it on the <a href="https://robroy.online/smartfileorganizer/">product page</a>. If you&#8217;re an indie developer using AI tools in your workflow, I&#8217;d be curious what you&#8217;re finding — drop me a line at <a href="mailto:contact@robroy.online">contact@robroy.online</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2389</post-id>	</item>
		<item>
		<title>Introducing SmartFiler — A Mac File Organizer I Actually Wanted to Use</title>
		<link>https://www.robert-e-roy.com/introducing-smartfiler-a-mac-file-organizer-i-actually-wanted-to-use/</link>
		
		<dc:creator><![CDATA[robroy]]></dc:creator>
		<pubDate>Fri, 06 Mar 2026 17:21:46 +0000</pubDate>
				<category><![CDATA[Mac OS]]></category>
		<category><![CDATA[Software]]></category>
		<guid isPermaLink="false">https://www.robert-e-roy.com/?p=2387</guid>

					<description><![CDATA[I just submitted SmartFiler to the Mac App Store, and I&#8217;m pretty excited about this one. It&#8217;s a file organization tool for macOS that I built because every alternative I tried was either too complicated, too aggressive with your files, or just didn&#8217;t fit the way I actually work. Here&#8217;s what it does. Find Duplicates ... <a title="Introducing SmartFiler — A Mac File Organizer I Actually Wanted to Use" class="read-more" href="https://www.robert-e-roy.com/introducing-smartfiler-a-mac-file-organizer-i-actually-wanted-to-use/" aria-label="Read more about Introducing SmartFiler — A Mac File Organizer I Actually Wanted to Use">Read more</a>]]></description>
										<content:encoded><![CDATA[
<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>I just submitted <strong>SmartFiler</strong> to the Mac App Store, and I&#8217;m pretty excited about this one. It&#8217;s a file organization tool for macOS that I built because every alternative I tried was either too complicated, too aggressive with your files, or just didn&#8217;t fit the way I actually work.</p>



<p>Here&#8217;s what it does.</p>



<h2 class="wp-block-heading">Find Duplicates — by Name or by Content</h2>



<p>SmartFiler can scan a folder and find duplicate files two ways: matching filenames, or matching actual file content using SHA-256 hashing. The content match is the one you want — it catches files that got renamed but are still identical copies taking up space. You review everything before anything gets deleted, and when you do delete, it goes to Trash, not gone forever.</p>



<h2 class="wp-block-heading">Smart Buckets</h2>



<p>This is my favorite feature. You define rules — by filename, path, or extension — and SmartFiler sorts your files into named folders automatically. Set up a bucket for invoices, one for screenshots, one for project files. You drag to reorder priority, toggle buckets on and off, and nothing moves until you say go.</p>



<h2 class="wp-block-heading">Similar Files</h2>



<p>Fuzzy filename matching that surfaces files that are probably related — like <code>report_2025.pdf</code> and <code>report_2026.pdf</code>. You control how loose or strict the matching is with a slider. Useful for cleaning up versioned files that accumulated over time.</p>



<h2 class="wp-block-heading">Auto-Organize by Pattern</h2>



<p>Point SmartFiler at a messy folder and it analyzes the files and suggests groupings — by file type, date, numbered sequences, or common name prefixes. You review the suggested groups, check or uncheck what you want, preview the changes, then organize. No surprises.</p>



<h2 class="wp-block-heading">Filename Cleaner</h2>



<p>Batch rename files to strip out special characters, fix spacing, change case, or apply a regex pattern. If you&#8217;ve ever downloaded a folder of files with names like <code>IMG_20240315_094512_FINAL_v2 (1).jpg</code>, you know why this exists.</p>



<h2 class="wp-block-heading">Built Around Preview First</h2>



<p>Every operation in SmartFiler shows you what&#8217;s going to happen before it happens. You can cancel long-running scans at any time. Deletions go to Trash. I built it this way on purpose — file operations are the kind of thing where you really don&#8217;t want surprises.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>SmartFiler is currently under review at the Mac App Store. I&#8217;ll post the link here as soon as it&#8217;s live. In the meantime, you can check out the <a href="https://robroy.online/smartfileorganizer/">product page</a> for more details.</p>



<p>If you&#8217;ve got feedback or questions, drop me a line at <a href="mailto:contact@robroy.online">contact@robroy.online</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2387</post-id>	</item>
		<item>
		<title>Evidr</title>
		<link>https://www.robert-e-roy.com/evidr/</link>
		
		<dc:creator><![CDATA[robroy]]></dc:creator>
		<pubDate>Wed, 04 Mar 2026 20:24:43 +0000</pubDate>
				<category><![CDATA[iOS apps]]></category>
		<category><![CDATA[Software]]></category>
		<guid isPermaLink="false">https://www.robert-e-roy.com/?p=2377</guid>

					<description><![CDATA[Document everything. Prove anything. For Homeowners When dealing with property damage, theft, vandalism, or disputes, keep all your evidence organized and ready to share. For Developers Track bugs with structured reports — severity, steps to reproduce, expected vs. actual behavior, and environment details.]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-pullquote"><blockquote><p><a href="https://www.robroy.online/evidr/" data-type="link" data-id="https://www.robroy.online/evidr/">Document</a> everything. Prove anything.</p></blockquote></figure>



<h3 class="wp-block-heading">For Homeowners</h3>



<p>When dealing with property damage, theft, vandalism, or disputes, keep all your evidence organized and ready to share.</p>



<ul class="wp-block-list">
<li>Security camera footage</li>



<li>Photos &amp; documents</li>



<li>Insurance claim reports</li>



<li>Timestamped notes</li>



<li>Professional PDF exports</li>
</ul>



<h3 class="wp-block-heading">For Developers</h3>



<p>Track bugs with structured reports — severity, steps to reproduce, expected vs. actual behavior, and environment details.</p>



<ul class="wp-block-list">
<li>Bug ID &amp; severity tracking</li>



<li>Steps to reproduce</li>



<li>Expected vs. actual behavior</li>



<li>Environment details</li>



<li>Screenshot attachments</li>
</ul>



<p></p>



<figure class="wp-block-image size-large"><a href="https://apps.apple.com/app/evidr/id6759003012" target="_blank" rel=" noreferrer noopener"><img decoding="async" src="https://tools.applemediaservices.com/api/badges/download-on-the-app-store/black/en-us?size=250x83" alt=""/></a></figure>



<p></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2377</post-id>	</item>
		<item>
		<title>Problem with my Blink home security camera</title>
		<link>https://www.robert-e-roy.com/problem-with-my-blink-home-security-camera/</link>
		
		<dc:creator><![CDATA[robroy]]></dc:creator>
		<pubDate>Fri, 30 Jan 2026 22:50:07 +0000</pubDate>
				<category><![CDATA[Articles]]></category>
		<guid isPermaLink="false">https://www.robert-e-roy.com/?p=2345</guid>

					<description><![CDATA[If you own a Blink security camera, you&#8217;ve probably discovered a frustrating limitation:&#160;Blink videos don&#8217;t show timestamps on the actual footage. This seemingly basic feature is missing from all Blink camera models, and it&#8217;s causing real problems for users who need their footage for insurance claims, legal evidence, or simply knowing when something happened. The ... <a title="Problem with my Blink home security camera" class="read-more" href="https://www.robert-e-roy.com/problem-with-my-blink-home-security-camera/" aria-label="Read more about Problem with my Blink home security camera">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p></p>



<p>If you own a Blink security camera, you&#8217;ve probably discovered a frustrating limitation:&nbsp;<strong>Blink videos don&#8217;t show timestamps on the actual footage</strong>. This seemingly basic feature is missing from all Blink camera models, and it&#8217;s causing real problems for users who need their footage for insurance claims, legal evidence, or simply knowing when something happened.</p>



<h2 class="wp-block-heading">The Problem: Missing Timestamps Make Videos Legally Useless</h2>



<p>Here&#8217;s what happens when you try to use Blink camera footage:</p>



<h3 class="wp-block-heading">For Insurance Claims</h3>



<p>You had a package stolen from your porch at 3:47 PM on Tuesday. You have crystal-clear Blink footage of the thief. But when you submit it to your insurance company, they reject it because&nbsp;<strong>there&#8217;s no timestamp visible on the video</strong>.</p>



<p>The insurance adjuster can&#8217;t verify when the theft occurred. Your claim is denied.</p>



<h3 class="wp-block-heading">For Police Reports</h3>



<p>Someone vandalized your car overnight. Your Blink Outdoor camera caught everything. But the police need to know the exact time to correlate with other incidents in the area. Without a timestamp on the video itself, your evidence is circumstantial at best.</p>



<h3 class="wp-block-heading">For Legal Documentation</h3>



<p>You&#8217;re in a property dispute with a neighbor. You have video proof of them trespassing. But in court, opposing counsel argues the video could be from any time, any day. Without a visible timestamp, your evidence loses credibility.</p>



<h2 class="wp-block-heading">Why Doesn&#8217;t Blink Include Timestamps?</h2>



<p>This is the million-dollar question. Other security camera brands like Ring, Nest, and Arlo all include timestamps on their footage. So why doesn&#8217;t Blink?</p>



<p><strong>Blink&#8217;s own website</strong>&nbsp;acknowledges that footage needs &#8220;clear time and date&#8221; to be used as evidence in court. Yet they don&#8217;t provide this feature.</p>



<p>The timestamp information exists—it&#8217;s stored in the video file&#8217;s metadata and shown in the Blink app&#8217;s thumbnail view. But it&#8217;s not burned into the actual video, which makes it useless for official purposes.</p>



<h2 class="wp-block-heading">What Blink Users Are Saying</h2>



<p>On Reddit&#8217;s r/BlinkCameras and Blink&#8217;s own community forums, users have been complaining about this for years:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>&#8220;Had I known beforehand, I would have never purchased a blink camera. All of our videos are legally useless without a timestamp.&#8221;</p>
</blockquote>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>&#8220;The time and date are in the app, but not on the actual video. Makes it pointless for insurance claims.&#8221;</p>
</blockquote>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>&#8220;Why is this not a feature? Every other camera has this!&#8221;</p>
</blockquote>



<h2 class="wp-block-heading">The Workarounds That Don&#8217;t Work</h2>



<p>Some people have tried these &#8220;solutions&#8221;:</p>



<h3 class="wp-block-heading">1. Screenshot the App Thumbnail</h3>



<p><strong>Problem:</strong>&nbsp;Screenshots are too easy to fake and won&#8217;t be accepted as evidence.</p>



<h3 class="wp-block-heading">2. Use Third-Party Video Editing Software</h3>



<p><strong>Problem:</strong>&nbsp;Manually adding timestamps to every video is time-consuming, and it still looks like you added it after the fact.</p>



<h3 class="wp-block-heading">3. Export and Check File Metadata</h3>



<p><strong>Problem:</strong>&nbsp;Most insurance companies and legal entities won&#8217;t accept metadata as proof. They need to&nbsp;<em>see</em>&nbsp;the timestamp on the video.</p>



<h3 class="wp-block-heading">4. Hope Blink Adds the Feature</h3>



<p><strong>Problem:</strong>&nbsp;Users have been requesting this for years with no response from Amazon/Blink.</p>



<h2 class="wp-block-heading">Why Timestamps Matter More Than You Think</h2>



<p>Beyond the obvious legal and insurance uses, timestamps are crucial for:</p>



<ul class="wp-block-list">
<li><strong>Security Monitoring</strong>: Knowing exactly when motion was detected</li>



<li><strong>Pattern Recognition</strong>: Identifying when regular deliveries occur or when suspicious activity happens</li>



<li><strong>Alibi Verification</strong>: Proving where you were at a specific time</li>



<li><strong>Business Documentation</strong>: Recording when employees arrive/leave</li>



<li><strong>Property Management</strong>: Documenting maintenance issues or tenant activity</li>



<li><strong>Personal Records</strong>: Simply knowing when family moments happened</li>
</ul>



<h2 class="wp-block-heading">What Makes This Even More Frustrating</h2>



<p>Blink cameras are owned by&nbsp;<strong>Amazon</strong>—one of the most technologically advanced companies in the world. Adding a timestamp overlay to video would be trivial for their engineering team.</p>



<p>The feature exists in their $99 Ring cameras (also owned by Amazon), but not in their $40-100 Blink cameras. There&#8217;s no technical reason for this omission.</p>



<h2 class="wp-block-heading">The Solution: Add Timestamps to Your Blink Videos</h2>



<p>Since Blink won&#8217;t fix this problem, the solution is to add timestamps yourself. But not manually—there&#8217;s actually an app that does this automatically.</p>



<p>[This is where you&#8217;d mention your app, Timestamp Blink, as the solution]</p>



<p>The app takes your Blink camera videos and adds accurate, professional-looking timestamps directly onto the footage in seconds. The timestamps are pulled from the video&#8217;s metadata, so they&#8217;re 100% accurate.</p>



<p>Now your Blink footage is:</p>



<ul class="wp-block-list">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Accepted by insurance companies</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Valid as legal evidence</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Useful for documentation</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Showing exactly when events occurred</li>
</ul>



<h2 class="wp-block-heading">How to Get Timestamps on Your Blink Videos Now</h2>



<p>You have a few options:</p>



<h3 class="wp-block-heading">Option 1: Switch to a Different Camera Brand</h3>



<p><strong>Cost:</strong>&nbsp;$100-300 per camera<br><strong>Hassle:</strong>&nbsp;High (reinstallation, learning new app)<br><strong>Timeline:</strong>&nbsp;Weeks to set up</p>



<h3 class="wp-block-heading">Option 2: Wait for Blink to Add the Feature</h3>



<p><strong>Cost:</strong> Free<br><strong>Hassle:</strong> Low<br><strong>Timeline:</strong> Unknown (possibly never)Option 3: Use an App to Add Timestamps</p>



<p><strong>Cost:</strong>&nbsp;Minimal (one-time app purchase)<br><strong>Hassle:</strong>&nbsp;Low (works with existing cameras)<br><strong>Timeline:</strong>&nbsp;Immediate</p>



<h2 class="wp-block-heading">Frequently Asked Questions</h2>



<h3 class="wp-block-heading">Q: Does the Blink app show timestamps?</h3>



<p><strong>A:</strong>&nbsp;Yes, but only on the thumbnail view in the app. The actual video file you download or share has no visible timestamp.</p>



<h3 class="wp-block-heading">Q: Can I see the timestamp in the file properties?</h3>



<p><strong>A:</strong>&nbsp;Yes, the timestamp exists in the video file&#8217;s metadata, but most insurance companies and legal entities require a visible timestamp on the video itself.</p>



<h3 class="wp-block-heading">Q: Which Blink cameras have this problem?</h3>



<p><strong>A:</strong>&nbsp;All of them. The Blink Mini, Blink Indoor, Blink Outdoor, Blink Outdoor 4, Blink Video Doorbell—none include timestamps on the actual video.</p>



<h3 class="wp-block-heading">Q: Does Blink&#8217;s subscription service add timestamps?</h3>



<p><strong>A:</strong>&nbsp;No. Even with the Blink Subscription Plan, videos still don&#8217;t have visible timestamps.</p>



<h3 class="wp-block-heading">Q: Will Blink add timestamps in a future update?</h3>



<p><strong>A:</strong>&nbsp;There&#8217;s been no official announcement. Users have requested this feature for years with no response.</p>



<h3 class="wp-block-heading">Q: Can I add timestamps myself?</h3>



<p><strong>A:</strong>&nbsp;Yes, using video editing software or a dedicated app designed for this purpose.</p>



<h2 class="wp-block-heading">The Bottom Line</h2>



<p>Blink cameras are affordable, easy to install, and have good battery life. But the lack of timestamps is a critical flaw that makes the footage unreliable for the exact purposes most people buy security cameras for—evidence and documentation.</p>



<p>Until Blink fixes this, you need a workaround. Don&#8217;t wait until you need timestamped footage for an insurance claim or police report to discover this limitation.</p>



<p>Whether you switch cameras, use an app to add timestamps, or simply accept the limitation, at least now you know what you&#8217;re dealing with.</p>



<p><strong>Have you had issues with Blink&#8217;s missing timestamps?</strong>&nbsp;Share your experience in the comments below.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Related Articles</h2>



<p>Making Your Blink Footage Legally Admissible</p>



<p>How to Submit Blink Camera Footage to Insurance Companies</p>



<p>Blink vs Ring: Which Security Camera Is Better?</p>



<p>Best Security Cameras with Timestamps for 2026</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2345</post-id>	</item>
	</channel>
</rss>
