<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Building Genealogix | Local-First Family History]]></title><description><![CDATA[Follow the development of Genealogix, a local-first genealogy platform. Discover technical insights, privacy-focused web architecture, and family history tips.]]></description><link>https://blog.genealogix.ai</link><image><url>https://cdn.hashnode.com/uploads/logos/69dba7c0aadf1107e2ea5eff/ab760235-ff53-4cbf-97a0-5b6efcbc17dc.png</url><title>Building Genealogix | Local-First Family History</title><link>https://blog.genealogix.ai</link></image><generator>RSS for Node</generator><lastBuildDate>Wed, 20 May 2026 10:55:10 GMT</lastBuildDate><atom:link href="https://blog.genealogix.ai/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Tech Tuesday: Building a Local-First Search Engine with Web Workers]]></title><description><![CDATA[Welcome back to Tech Tuesday!
If you look at any major genealogy platform today, the search bar is the center of the universe. Users expect to type in "John Smith Brooklyn" and instantly see a filtere]]></description><link>https://blog.genealogix.ai/tech-tuesday-building-a-local-first-search-engine-with-web-workers</link><guid isPermaLink="true">https://blog.genealogix.ai/tech-tuesday-building-a-local-first-search-engine-with-web-workers</guid><category><![CDATA[Web Development]]></category><category><![CDATA[React]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[web workers]]></category><category><![CDATA[Software Engineering]]></category><dc:creator><![CDATA[Robert Ocasio]]></dc:creator><pubDate>Tue, 28 Apr 2026 14:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69dba7c0aadf1107e2ea5eff/914a65d7-b24e-4901-8b53-56504a6d191d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome back to Tech Tuesday!</p>
<p>If you look at any major genealogy platform today, the search bar is the center of the universe. Users expect to type in "John Smith Brooklyn" and instantly see a filtered list of census records, life events, and family members.</p>
<p>When you have a massive server farm running an Elasticsearch cluster, this is easy. But Genealogix has a strict <strong>zero cloud database</strong> policy to protect user privacy. All of your family history lives locally in your browser’s IndexedDB.</p>
<p>So, how do you run a full-text search across thousands of complex, encrypted JSON objects entirely on the client side? Here is how we engineered the Genealogix search engine.</p>
<h3>The Problem: The Single-Threaded Bottleneck</h3>
<p>JavaScript runs on a single main thread. This thread is responsible for everything: rendering the React components, handling your mouse clicks, and running your D3.js family tree visualizations.</p>
<p>When a user types a query into the Genealogix search bar, the app needs to:</p>
<ol>
<li><p>Fetch all the records from IndexedDB.</p>
</li>
<li><p>Tokenize the search query (breaking it into searchable chunks).</p>
</li>
<li><p>Run a matching algorithm across names, dates, places, and notes.</p>
</li>
<li><p>Score and sort the results by relevance.</p>
</li>
</ol>
<p>If we ran this heavy computational math on the main thread, the entire application would freeze for a few seconds on every single keystroke. The React UI would lock up, and the user experience would feel broken.</p>
<h3>The Solution: Web Workers to the Rescue</h3>
<p>To keep the Genealogix interface buttery smooth, we had to move the search engine off the main thread entirely. We accomplished this using <strong>Web Workers</strong>.</p>
<p>In our architecture, we built a dedicated <code>fullTextSearch.worker.ts</code> file. A Web Worker acts like a background processor sitting behind the scenes in your browser.</p>
<p>Here is the flow:</p>
<ol>
<li><p><strong>The Hand-off:</strong> When a user types in the search bar, the React UI doesn't try to search anything. It simply packages the query string and sends a quick message to the Web Worker.</p>
</li>
<li><p><strong>The Heavy Lifting:</strong> The Web Worker receives the message, wakes up, and runs the heavy full-text search algorithm against the cached local data. It handles all the tokenization and string matching in complete isolation.</p>
</li>
<li><p><strong>The Return:</strong> Once the worker has a sorted list of matches, it posts a message back to the main thread with the results. React takes that list and instantly updates the UI panel.</p>
</li>
</ol>
<h3>Why This Matters</h3>
<p>Because the Web Worker handles the CPU-intensive search process in the background, the main thread remains completely free. The user can keep typing, panning around their family tree, or opening menus, and the app will never stutter or drop frames.</p>
<p>By combining IndexedDB for local storage with Web Workers for background processing, we’ve matched the speed and UX of a modern, server-backed search engine—without ever letting your family data leave your device.</p>
<p>Are you utilizing Web Workers in your React applications? Let me know your favorite use cases in the comments below!</p>
]]></content:encoded></item><item><title><![CDATA[Tech Tuesday: Taming React and D3.js to Render Massive Family Trees]]></title><description><![CDATA[Welcome back to Tech Tuesday!
Last week, we dove into the invisible engine of Genealogix: how we use IndexedDB and .gnlx bundles to build a local-first application without a centralized cloud database]]></description><link>https://blog.genealogix.ai/tech-tuesday-taming-react-and-d3-js-to-render-massive-family-trees</link><guid isPermaLink="true">https://blog.genealogix.ai/tech-tuesday-taming-react-and-d3-js-to-render-massive-family-trees</guid><category><![CDATA[React]]></category><category><![CDATA[D3.js]]></category><category><![CDATA[DataVisualization]]></category><category><![CDATA[webdev]]></category><category><![CDATA[webdevelopment]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[software development]]></category><category><![CDATA[Software Engineering]]></category><dc:creator><![CDATA[Robert Ocasio]]></dc:creator><pubDate>Tue, 21 Apr 2026 14:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69dba7c0aadf1107e2ea5eff/4ab484e6-6a94-4366-a10e-16bf9ebc5613.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Welcome back to Tech Tuesday!</h2>
<p>Last week, we dove into the invisible engine of Genealogix: how we use IndexedDB and .gnlx bundles to build a local-first application without a centralized cloud database. But once you have thousands of encrypted, local historical records sitting in the browser, you hit the next massive hurdle.</p>
<h2>How do you actually visualize them?</h2>
<p>A family history isn't a flat list of rows and columns. It is a massive, complex, endlessly branching graph. To build Genealogix, we needed a visualization library that could handle massive datasets, complex math, and smooth zooming. That led us straight to the heavyweight champion of data visualization: D3.js.</p>
<p>Here is a look at how we combined React and D3 to build the interactive tree views in Genealogix.</p>
<p>The Great React vs. D3 Dilemma If you have ever tried to use D3 inside a React application, you know the fundamental conflict.</p>
<p>React wants total control of the DOM. It expects you to declare state, and it will figure out how to update the HTML efficiently.</p>
<p>D3 also wants total control of the DOM. It expects to grab an element, manually append SVG nodes, and calculate transitions on the fly.</p>
<p>If you let them fight, your app will crash. For Genealogix, we had to define strict boundaries. We use React to handle the application state, the UI panels, and the container wrapper. Then, we use a React ref to hand a specific, empty SVG canvas over to D3.</p>
<p>Once D3 has the canvas, we use its powerful d3-hierarchy modules to run the heavy algorithmic math: calculating the X and Y coordinates for every ancestor, drawing the bezier curves that connect generations, and handling the complex panning and zooming.</p>
<img src="https://cdn.hashnode.com/uploads/covers/69dba7c0aadf1107e2ea5eff/bde4f53a-eda1-4a98-b619-98de4466a9cd.jpg" alt="" style="display:block;margin:0 auto" />

<h2>Beyond the Standard Pedigree: The Fan and Bowtie Charts</h2>
<p>The standard left-to-right pedigree chart is great, but it gets unwieldy when you go back five or six generations. To give users a better way to explore their local data, we expanded our D3 implementation to include more advanced layouts:</p>
<h2>1. The Fan Chart</h2>
<p>Using D3's arc generators, we built a Fan Chart view. Instead of branching outward infinitely, the home person sits in the center, and ancestors radiate outward in concentric semi-circles. It is a stunning way to visually identify "dead ends" (brick walls) in your research at a single glance.</p>
<img src="https://cdn.hashnode.com/uploads/covers/69dba7c0aadf1107e2ea5eff/a10a1e27-3356-45bb-aea3-26b70d449120.jpg" alt="" style="display:block;margin:0 auto" />

<h2>2. The Bowtie Chart</h2>
<p>Sometimes you don't just want to look backward; you want to look at the immediate family unit. We engineered a Bowtie view that places a primary couple in the center, with the paternal ancestors branching to the left, maternal ancestors to the right, and their children hanging below.</p>
<img src="https://cdn.hashnode.com/uploads/covers/69dba7c0aadf1107e2ea5eff/cebc05b2-bd5d-4598-a0a9-0eb532d1b245.jpg" alt="" style="display:block;margin:0 auto" />

<h2>Local-First Performance</h2>
<p>The biggest benefit of our local-first architecture (which we discussed last week) is speed. Because Genealogix doesn't have to query a remote cloud server every time you pan, zoom, or expand a branch, the D3 visualizations are buttery smooth. The data is already sitting in your browser's IndexedDB, allowing D3 to recalculate the hierarchy and re-render the SVG graph in milliseconds.</p>
<p>Building custom D3 visualizations takes significantly more time than using a drag-and-drop component library, but for a tool designed to map the complexities of human history, the flexibility is worth every line of code.</p>
<p>If you want to see these D3 trees in action, load up your family data at <a href="https://www.genealogix.ai">Genealogix.ai</a> and switch between the different views!</p>
<p>Have you wrestled with React and D3 in your own projects? Let me know your favorite approach in the comments!</p>
]]></content:encoded></item><item><title><![CDATA[Tech Tuesday: How Genealogix Stores Your Data Without a Cloud Database]]></title><description><![CDATA[Welcome to the first installment of Tech Tuesday!
When I first started building Genealogix, I had a strict, non-negotiable rule: zero cloud databases. To fulfill the mission of helping people stop ren]]></description><link>https://blog.genealogix.ai/tech-tuesday-how-genealogix-stores-your-data-without-a-cloud-database</link><guid isPermaLink="true">https://blog.genealogix.ai/tech-tuesday-how-genealogix-stores-your-data-without-a-cloud-database</guid><category><![CDATA[Software Engineering]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[local first]]></category><category><![CDATA[indexeddb]]></category><dc:creator><![CDATA[Robert Ocasio]]></dc:creator><pubDate>Wed, 15 Apr 2026 02:09:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69dba7c0aadf1107e2ea5eff/5770d399-c19b-47a7-9eaf-13a469b050b8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome to the first installment of Tech Tuesday!</p>
<p>When I first started building Genealogix, I had a strict, non-negotiable rule: zero cloud databases. To fulfill the mission of helping people stop renting their history, user data could not live on a centralized server where it could be data-mined or held behind a subscription paywall.</p>
<p>But building a rich, AI-powered web application without a backend database introduces some massive engineering hurdles. Today, I want to pull back the curtain and show you exactly how Genealogix handles data persistence, cloud syncing, and AI artifact storage entirely in the browser.</p>
<h2>The Core Engine: IndexedDB &amp; At-Rest Encryption</h2>
<p>Because a serious genealogist's family tree can contain thousands of individuals and high-resolution documents, standard localStorage (with its 5MB limit) wasn't going to cut it.</p>
<p>Genealogix relies heavily on IndexedDB. When you add a person or a family tie, it is written directly to your browser's local storage. However, browser storage isn't inherently secure from malicious extensions. To solve this, Genealogix implements a strict at-rest encryption pattern.</p>
<p>Before a transaction is ever opened to write a record to IndexedDB, the payload is serialized and encrypted. We store the indexing keys (like personId) in plain text so we can still run lightning-fast queries, but the actual content body is stored as an encrypted string.</p>
<h2>The Sync Problem: Enter the .gnlx Bundle</h2>
<p>If the data only lives in your laptop's browser, what happens when you want to look at your tree on your phone?</p>
<p>Instead of routing your data through a proprietary server to sync devices, I built a custom file format: the .gnlx bundle.</p>
<p>When you enable Cloud Sync, the app gathers your encrypted IndexedDB records, packages them into a compressed .gnlx JSON structure, and pushes that single file directly to your personal Google Drive. When you open Genealogix on your phone, it simply fetches that .gnlx file from your Drive, decrypts the diffs, and updates your mobile IndexedDB. You get all the seamless cross-device syncing of a modern web app, but you own the storage bucket.</p>
<h2>The AI Data Dilemma: Caches vs. Durable Artifacts</h2>
<p>This week, I tackled one of the hardest architectural challenges of building an AI-native app: managing the lifecycle of generated content.</p>
<p>When our Research Assistant analyzes a brick wall, or the Tree-Aware Genie generates a Life Story, that requires an expensive API call. Initially, I just cached the results using the prompt hash. But caching is an implementation detail—it has a Time-To-Live (TTL) and gets cleared. Users were losing AI-generated recipes and translated narratives that they considered part of their permanent archive.</p>
<p>💡 The Trap: Why not just save AI outputs into the standard notes or memories fields? Because it creates a catastrophic AI feedback loop! If AI-generated stories are saved as "evidence" in the notes, future AI prompts will consume those generations as facts, leading to cascading hallucinations.</p>
<p>The Solution: I just shipped a dedicated "aiArtifacts" storage layer. We explicitly separated the ephemeral cache (researchCache) from durable user data. Now, when the AI generates a Life Story, users have a dedicated "Save" button. This writes an explicit, encrypted "LifeStoryArtifact" to IndexedDB.</p>
<p>To handle data mutations (e.g., you save a Life Story, but later update the ancestor's birth year), the artifact stores a sourceHash of the person's data at the time of generation. When you load the person's profile, the app recalculates the current hash. If it doesn't match the artifact's sourceHash, the UI flags the saved story as stale, allowing the user to decide if they want to keep the old version or generate a new one.</p>
<h2>Building for Ownership</h2>
<p>Building a local-first application requires a lot more architectural overhead than just spinning up a standard PostgreSQL database on AWS. But when you see a user successfully translate a 19th-century document and save it locally without sacrificing their privacy, the extra engineering effort is completely worth it.</p>
<p>If you are building local-first apps or wrestling with AI data lifecycles, drop a comment below or connect with me. And if you want to see this architecture in action, try building your tree at <a href="https://www.genealogix.ai">Genealogix.ai</a>.</p>
<p>Until next Tuesday, keep building!</p>
]]></content:encoded></item><item><title><![CDATA[Vibe-Coding My Family Tree: The Birth of Genealogix]]></title><description><![CDATA[Growing Up With 100 Cousins
My name is Robert, and I grew up in Brooklyn, New York, with my parents and brother. My parents were both born in Puerto Rico before World War II, and moved to New York in ]]></description><link>https://blog.genealogix.ai/vibe-coding-my-family-tree-the-birth-of-genealogix</link><guid isPermaLink="true">https://blog.genealogix.ai/vibe-coding-my-family-tree-the-birth-of-genealogix</guid><dc:creator><![CDATA[Robert Ocasio]]></dc:creator><pubDate>Sun, 12 Apr 2026 22:10:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69dba7c0aadf1107e2ea5eff/7c159965-8bb1-41aa-8bef-6c381744c55f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Growing Up With 100 Cousins</h2>
<p>My name is Robert, and I grew up in Brooklyn, New York, with my parents and brother. My parents were both born in Puerto Rico before World War II, and moved to New York in the 1960s. They both had relatives in (or near) New York City, and as typical children of Puerto Rican descent, my brother and I spent a lot of time with our uncles, aunts, and cousins. We were always aware that we had a large extended family. In fact, my brother and I used to count our first cousins, both those we actually met and those we never had. I remember us counting around 100 of them. We also made a game of naming all of our aunts and uncles - my mom was one of twelve.</p>
<h2>Hitting the Brick Wall</h2>
<p>My fascination with genealogy started back, without knowing what it was called. I always thought it was just a proud recollection of our living relatives. The first time I created a family tree was in school, probably in the 6th or 7th grade. Filling up my family tree to my great-grandparents was something to be proud of, but until that day, I didn't realize that most of my classmates could not go past their grandparents. Years later, my interest in genealogy became more serious. I created an account on Ancestry, built up my tree, and took a DNA test. I was absolutely hooked when my brick walls started to crumble. I met distant cousins I never knew existed. I created trees and DNA tests on other platforms. I tested my Y-DNA on Family Tree DNA. I traced my lineage back to Spain on multiple branches. But the more information I found, the more questions I had, and the more I realized I couldn't unlock every mystery hidden in my family tree without going to Puerto Rico and digging through the archives. This proved difficult for me because I was still working a full-time job. This sounded like something I could do many years from now when I retire, and I have a lot of time on my hands. After a few years of continuing my research and helping others start theirs, I started to slow my research down until eventually I stopped.</p>
<p>Sometime during these years, I received a Bachelor's degree and a Master's degree in Computer Science. I finally achieved my dream career as a software engineer, and then AI came into play. Artificial Intelligence was the shiny new toy in the technology field, and like so many others, I dove right in, fascinated by the possibilities. I watched videos about vibe-coding and came up with a few simple tools, but the wheels in my mind started to spin. What kind of project can I do to showcase my skills while working on something I'm genuinely interested in?</p>
<h2>Vibe-coding the Future</h2>
<p>Genealogix started as an experiment using Google AI Studio. I wanted to vibe-code a website that served a purpose that was interesting to me. It did a surprisingly good job. For those who are not familiar, vibe-coding is having AI do all the coding work based on your prompts (instructions). I saved my code on GitHub as a backup, and continued to add features to Genealogix until it made some serious errors. I switched away from Google AI Studio to using Visual Studio Code with GitHub Copilot for vibe-coding. I initially used Claude Sonnet 3.5 as a model, but more importantly, I used Gemini for ideation. Gemini 3 Pro had just come out, and it was great for bouncing ideas off it. It would give me details for a feature I wanted to implement, then I had Copilot actually do the work. This system is what I use in my current job, so I was familiar with the intricacies of this setup. The models I use constantly change as technology improves, and will continue to change. Who knows? In a few months, I may start using Cursor instead of VS Code and GitHub Copilot, or whatever is the next big thing.</p>
<h2>What is Genealogix?</h2>
<p>So what exactly is Genealogix? It's a website designed to make genealogy research easier with the help of AI. It is also an answer to the problem genealogists have had for decades - privacy. Whose data is it, really? Why are we renting our own family history on the big sites? I built Genealogix from the very beginning to solve this problem. How do we keep data away from the website servers? I think the approach I've taken when building this site resolves this, and we can discuss it in depth in another post. The website is a work in progress, and I hope serious genealogists can give it a chance and let me know what it's missing to be competitive, and if there is anything obviously broken. If you want to give it a try today, go to <a href="https://www.genealogix.ai">https://www.genealogix.ai</a>.</p>
<p>I want to use this blog to go into detail on the coding choices I make for each feature, as well as discuss genealogy tips for those curious about how AI can help. Please join me on this journey with me. Hopefully, these blog posts will be as interesting to you as they will be to me.</p>
<p>Click the subscribe button to make sure you get notified when I drop the next installment. Thanks for giving Genealogix a try, keeping our family history in our own hands!</p>
]]></content:encoded></item></channel></rss>