<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Eladio Caritos</title>
    <subtitle>Personal website and blog of Eladio Caritos</subtitle>
    <link rel="self" type="application/atom+xml" href="https://caritos.com/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://caritos.com"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2025-11-15T00:00:00+00:00</updated>
    <id>https://caritos.com/atom.xml</id>
    <entry xml:lang="en">
        <title>Building a Frictionless Capture System: Voice Memos to Obsidian</title>
        <published>2025-11-15T00:00:00+00:00</published>
        <updated>2025-11-15T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Eladio Caritos
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://caritos.com/posts/capturing-thoughts-apple-watch-obsidian/"/>
        <id>https://caritos.com/posts/capturing-thoughts-apple-watch-obsidian/</id>
        
        <content type="html" xml:base="https://caritos.com/posts/capturing-thoughts-apple-watch-obsidian/">&lt;p&gt;&quot;Our brains are for having ideas, not holding them.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;This principle, from Jeff Su&#x27;s C.O.R.E productivity system taught to thousands of Googlers, resonated with me immediately. The C.O.R.E system starts with &lt;strong&gt;Capture&lt;&#x2F;strong&gt;—immediately recording information before it&#x27;s forgotten. But capture only works if it&#x27;s truly frictionless.&lt;&#x2F;p&gt;
&lt;p&gt;After watching his explanation of how capture should be &quot;a reflex, not a decision,&quot; I realized my current capture workflow had too much friction. So I built something better.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-problem-i-wanted-to-solve&quot;&gt;The Problem I Wanted to Solve&lt;&#x2F;h2&gt;
&lt;p&gt;Ideas don&#x27;t wait for convenient moments. They show up while running, driving, or carrying groceries. My previous capture methods all had friction:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Physical notebook&lt;&#x2F;strong&gt;: Forgotten at home, requires stopping to write&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Phone notes app&lt;&#x2F;strong&gt;: Unlock phone, find app, type with thumbs&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Email to myself&lt;&#x2F;strong&gt;: Clutters inbox, awkward to process later&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Task management apps&lt;&#x2F;strong&gt;: Too many taps and required fields&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The Apple Watch partially solved this—I can record voice memos hands-free in seconds. But voice memos alone just create a different problem: they pile up unprocessed in the Voice Memos app instead of living in my Obsidian vault where I actually work.&lt;&#x2F;p&gt;
&lt;p&gt;I needed the memos transcribed, tagged with metadata, and automatically filed in Obsidian.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-solution-automated-transcription-pipeline&quot;&gt;The Solution: Automated Transcription Pipeline&lt;&#x2F;h2&gt;
&lt;p&gt;I built a system that bridges the gap between Apple Watch capture and Obsidian organization:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Capture&lt;&#x2F;strong&gt;: Record voice memo on Apple Watch (2 seconds, hands-free)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Automatic sync&lt;&#x2F;strong&gt;: Voice memo syncs to Mac via iCloud&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Scheduled processing&lt;&#x2F;strong&gt;: Cron job runs my Python script&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;AI transcription&lt;&#x2F;strong&gt;: OpenAI&#x27;s Whisper converts audio to text&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Smart filing&lt;&#x2F;strong&gt;: Saves to Obsidian with rich metadata&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Cleanup&lt;&#x2F;strong&gt;: Deletes original voice memo&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The entire process runs automatically. I capture the thought, and later it appears in my Obsidian vault, transcribed and ready to process.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;technical-implementation&quot;&gt;Technical Implementation&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;the-core-script&quot;&gt;The Core Script&lt;&#x2F;h3&gt;
&lt;p&gt;I wrote a Python script using OpenAI&#x27;s Whisper for transcription. Whisper runs locally (no API costs) and handles various audio formats and languages automatically.&lt;&#x2F;p&gt;
&lt;p&gt;Key features:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Batch processing&lt;&#x2F;strong&gt;: Processes all pending voice memos in one run&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Multiple model sizes&lt;&#x2F;strong&gt;: Trade speed for accuracy (tiny&#x2F;base&#x2F;small&#x2F;medium&#x2F;large)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Flexible output formats&lt;&#x2F;strong&gt;: txt, srt, vtt, or json&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Audio preservation&lt;&#x2F;strong&gt;: Optionally copies original audio alongside transcription&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Safe cleanup&lt;&#x2F;strong&gt;: Only deletes originals after successful transcription&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;metadata-generation&quot;&gt;Metadata Generation&lt;&#x2F;h3&gt;
&lt;p&gt;The script extracts timestamps from Voice Memo filenames (format: &lt;code&gt;20250505 072813-DADFB99E.m4a&lt;&#x2F;code&gt;) and generates Obsidian frontmatter:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span&gt;---
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;who&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[[~eladio]]&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;what&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[[%voice]]&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[[%memo]]&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;when&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[[@2025]]&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[[@2025-05]]&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[[@2025-05-05]]&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[[@2025-W18]]&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[[@2025-05-05 07:28:13]]&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;where&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[[+stony-brook]]&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[[+new-york]]&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;status&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[[!archive]]&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;visibility&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;[[!private]]&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;---
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This rich metadata means I&#x27;ll be able to query voice memos by date, week, location, or type using Obsidian&#x27;s Dataview queries.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-automation&quot;&gt;The Automation&lt;&#x2F;h3&gt;
&lt;p&gt;A simple shell script orchestrates the workflow:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;#!&#x2F;bin&#x2F;bash
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;VOICE_MEMOS_DIR&lt;&#x2F;span&gt;&lt;span&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;Users&#x2F;eladio&#x2F;Library&#x2F;Group Containers&#x2F;group.com.apple.VoiceMemos.shared&#x2F;Recordings&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;OUTPUT_DIR&lt;&#x2F;span&gt;&lt;span&gt;=&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;HOME&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;src&#x2F;transcribe-voice-memos&#x2F;transcriptions&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;cd &lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;HOME&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;&#x2F;src&#x2F;transcribe-voice-memos&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;source&lt;&#x2F;span&gt;&lt;span&gt; venv&#x2F;bin&#x2F;activate
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;python&lt;&#x2F;span&gt;&lt;span&gt; transcribe_voice_memos.py &amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;VOICE_MEMOS_DIR&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; \
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;    --batch &lt;&#x2F;span&gt;&lt;span&gt;\
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;    --output &lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;OUTPUT_DIR&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; \
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;    --copy-audio &lt;&#x2F;span&gt;&lt;span&gt;\
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;    --delete-after
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Running this via cron means transcriptions appear automatically without any manual work.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-this-aligns-with-c-o-r-e&quot;&gt;Why This Aligns with C.O.R.E&lt;&#x2F;h2&gt;
&lt;p&gt;Jeff Su&#x27;s system emphasizes that capture should be &quot;a reflex, not a decision.&quot; This automation should achieve exactly that:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;No Decision Required&lt;&#x2F;strong&gt;: I won&#x27;t need to think about where to file it, how to categorize it, or whether it&#x27;s &quot;important enough.&quot; Just speak and move on.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Offload Immediately&lt;&#x2F;strong&gt;: The thought leaves my brain and enters my external system instantly. No mental carrying until I can &quot;properly&quot; write it down.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Separate Capture from Processing&lt;&#x2F;strong&gt;: I capture in the moment. I organize and review later during dedicated sessions at my desk. Each step happens when it&#x27;s most effective.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Trust Through Automation&lt;&#x2F;strong&gt;: Because it&#x27;s automated and reliable, I can trust it completely. This trust removes hesitation—I won&#x27;t second-guess whether to use it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-technical-stack&quot;&gt;The Technical Stack&lt;&#x2F;h2&gt;
&lt;p&gt;For anyone wanting to build something similar:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Python 3.13&lt;&#x2F;strong&gt; with virtual environment&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;OpenAI Whisper&lt;&#x2F;strong&gt; (open source, runs locally—no API costs)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;PyTorch&lt;&#x2F;strong&gt; for machine learning backend&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Shell scripts&lt;&#x2F;strong&gt; for orchestration&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Cron&lt;&#x2F;strong&gt; for scheduling (could use macOS Launch Agents)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The complete project lives at &lt;code&gt;~&#x2F;src&#x2F;transcribe-voice-memos&#x2F;&lt;&#x2F;code&gt; and is relatively straightforward to adapt for other note-taking systems.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;configuration-options&quot;&gt;Configuration Options&lt;&#x2F;h2&gt;
&lt;p&gt;The script is flexible:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Model Selection&lt;&#x2F;strong&gt; (trading speed for accuracy):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tiny&lt;&#x2F;code&gt;: Fastest, good for simple ideas&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;base&lt;&#x2F;code&gt;: My default, solid balance&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;medium&lt;&#x2F;code&gt;: Better for technical terms&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;large&lt;&#x2F;code&gt;: Best accuracy, slower&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Output Formats&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;txt&lt;&#x2F;code&gt;: Markdown with frontmatter (my choice)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;srt&lt;&#x2F;code&gt;: Subtitle format with timestamps&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;vtt&lt;&#x2F;code&gt;: WebVTT format&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;json&lt;&#x2F;code&gt;: Full structured data&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Processing Modes&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Auto-delete originals (clean workflow)&lt;&#x2F;li&gt;
&lt;li&gt;Keep originals (redundant backup)&lt;&#x2F;li&gt;
&lt;li&gt;Copy audio files (my approach—transcription plus original for reference)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;ideas-for-future-enhancement&quot;&gt;Ideas for Future Enhancement&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;m already thinking about improvements:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Intelligent Categorization&lt;&#x2F;strong&gt;: Use GPT to analyze memo content and automatically categorize (work, personal, ideas, todos) and route to appropriate Obsidian folders.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Immediate Processing&lt;&#x2F;strong&gt;: Integrate with iOS Shortcuts to trigger transcription right after recording instead of waiting for the next cron run.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Voice Commands&lt;&#x2F;strong&gt;: Parse commands embedded in memos (&quot;File this as a project idea&quot; or &quot;Add to shopping list&quot;) and act on them.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Task Extraction&lt;&#x2F;strong&gt;: Automatically create Obsidian tasks when memos contain phrases like &quot;TODO&quot; or &quot;Remember to...&quot;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-design-philosophy-eliminate-friction&quot;&gt;The Design Philosophy: Eliminate Friction&lt;&#x2F;h2&gt;
&lt;p&gt;This project reinforced an important lesson: good productivity tools aren&#x27;t about features—they&#x27;re about removing friction.&lt;&#x2F;p&gt;
&lt;p&gt;The Apple Watch already existed. Obsidian already existed. Voice memos were already being created. Transcription technology was already available.&lt;&#x2F;p&gt;
&lt;p&gt;The friction was in the &lt;strong&gt;gaps between tools&lt;&#x2F;strong&gt;: manually transcribing audio, copying files, adding metadata, organizing notes.&lt;&#x2F;p&gt;
&lt;p&gt;By automating those gaps, the workflow becomes frictionless. And frictionless capture, as the C.O.R.E system teaches, is the foundation of effective productivity.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;getting-started&quot;&gt;Getting Started&lt;&#x2F;h2&gt;
&lt;p&gt;If you want to build something similar:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Set up Python environment: &lt;code&gt;python -m venv venv&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Install dependencies: &lt;code&gt;pip install openai-whisper torch&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Write a script to process voice memos from Apple&#x27;s directory&lt;&#x2F;li&gt;
&lt;li&gt;Generate appropriate metadata&#x2F;frontmatter for your system&lt;&#x2F;li&gt;
&lt;li&gt;Create automation (cron job or Launch Agent)&lt;&#x2F;li&gt;
&lt;li&gt;Test thoroughly before enabling auto-deletion&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The setup takes a few hours, but creates a system that should pay dividends over time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-s-next&quot;&gt;What&#x27;s Next&lt;&#x2F;h2&gt;
&lt;p&gt;I just built this system, so I can&#x27;t yet report on real-world effectiveness. But the theory is sound:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Capture should be effortless&lt;&#x2F;li&gt;
&lt;li&gt;Processing should be separate from capture&lt;&#x2F;li&gt;
&lt;li&gt;Automation removes friction&lt;&#x2F;li&gt;
&lt;li&gt;Trust in the system enables reflexive use&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I&#x27;ll be testing this workflow over the coming weeks and will share results in a future post. If it works as designed, it should capture ideas that would otherwise be lost while keeping my Obsidian vault as the single source of truth.&lt;&#x2F;p&gt;
&lt;p&gt;The real test will be whether I naturally reach for voice memos when ideas strike, or if friction still creeps in. Time will tell.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;The code for this project is available at &lt;code&gt;~&#x2F;src&#x2F;transcribe-voice-memos&#x2F;&lt;&#x2F;code&gt;. I&#x27;ll write a follow-up post once I&#x27;ve used this system in real-world conditions and can share actual results rather than theoretical benefits.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Row Level Security (RLS) in Expo + Supabase: Your Backend Access Control</title>
        <published>2025-09-07T00:00:00+00:00</published>
        <updated>2025-09-07T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Eladio Caritos
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://caritos.com/posts/rls-policy-expo-supabase/"/>
        <id>https://caritos.com/posts/rls-policy-expo-supabase/</id>
        
        <content type="html" xml:base="https://caritos.com/posts/rls-policy-expo-supabase/">&lt;p&gt;When building mobile apps with Expo and Supabase, Row Level Security (RLS) becomes your primary defense mechanism for data access control. Since your mobile app connects directly to the database through Supabase&#x27;s API, RLS policies act as your backend security layer.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-rls&quot;&gt;What is RLS?&lt;&#x2F;h2&gt;
&lt;p&gt;Row Level Security is a Postgres feature that lets you define rules (policies) for who can access or modify specific rows in a table. Instead of granting blanket table permissions, you can create fine-grained access control based on user identity, roles, or any other criteria.&lt;&#x2F;p&gt;
&lt;p&gt;In your Expo + Supabase stack:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Database&lt;&#x2F;strong&gt;: Supabase (Postgres with RLS)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Frontend&lt;&#x2F;strong&gt;: Expo (React Native)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Auth&lt;&#x2F;strong&gt;: Supabase Auth with JWT tokens&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;how-rls-works-in-your-app-flow&quot;&gt;How RLS Works in Your App Flow&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;User authenticates&lt;&#x2F;strong&gt; via Supabase Auth and receives a JWT token&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Expo app makes requests&lt;&#x2F;strong&gt; to Supabase with that token&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;RLS policies inspect&lt;&#x2F;strong&gt; the JWT&#x27;s &lt;code&gt;sub&lt;&#x2F;code&gt; (user ID), roles, and other claims&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Postgres returns&lt;&#x2F;strong&gt; only rows that match your policy rules&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This means you don&#x27;t need a separate API layer for basic access control - RLS handles it at the database level.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;common-rls-policy-patterns&quot;&gt;Common RLS Policy Patterns&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;user-owned-data-access&quot;&gt;User-Owned Data Access&lt;&#x2F;h3&gt;
&lt;p&gt;The most common pattern: users can only access their own data.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sql&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sql &quot;&gt;&lt;code class=&quot;language-sql&quot; data-lang=&quot;sql&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;-- Enable RLS on the table
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;ALTER TABLE &lt;&#x2F;span&gt;&lt;span&gt;profiles ENABLE ROW LEVEL SECURITY;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;-- Users can only see their own profile
&lt;&#x2F;span&gt;&lt;span&gt;CREATE POLICY &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Users can view own profile&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; ON profiles
&lt;&#x2F;span&gt;&lt;span&gt;FOR &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;SELECT USING&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;auth&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;uid&lt;&#x2F;span&gt;&lt;span&gt;() = id);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;-- Users can only update their own profile  
&lt;&#x2F;span&gt;&lt;span&gt;CREATE POLICY &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Users can update own profile&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; ON profiles
&lt;&#x2F;span&gt;&lt;span&gt;FOR &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;UPDATE USING&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;auth&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;uid&lt;&#x2F;span&gt;&lt;span&gt;() = id);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;-- Users can insert their own profile
&lt;&#x2F;span&gt;&lt;span&gt;CREATE POLICY &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Users can insert own profile&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; ON profiles
&lt;&#x2F;span&gt;&lt;span&gt;FOR &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;INSERT WITH CHECK&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;auth&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;uid&lt;&#x2F;span&gt;&lt;span&gt;() = id);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;public-read-private-write&quot;&gt;Public Read, Private Write&lt;&#x2F;h3&gt;
&lt;p&gt;Perfect for public profiles or posts where anyone can read but only owners can modify.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sql&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sql &quot;&gt;&lt;code class=&quot;language-sql&quot; data-lang=&quot;sql&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;-- Anyone can read profiles
&lt;&#x2F;span&gt;&lt;span&gt;CREATE POLICY &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Profiles are publicly readable&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; ON profiles
&lt;&#x2F;span&gt;&lt;span&gt;FOR &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;SELECT USING&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;-- Only profile owners can update
&lt;&#x2F;span&gt;&lt;span&gt;CREATE POLICY &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Users can update own profile&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; ON profiles  
&lt;&#x2F;span&gt;&lt;span&gt;FOR &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;UPDATE USING&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;auth&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;uid&lt;&#x2F;span&gt;&lt;span&gt;() = user_id);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;relationship-based-access&quot;&gt;Relationship-Based Access&lt;&#x2F;h3&gt;
&lt;p&gt;For data involving multiple users, like messages or shared documents.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sql&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sql &quot;&gt;&lt;code class=&quot;language-sql&quot; data-lang=&quot;sql&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;-- Users can read messages they sent or received
&lt;&#x2F;span&gt;&lt;span&gt;CREATE POLICY &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Users can read their messages&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; ON messages
&lt;&#x2F;span&gt;&lt;span&gt;FOR &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;SELECT USING&lt;&#x2F;span&gt;&lt;span&gt; (
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;auth&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;uid&lt;&#x2F;span&gt;&lt;span&gt;() = sender_id OR &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;auth&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;uid&lt;&#x2F;span&gt;&lt;span&gt;() = receiver_id
&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;-- Users can only send messages as themselves
&lt;&#x2F;span&gt;&lt;span&gt;CREATE POLICY &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Users can send messages&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; ON messages
&lt;&#x2F;span&gt;&lt;span&gt;FOR &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;INSERT WITH CHECK&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;auth&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;uid&lt;&#x2F;span&gt;&lt;span&gt;() = sender_id);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;implementing-rls-in-your-expo-app&quot;&gt;Implementing RLS in Your Expo App&lt;&#x2F;h2&gt;
&lt;p&gt;The beauty of RLS is that your Expo code remains clean and simple:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;typescript&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-typescript &quot;&gt;&lt;code class=&quot;language-typescript&quot; data-lang=&quot;typescript&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; This query automatically respects RLS policies
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;error &lt;&#x2F;span&gt;&lt;span&gt;} = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;await &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;supabase
&lt;&#x2F;span&gt;&lt;span&gt;  .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;profiles&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;)
&lt;&#x2F;span&gt;&lt;span&gt;  .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;select&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Only returns profiles the user is allowed to see
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; No need for manual filtering or authorization checks
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For real-time subscriptions:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;typescript&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-typescript &quot;&gt;&lt;code class=&quot;language-typescript&quot; data-lang=&quot;typescript&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Subscriptions also respect RLS
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;subscription &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;supabase
&lt;&#x2F;span&gt;&lt;span&gt;  .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;channel&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;profiles&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;)
&lt;&#x2F;span&gt;&lt;span&gt;  .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;on&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;postgres_changes&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;, 
&lt;&#x2F;span&gt;&lt;span&gt;    { event: &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;, schema: &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;public&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;, table: &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;profiles&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39; },
&lt;&#x2F;span&gt;&lt;span&gt;    (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;payload&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ebcb8b;&quot;&gt;console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Change received!&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;payload&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;  )
&lt;&#x2F;span&gt;&lt;span&gt;  .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;subscribe&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;advanced-patterns&quot;&gt;Advanced Patterns&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;role-based-access&quot;&gt;Role-Based Access&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;sql&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sql &quot;&gt;&lt;code class=&quot;language-sql&quot; data-lang=&quot;sql&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;-- Create a function to get user role
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;CREATE OR REPLACE FUNCTION &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;get_user_role&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;RETURNS &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;text &lt;&#x2F;span&gt;&lt;span&gt;AS $$
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span&gt; raw_user_meta_data-&amp;gt;&amp;gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;role&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39; 
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;FROM &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;auth&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;users 
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span&gt; id = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;auth&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;uid&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;$$ LANGUAGE sql SECURITY DEFINER;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;-- Admin users can see all profiles
&lt;&#x2F;span&gt;&lt;span&gt;CREATE POLICY &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Admins can view all profiles&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; ON profiles
&lt;&#x2F;span&gt;&lt;span&gt;FOR &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;SELECT USING&lt;&#x2F;span&gt;&lt;span&gt; (get_user_role() = &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;admin&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;time-based-access&quot;&gt;Time-Based Access&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;sql&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sql &quot;&gt;&lt;code class=&quot;language-sql&quot; data-lang=&quot;sql&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;-- Users can only edit posts within 24 hours of creation
&lt;&#x2F;span&gt;&lt;span&gt;CREATE POLICY &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Users can edit recent posts&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; ON posts
&lt;&#x2F;span&gt;&lt;span&gt;FOR &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;UPDATE USING&lt;&#x2F;span&gt;&lt;span&gt; (
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;auth&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;uid&lt;&#x2F;span&gt;&lt;span&gt;() = author_id AND 
&lt;&#x2F;span&gt;&lt;span&gt;  created_at &amp;gt; now() - interval &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;24 hours&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;testing-your-rls-policies&quot;&gt;Testing Your RLS Policies&lt;&#x2F;h2&gt;
&lt;p&gt;Always test with actual user tokens, not the service role key:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;typescript&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-typescript &quot;&gt;&lt;code class=&quot;language-typescript&quot; data-lang=&quot;typescript&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Create a test user
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;user &lt;&#x2F;span&gt;&lt;span&gt;} = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;await &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;supabase&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;auth&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;signUp&lt;&#x2F;span&gt;&lt;span&gt;({
&lt;&#x2F;span&gt;&lt;span&gt;  email: &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;test@example.com&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;,
&lt;&#x2F;span&gt;&lt;span&gt;  password: &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;password&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Make requests as that user to verify policies work
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data &lt;&#x2F;span&gt;&lt;span&gt;} = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;await &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;supabase
&lt;&#x2F;span&gt;&lt;span&gt;  .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;profiles&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;)
&lt;&#x2F;span&gt;&lt;span&gt;  .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;select&lt;&#x2F;span&gt;&lt;span&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;important-gotchas&quot;&gt;Important Gotchas&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Default Deny&lt;&#x2F;strong&gt;: Once RLS is enabled, all access is blocked until you create policies&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Service Role Bypasses RLS&lt;&#x2F;strong&gt;: Server-side functions using the service key ignore RLS&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Policy Order Matters&lt;&#x2F;strong&gt;: More specific policies should come first&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Performance&lt;&#x2F;strong&gt;: Complex policies can impact query performance&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;security-benefits&quot;&gt;Security Benefits&lt;&#x2F;h2&gt;
&lt;p&gt;With proper RLS policies, you get:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Data isolation&lt;&#x2F;strong&gt; between users automatically&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Protection against&lt;&#x2F;strong&gt; client-side tampering or reverse engineering&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Consistent security&lt;&#x2F;strong&gt; across all database access points&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Real-time security&lt;&#x2F;strong&gt; for subscriptions and live updates&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;RLS transforms Supabase from just a database-as-a-service into a secure backend-as-a-service, making it perfect for mobile apps that need robust data protection without the complexity of building custom APIs.&lt;&#x2F;p&gt;
&lt;p&gt;The key is starting with simple policies and gradually adding complexity as your app&#x27;s requirements grow. Your Expo app stays clean while Postgres handles the heavy lifting of access control.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Automating My Tennis Shoe Shopping: Because Even Athletes Need Automation</title>
        <published>2025-09-03T00:00:00+00:00</published>
        <updated>2025-09-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Eladio Caritos
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://caritos.com/posts/automating-tennis-shoe-shopping/"/>
        <id>https://caritos.com/posts/automating-tennis-shoe-shopping/</id>
        
        <content type="html" xml:base="https://caritos.com/posts/automating-tennis-shoe-shopping/">&lt;p&gt;As someone who plays tennis regularly, I&#x27;ve learned that replacing tennis shoes every 6 months isn&#x27;t just a recommendation—it&#x27;s essential for both performance and injury prevention. But I don&#x27;t want shoe shopping to be another recurring task on my mental to-do list.&lt;&#x2F;p&gt;
&lt;p&gt;So I did what any programmer would do: I automated it.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-why&quot;&gt;The Why&lt;&#x2F;h1&gt;
&lt;p&gt;Tennis shoes lose their cushioning and support over time, and for someone who plays multiple times per week, that degradation happens faster than you might think. The general rule is every 6 months or 300-500 hours of play, whichever comes first.&lt;&#x2F;p&gt;
&lt;p&gt;I know I need new shoes regularly. I just don&#x27;t want to think about it. Shopping for shoes, comparing prices, checking inventory - it&#x27;s all time and mental energy I&#x27;d rather spend elsewhere. So I automated the entire process.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-solution&quot;&gt;The Solution&lt;&#x2F;h1&gt;
&lt;p&gt;I created an open source project that handles the entire tennis shoe replacement cycle:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Automated scheduling&lt;&#x2F;strong&gt; - Tracks when it&#x27;s time for replacement based on your play frequency&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Price monitoring&lt;&#x2F;strong&gt; - Watches multiple retailers for your preferred models and sizes&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Inventory tracking&lt;&#x2F;strong&gt; - Alerts you when your shoes are in stock at the best price&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Purchase automation&lt;&#x2F;strong&gt; - Can automatically order when conditions are met&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Performance analytics&lt;&#x2F;strong&gt; - Tracks how different shoes perform over their lifecycle&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;key-features&quot;&gt;Key Features&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Smart Scheduling&lt;&#x2F;strong&gt;: The system learns from your play patterns. Log your court time, and it calculates optimal replacement timing based on actual usage rather than just calendar months.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Multi-Retailer Monitoring&lt;&#x2F;strong&gt;: Checks major tennis retailers, Amazon, and direct manufacturer sites for price drops and availability.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Model Intelligence&lt;&#x2F;strong&gt;: Maintains a database of tennis shoe models with performance ratings, durability data, and user reviews to suggest the best options for your playing style.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Budget Optimization&lt;&#x2F;strong&gt;: Finds the sweet spot between shoe quality and cost, factoring in how long different models last under your specific playing conditions.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;why-this-matters&quot;&gt;Why This Matters&lt;&#x2F;h1&gt;
&lt;p&gt;Beyond the obvious convenience factor, this project solves several real problems:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Injury Prevention&lt;&#x2F;strong&gt;: Worn-out shoes are a major cause of tennis injuries. Automated replacement ensures you&#x27;re always playing in properly supportive footwear.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Performance Consistency&lt;&#x2F;strong&gt;: Fresh shoes mean consistent traction and comfort, which translates to better play and fewer distractions on court.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Cost Efficiency&lt;&#x2F;strong&gt;: By monitoring prices continuously, the system catches sales and deals you&#x27;d otherwise miss, often saving 20-30% compared to emergency purchases.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Time Savings&lt;&#x2F;strong&gt;: No more shopping around or trying to remember when you last bought shoes. The system handles everything.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-technical-implementation&quot;&gt;The Technical Implementation&lt;&#x2F;h1&gt;
&lt;p&gt;The project is built with modularity in mind:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Scheduling Engine&lt;&#x2F;strong&gt;: Configurable algorithms for calculating replacement timing&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Web Scraping Framework&lt;&#x2F;strong&gt;: Robust price and inventory monitoring across retailers&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Notification System&lt;&#x2F;strong&gt;: Alerts via email, SMS, or push notifications&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Purchase Integration&lt;&#x2F;strong&gt;: Secure API connections to supported retailers&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Analytics Dashboard&lt;&#x2F;strong&gt;: Track spending, shoe performance, and play patterns&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;open-source-approach&quot;&gt;Open Source Approach&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;ve open-sourced this because the tennis community (and athletes in general) shouldn&#x27;t have to solve these problems individually. The project is designed to be:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Extensible&lt;&#x2F;strong&gt;: Easy to add new retailers or shoe models&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Configurable&lt;&#x2F;strong&gt;: Adaptable to different sports, playing frequencies, and budgets&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Privacy-Focused&lt;&#x2F;strong&gt;: All data stays local or in your chosen cloud provider&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Community-Driven&lt;&#x2F;strong&gt;: Feature requests and improvements from actual players&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;getting-started&quot;&gt;Getting Started&lt;&#x2F;h1&gt;
&lt;p&gt;The system is designed for easy setup:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Configure your playing schedule and preferred shoe models&lt;&#x2F;li&gt;
&lt;li&gt;Set up retailer monitoring for your size and budget range&lt;&#x2F;li&gt;
&lt;li&gt;Choose notification preferences and automation level&lt;&#x2F;li&gt;
&lt;li&gt;Let the system handle the rest&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;You can run it fully automated or use it as a monitoring tool with manual purchase decisions—whatever fits your comfort level.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;real-world-results&quot;&gt;Real-World Results&lt;&#x2F;h1&gt;
&lt;p&gt;Since implementing this system:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Zero missed replacement windows&lt;&#x2F;strong&gt; - No more playing in worn-out shoes&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;25% average savings&lt;&#x2F;strong&gt; on shoe purchases through automated deal detection&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Eliminated decision fatigue&lt;&#x2F;strong&gt; - No more spending hours comparing options&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Better performance tracking&lt;&#x2F;strong&gt; - Data on how different shoes perform over time&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;the-future&quot;&gt;The Future&lt;&#x2F;h1&gt;
&lt;p&gt;This is just the beginning. Future versions could include:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Biomechanical integration&lt;&#x2F;strong&gt; - Using wearable data to predict optimal replacement timing&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Community recommendations&lt;&#x2F;strong&gt; - Leveraging user data to suggest optimal shoes for different playing styles&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Injury correlation&lt;&#x2F;strong&gt; - Tracking relationships between shoe condition and injury patterns&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Multi-sport support&lt;&#x2F;strong&gt; - Expanding beyond tennis to other athletic footwear&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;contributing&quot;&gt;Contributing&lt;&#x2F;h1&gt;
&lt;p&gt;The project is available on GitHub and welcomes contributions from developers and athletes alike. Whether you&#x27;re interested in adding support for new sports, improving the price monitoring algorithms, or just reporting bugs, the tennis community benefits from everyone&#x27;s input.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;Tennis players spend countless hours perfecting their game—their equipment maintenance should be just as optimized. If you&#x27;re tired of manual shoe shopping or have ideas for improving athletic gear automation, check out the project and contribute!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>My Car Buying Experience: From a Worn Odyssey to a New Sienna</title>
        <published>2025-09-02T00:00:00+00:00</published>
        <updated>2025-09-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Eladio Caritos
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://caritos.com/posts/my-car-buying-experience/"/>
        <id>https://caritos.com/posts/my-car-buying-experience/</id>
        
        <content type="html" xml:base="https://caritos.com/posts/my-car-buying-experience/">&lt;h1 id=&quot;the-search-begins&quot;&gt;The Search Begins&lt;&#x2F;h1&gt;
&lt;p&gt;After 14 years with our 2011 Honda Odyssey approaching 200,000 miles, it was time for a change. The reliability issues were piling up: the battery would die even after charging, both sliding doors had to be operated manually (and the kids would often leave them ajar), the backup camera was dead, and one A&#x2F;C vent wasn&#x27;t working properly. After over a decade of faithful service, our minivan was showing its age.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;research-phase&quot;&gt;Research Phase&lt;&#x2F;h1&gt;
&lt;p&gt;The process of choosing a replacement was arduous. My wife and kids wanted a large SUV, while my youngest and I were team minivan.&lt;&#x2F;p&gt;
&lt;p&gt;Initially, I set my sights on the Hybrid Grand Highlander, but finding one without a significant market markup proved nearly impossible. This led me to explore large SUVs like the Toyota Sequoia and Cadillac Escalade. For a while, we seriously considered the Chevrolet Tahoe - we even rented one in Florida for a week and loved it. But reality set in: the thing was massive. How would I navigate tight city spots? Where would I even park it?&lt;&#x2F;p&gt;
&lt;p&gt;These practical concerns led me back to minivans. When I discovered that Toyota had given the Sienna a major electronic upgrade and made it a hybrid, I was increasingly sold.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-i-was-looking-for&quot;&gt;What I Was Looking For&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Must-haves:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;7-8 seats to accommodate our large family plus occasional guests&lt;&#x2F;li&gt;
&lt;li&gt;Reliability and dependability&lt;&#x2F;li&gt;
&lt;li&gt;Good fuel economy&lt;&#x2F;li&gt;
&lt;li&gt;Reasonable maintenance costs&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;the-shopping-experience&quot;&gt;The Shopping Experience&lt;&#x2F;h1&gt;
&lt;p&gt;Working with dealerships was frustrating. They&#x27;d present spec sheets where the numbers didn&#x27;t add up, sneaking in &quot;market adjustment fees&quot; due to high demand. Most wouldn&#x27;t budge on price - it was take it or leave it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;test-drives&quot;&gt;Test Drives&lt;&#x2F;h2&gt;
&lt;p&gt;I test drove the Toyota Grand Highlander and Cadillac Escalade. Both had their merits, but neither felt quite right for our needs.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-decision&quot;&gt;The Decision&lt;&#x2F;h1&gt;
&lt;p&gt;I ultimately chose the 2025 Toyota Sienna XLE. It checked all our practical boxes without the bulk of a full-size SUV.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;negotiation-process&quot;&gt;Negotiation Process&lt;&#x2F;h2&gt;
&lt;p&gt;I contacted multiple dealerships, and most were still tacking on $5,000+ market adjustment fees. Eventually, I found one willing to sell at MSRP with no extra fees - a win in today&#x27;s market.&lt;&#x2F;p&gt;
&lt;p&gt;A word of warning: the dealership will claim they have the best financing rates. Don&#x27;t take their word for it. I ended up financing through Teachers Federal Credit Union at a lower rate than what the dealer offered.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;final-thoughts&quot;&gt;Final Thoughts&lt;&#x2F;h1&gt;
&lt;p&gt;The biggest lesson? Don&#x27;t rush. Taking your time is your best negotiating tactic. Dealers can sense desperation, and in a seller&#x27;s market, patience is your only leverage.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tips-for-future-car-buyers&quot;&gt;Tips for Future Car Buyers&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Know your needs vs. wants&lt;&#x2F;strong&gt; - A week-long rental really helped us understand what living with a particular vehicle would be like&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Shop around for financing&lt;&#x2F;strong&gt; - Credit unions often beat dealer rates&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Be patient&lt;&#x2F;strong&gt; - In a market with markups, the dealer who doesn&#x27;t add fees is worth waiting for&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Consider total cost of ownership&lt;&#x2F;strong&gt; - Fuel economy and maintenance costs add up over time&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h1 id=&quot;the-car&quot;&gt;The Car&lt;&#x2F;h1&gt;
&lt;p&gt;2025 Toyota Sienna XLE. Nothing fancy, just practical. It&#x27;s the perfect blend of space, efficiency, and reliability that our family needs. Sometimes the smartest choice isn&#x27;t the flashiest one.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Real-time Log Monitoring with Claude Code and Expo</title>
        <published>2025-08-21T00:00:00+00:00</published>
        <updated>2025-08-21T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Eladio Caritos
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://caritos.com/posts/claude-code-expo-workflow/"/>
        <id>https://caritos.com/posts/claude-code-expo-workflow/</id>
        
        <content type="html" xml:base="https://caritos.com/posts/claude-code-expo-workflow/">&lt;p&gt;One of the most powerful workflows I&#x27;ve discovered while developing React Native apps with Claude Code is using real-time log monitoring. This simple technique has saved me countless hours of debugging and development time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-problem&quot;&gt;The Problem&lt;&#x2F;h2&gt;
&lt;p&gt;When developing React Native apps with Expo, you&#x27;re often juggling multiple things:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Writing code&lt;&#x2F;li&gt;
&lt;li&gt;Running the development server&lt;&#x2F;li&gt;
&lt;li&gt;Monitoring console logs&lt;&#x2F;li&gt;
&lt;li&gt;Debugging errors&lt;&#x2F;li&gt;
&lt;li&gt;Testing on simulators or devices&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Traditionally, this means constantly switching between your code editor and terminal to check logs, understand errors, and debug issues. It&#x27;s a context-switching nightmare that slows down development.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-solution-real-time-log-piping&quot;&gt;The Solution: Real-time Log Piping&lt;&#x2F;h2&gt;
&lt;p&gt;Here&#x27;s the game-changing command I use:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;npx&lt;&#x2F;span&gt;&lt;span&gt; expo start &amp;gt; logs&#x2F;expo.log &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This simple command redirects all Expo server output (both stdout and stderr) to a log file that Claude Code can monitor in real-time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-this-works-so-well&quot;&gt;Why This Works So Well&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Claude Code can see everything&lt;&#x2F;strong&gt;: By piping logs to a file, Claude Code can read and analyze the entire output history, not just what&#x27;s currently visible in your terminal.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Context-aware debugging&lt;&#x2F;strong&gt;: When an error occurs, Claude Code can immediately see:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The full error stack trace&lt;&#x2F;li&gt;
&lt;li&gt;What was happening before the error&lt;&#x2F;li&gt;
&lt;li&gt;Related warnings or logs&lt;&#x2F;li&gt;
&lt;li&gt;The exact file and line number&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Proactive problem-solving&lt;&#x2F;strong&gt;: Claude Code often catches issues before I even notice them. It can spot deprecation warnings, performance issues, or potential bugs in the log output.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;No more copy-pasting&lt;&#x2F;strong&gt;: Instead of copying error messages to ask Claude Code about them, it already has the full context and can suggest fixes immediately.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;setting-it-up&quot;&gt;Setting It Up&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a logs directory in your project:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;mkdir -p&lt;&#x2F;span&gt;&lt;span&gt; logs
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Add &lt;code&gt;logs&#x2F;&lt;&#x2F;code&gt; to your &lt;code&gt;.gitignore&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;logs&#x2F;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Start your Expo server with log redirection:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;npx&lt;&#x2F;span&gt;&lt;span&gt; expo start &amp;gt; logs&#x2F;expo.log &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;In a Claude Code session, ask it to monitor the logs:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;&amp;quot;Can you check the Expo logs at logs&#x2F;expo.log and help me debug any issues?&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;real-world-examples&quot;&gt;Real-World Examples&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;example-1-mysterious-app-crashes&quot;&gt;Example 1: Mysterious App Crashes&lt;&#x2F;h3&gt;
&lt;p&gt;My app was crashing intermittently on Android. Instead of spending hours adding console.logs everywhere, I just asked Claude Code to analyze the log file. It immediately spotted a memory leak pattern in the logs that I had missed.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;example-2-performance-optimization&quot;&gt;Example 2: Performance Optimization&lt;&#x2F;h3&gt;
&lt;p&gt;Claude Code noticed repeated warnings about large lists being rendered without optimization. It not only identified the issue but also suggested implementing &lt;code&gt;FlatList&lt;&#x2F;code&gt; with proper &lt;code&gt;keyExtractor&lt;&#x2F;code&gt; and &lt;code&gt;getItemLayout&lt;&#x2F;code&gt; props.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;example-3-dependency-conflicts&quot;&gt;Example 3: Dependency Conflicts&lt;&#x2F;h3&gt;
&lt;p&gt;When upgrading Expo SDK versions, the logs showed various compatibility warnings. Claude Code read through all of them and provided a step-by-step plan to resolve each conflict.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tips-for-maximum-effectiveness&quot;&gt;Tips for Maximum Effectiveness&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Keep logs focused&lt;&#x2F;strong&gt;: Clear your log file periodically to keep it manageable:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;echo &lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&amp;quot; &amp;gt; logs&#x2F;expo.log
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Use descriptive console.logs&lt;&#x2F;strong&gt;: Add meaningful log messages in your code. Claude Code can use these as context clues.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Let Claude Code be proactive&lt;&#x2F;strong&gt;: Don&#x27;t wait for errors. Ask Claude Code to periodically check the logs for warnings or potential issues.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Combine with other tools&lt;&#x2F;strong&gt;: This workflow pairs excellently with React Native Debugger and Expo&#x27;s built-in tools.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;beyond-expo&quot;&gt;Beyond Expo&lt;&#x2F;h2&gt;
&lt;p&gt;This pattern works for any development server or long-running process:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Next.js: &lt;code&gt;npm run dev &amp;gt; logs&#x2F;next.log 2&amp;gt;&amp;amp;1&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Node.js apps: &lt;code&gt;node server.js &amp;gt; logs&#x2F;server.log 2&amp;gt;&amp;amp;1&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Docker containers: &lt;code&gt;docker-compose logs -f &amp;gt; logs&#x2F;docker.log 2&amp;gt;&amp;amp;1&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;This simple logging technique has transformed how I work with Claude Code. Instead of being reactive to errors, we can be proactive. Instead of losing context in terminal scrollback, we have a persistent record. Instead of manually copying errors, Claude Code already has the full picture.&lt;&#x2F;p&gt;
&lt;p&gt;Give it a try on your next project. You might be surprised how much time it saves you.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Building Mobile Apps with Claude Code: A Game-Changing Development Experience</title>
        <published>2025-07-20T00:00:00+00:00</published>
        <updated>2025-07-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Eladio Caritos
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://caritos.com/posts/building-mobile-apps-with-claude-code/"/>
        <id>https://caritos.com/posts/building-mobile-apps-with-claude-code/</id>
        
        <content type="html" xml:base="https://caritos.com/posts/building-mobile-apps-with-claude-code/">&lt;p&gt;I&#x27;ve been experimenting with Claude Code for mobile app development recently, and I have to say—it&#x27;s been a remarkable experience that&#x27;s fundamentally changing how I approach building cross-platform mobile applications. If you&#x27;re a mobile developer who hasn&#x27;t tried Claude Code yet, you&#x27;re missing out on what might be the most significant productivity boost since Expo made React Native development accessible to TypeScript developers.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;learning-from-previous-ai-development-failures&quot;&gt;Learning from Previous AI Development Failures&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;ll be honest—this isn&#x27;t my first attempt at building an app with AI assistance. I&#x27;ve had multiple unsuccessful attempts in the past where I&#x27;d jump straight into asking AI tools to generate code, only to end up with fragmented, inconsistent implementations that didn&#x27;t work together as a cohesive application. The problem wasn&#x27;t the AI—it was my approach.&lt;&#x2F;p&gt;
&lt;p&gt;The key difference this time? &lt;strong&gt;Planning before coding.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Instead of diving headfirst into code generation, I spent considerable time creating a comprehensive project structure that provides the AI with the context it needs to build something meaningful. Here&#x27;s what I&#x27;ve learned makes all the difference:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-foundation-comprehensive-project-documentation&quot;&gt;The Foundation: Comprehensive Project Documentation&lt;&#x2F;h3&gt;
&lt;p&gt;Before writing a single line of code, I created several key organizational files:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;CLAUDE.md&lt;&#x2F;strong&gt; - This file contains essential development information and context that helps Claude Code understand my project&#x27;s architecture, coding conventions, and specific requirements. It&#x27;s like giving the AI a thorough onboarding document.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;TODO.md&lt;&#x2F;strong&gt; - A detailed task list that breaks down the app development into manageable chunks. This ensures nothing gets forgotten and provides a clear roadmap for both me and Claude Code to follow.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;wireframes&#x2F;&lt;&#x2F;strong&gt; directory - Visual representations of what each screen should look like. Screenshots, mockups, and UI sketches that give Claude Code a clear understanding of the desired user interface.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;flows&#x2F;&lt;&#x2F;strong&gt; directory - Detailed descriptions of user interactions and navigation patterns. These documents describe how users move through the app, what happens when they tap buttons, and how different features connect together.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;why-context-changes-everything&quot;&gt;Why Context Changes Everything&lt;&#x2F;h3&gt;
&lt;p&gt;What I discovered is that AI code generation is only as good as the context you provide. My previous attempts failed because I was asking for isolated pieces of functionality without explaining how they fit into the bigger picture. It&#x27;s like asking someone to write a chapter of a book without telling them what the book is about.&lt;&#x2F;p&gt;
&lt;p&gt;With this structured approach, Claude Code doesn&#x27;t just generate code—it generates code that fits seamlessly into my app&#x27;s architecture. It understands the user flows, respects the design patterns I&#x27;ve established, and maintains consistency across different features.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-planning-payoff&quot;&gt;The Planning Payoff&lt;&#x2F;h3&gt;
&lt;p&gt;This upfront investment in planning and documentation has paid dividends:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Coherent architecture&lt;&#x2F;strong&gt; - Every component fits together logically&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Consistent UI&#x2F;UX&lt;&#x2F;strong&gt; - The app feels like it was designed by a single team&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Fewer integration issues&lt;&#x2F;strong&gt; - New features work seamlessly with existing code&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Better debugging&lt;&#x2F;strong&gt; - When issues arise, they&#x27;re easier to trace and fix&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Maintainable codebase&lt;&#x2F;strong&gt; - The code follows established patterns and conventions&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;what-makes-claude-code-special-for-mobile-development&quot;&gt;What Makes Claude Code Special for Mobile Development&lt;&#x2F;h2&gt;
&lt;p&gt;Claude Code isn&#x27;t just another AI coding assistant. It&#x27;s a comprehensive development environment that understands the nuances of modern mobile development, from React Native component patterns to Expo&#x27;s managed workflow intricacies. What sets it apart is its ability to not just write code, but to understand the broader context of full-stack mobile app architecture—from frontend React Native components to Supabase backend integration.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;real-time-code-generation-and-component-creation&quot;&gt;Real-Time Code Generation and Component Creation&lt;&#x2F;h3&gt;
&lt;p&gt;One of the most impressive features is how Claude Code can generate entire React Native components based on simple descriptions. I recently asked it to create a custom tab navigation component with smooth animations, and it delivered production-ready code that would have taken me hours to write and debug. The component included proper TypeScript interfaces, accessibility features, and smooth animations—all from a basic description of what I wanted.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;accelerating-complex-features&quot;&gt;Accelerating Complex Features&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;supabase-integration-made-simple&quot;&gt;Supabase Integration Made Simple&lt;&#x2F;h3&gt;
&lt;p&gt;Building robust backend integration is traditionally one of the more time-consuming aspects of mobile development. Claude Code excels at creating clean, maintainable Supabase integration code that handles authentication, real-time subscriptions, and database operations. It understands the nuances of Supabase&#x27;s client libraries and can generate comprehensive service classes with proper error handling and TypeScript types.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;expo-specific-features-and-navigation&quot;&gt;Expo-Specific Features and Navigation&lt;&#x2F;h3&gt;
&lt;p&gt;One area where Claude Code really shines is in understanding Expo&#x27;s ecosystem. It can generate navigation setups using Expo Router, handle device capabilities, and integrate with Expo&#x27;s managed services. Whether it&#x27;s setting up authentication flows, configuring app builds, or implementing platform-specific features, Claude Code understands the Expo workflow and generates code that follows best practices.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-learning-amplifier&quot;&gt;The Learning Amplifier&lt;&#x2F;h2&gt;
&lt;p&gt;What I find most valuable about Claude Code isn&#x27;t just that it writes code for me—it&#x27;s that it explains the &lt;em&gt;why&lt;&#x2F;em&gt; behind architectural decisions. When I ask for a particular implementation, it doesn&#x27;t just provide the code; it explains the trade-offs, suggests alternatives, and helps me understand React Native and Expo development patterns I might not have encountered otherwise.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;testing-and-quality-assurance&quot;&gt;Testing and Quality Assurance&lt;&#x2F;h3&gt;
&lt;p&gt;Claude Code has also improved my testing practices. It generates comprehensive Jest tests for React Native components and can even suggest testing scenarios for Expo-specific features. The tests it creates are thorough and follow testing best practices, covering edge cases I might not have considered on my own.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;real-world-impact&quot;&gt;Real-World Impact&lt;&#x2F;h2&gt;
&lt;p&gt;Since incorporating Claude Code into my mobile development workflow, I&#x27;ve seen:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;50% reduction in development time&lt;&#x2F;strong&gt; for new features&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Significantly fewer bugs&lt;&#x2F;strong&gt; due to better code patterns and comprehensive testing&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Improved code quality&lt;&#x2F;strong&gt; through consistent architecture and best practices&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Faster learning curve&lt;&#x2F;strong&gt; when exploring new React Native libraries and Expo features&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;the-future-of-mobile-development&quot;&gt;The Future of Mobile Development&lt;&#x2F;h2&gt;
&lt;p&gt;Claude Code represents a paradigm shift in how we approach mobile development. It&#x27;s not replacing developers—it&#x27;s amplifying our capabilities and allowing us to focus on the creative and strategic aspects of app building rather than getting bogged down in boilerplate code.&lt;&#x2F;p&gt;
&lt;p&gt;The combination of AI assistance with modern development tools creates a powerful synergy. Expo&#x27;s development experience, Supabase&#x27;s backend services, and Claude Code&#x27;s intelligent code generation creates an environment where building complex cross-platform mobile apps becomes more accessible and enjoyable.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;getting-started&quot;&gt;Getting Started&lt;&#x2F;h2&gt;
&lt;p&gt;If you&#x27;re interested in trying Claude Code for mobile development, here&#x27;s what I recommend based on my journey from failed attempts to success:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;start-with-planning-not-coding&quot;&gt;Start with Planning, Not Coding&lt;&#x2F;h3&gt;
&lt;p&gt;Before you write a single line of code, invest time in documentation:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create a CLAUDE.md file&lt;&#x2F;strong&gt; - Document your project&#x27;s architecture, coding conventions, and requirements&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Build a comprehensive TODO.md&lt;&#x2F;strong&gt; - Break down your app into specific, manageable tasks&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Design wireframes&lt;&#x2F;strong&gt; - Create visual mockups of your screens, even if they&#x27;re hand-drawn sketches&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Map user flows&lt;&#x2F;strong&gt; - Document how users navigate through your app and interact with features&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;test-with-small-features-first&quot;&gt;Test with Small Features First&lt;&#x2F;h3&gt;
&lt;p&gt;Start with a small project or feature, but make sure it&#x27;s properly documented. The learning curve is minimal, and the productivity gains become apparent almost immediately when you provide proper context.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;think-partnership-not-generation&quot;&gt;Think Partnership, Not Generation&lt;&#x2F;h3&gt;
&lt;p&gt;The key is to think of Claude Code as a knowledgeable pair programming partner rather than just a code generator. Give it the context it needs to understand your vision, and it will help you build something truly cohesive.&lt;&#x2F;p&gt;
&lt;p&gt;The future of mobile development is here, and it&#x27;s more exciting than ever. With tools like Claude Code, we&#x27;re entering an era where the limitation isn&#x27;t our ability to implement ideas—it&#x27;s our ability to imagine them.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;Have you tried Claude Code for mobile development? I&#x27;d love to hear about your experiences and the kinds of apps you&#x27;re building with AI assistance. Feel free to reach out and share your stories!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>A Memorable Family Adventure in Paris</title>
        <published>2025-03-06T00:00:00+00:00</published>
        <updated>2025-03-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Eladio Caritos
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://caritos.com/posts/a-memorable-family-adventure-in-paris/"/>
        <id>https://caritos.com/posts/a-memorable-family-adventure-in-paris/</id>
        
        <content type="html" xml:base="https://caritos.com/posts/a-memorable-family-adventure-in-paris/">&lt;h1 id=&quot;a-memorable-family-adventure-in-paris&quot;&gt;A Memorable Family Adventure in Paris&lt;&#x2F;h1&gt;
&lt;p&gt;Two weeks have passed since our return to the United States, and I&#x27;m already nostalgic about our family adventure in Paris. The City of Light left an indelible mark on all of us, creating memories we&#x27;ll cherish forever.&lt;&#x2F;p&gt;
&lt;p&gt;The excitement began well before our departure. As an enthusiast of Rick Steves&#x27; travel philosophy and an active member of the &lt;a href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;onebag&#x2F;&quot;&gt;onebag subreddit&lt;&#x2F;a&gt;, I was determined to put minimalist packing into practice. Rick&#x27;s wisdom resonated with me: &quot;Don&#x27;t pack for the worst-case scenario. Pack for the best-case scenario and buy yourself out of any jams.&quot; This approach to &lt;a href=&quot;https:&#x2F;&#x2F;www.ricksteves.com&#x2F;travel-tips&#x2F;packing-light&#x2F;packing-smart&quot;&gt;packing smart and traveling light&lt;&#x2F;a&gt; proved invaluable throughout our journey.&lt;&#x2F;p&gt;
&lt;p&gt;Our week in Paris was filled with classic attractions and unexpected delights. While we explored iconic landmarks like the Eiffel Tower, Louvre Museum, and Notre Dame, some of our most memorable moments came from simply wandering the charming streets of Paris. We embraced the local way of life, navigating the Metro and bus system like true Parisians. Following our noses to small, inviting restaurants led us to some of the most authentic and delicious meals of our trip.&lt;&#x2F;p&gt;
&lt;p&gt;A highlight of our stay was fulfilling my wife&#x27;s dream of experiencing dinner at the legendary Moulin Rouge. The spectacular show and ambiance made for an unforgettable evening that exceeded our expectations.&lt;&#x2F;p&gt;
&lt;p&gt;Traveling with children can be challenging, but our kids were remarkable travel companions. While there were occasional moments of fatigue and resistance (as expected), we struck a balance between adult interests and child-friendly activities. This compromise helped everyone feel invested in our family adventure.&lt;&#x2F;p&gt;
&lt;p&gt;For those interested in the practical details, our total expenses came to $6,850. By booking six months in advance, we secured excellent airfare at $2,300 for our family of six. Our comfortable Airbnb accommodation cost $1,300, with the remaining budget covering food, attractions, and local transportation.&lt;&#x2F;p&gt;
&lt;p&gt;This Parisian adventure has reignited my passion for travel. It&#x27;s remarkable how stepping out of our daily routines can refresh our perspective on life. Navigating a new city, sampling unfamiliar cuisines, and tackling unexpected challenges as a family didn&#x27;t just create lasting memories – it reminded us that life&#x27;s greatest moments often lie outside our comfort zone.&lt;&#x2F;p&gt;
&lt;p&gt;The journey has taught us that travel isn&#x27;t just about checking off tourist attractions; it&#x27;s about growing together as a family and embracing new experiences with an open mind and heart. As we settle back into our routine, we&#x27;re already dreaming about our next family adventure.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Notes on Rust Programming Language</title>
        <published>2025-01-05T00:00:00+00:00</published>
        <updated>2025-01-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Eladio Caritos
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://caritos.com/posts/notes-on-rust-programming-language-book/"/>
        <id>https://caritos.com/posts/notes-on-rust-programming-language-book/</id>
        
        <content type="html" xml:base="https://caritos.com/posts/notes-on-rust-programming-language-book/">&lt;h1 id=&quot;rust-programming-language&quot;&gt;Rust Programming Language&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;7-managing-growing-projects-with-packages-crates-and-modules&quot;&gt;7 - Managing Growing Projects with Packages, Crates, and Modules&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;encapsulation
&lt;ul&gt;
&lt;li&gt;lets you reuse code at a higher level&lt;&#x2F;li&gt;
&lt;li&gt;once you&#x27;ve implemented an operation, other code can call your code via its public interface without having to know how the implementation works&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;scope
&lt;ul&gt;
&lt;li&gt;the nested context in which code is written has a set of names that are defined as &quot;in scope&quot;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;rust features to manage code organization
&lt;ul&gt;
&lt;li&gt;Packages
&lt;ul&gt;
&lt;li&gt;a cargo feature that lets you build, test, and share craftes&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Crates
&lt;ul&gt;
&lt;li&gt;a tree of modules that produces a library or executable&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Modules and use
&lt;ul&gt;
&lt;li&gt;let you control the organization, scope, and privacy of paths&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Paths
&lt;ul&gt;
&lt;li&gt;a way of naming an item, such as a struct, function, or module&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;packages-and-crates&quot;&gt;Packages and Crates&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;crate
&lt;ul&gt;
&lt;li&gt;smallest amount of code that the Rust compiler considers at a time&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;binary crate
&lt;ul&gt;
&lt;li&gt;programs you can compile to an executable that you can run&lt;&#x2F;li&gt;
&lt;li&gt;i.e. command line program or server&lt;&#x2F;li&gt;
&lt;li&gt;must have a function &quot;main&quot;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;library crate
&lt;ul&gt;
&lt;li&gt;don&#x27;t have a main function&lt;&#x2F;li&gt;
&lt;li&gt;don&#x27;t compile to an executable&lt;&#x2F;li&gt;
&lt;li&gt;define functionality intended to be shared with multiple projects&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;crate root
&lt;ul&gt;
&lt;li&gt;source file that the Rust compiler starts from and makes up the root module of your crate&lt;&#x2F;li&gt;
&lt;li&gt;src&#x2F;main.rs&lt;&#x2F;li&gt;
&lt;li&gt;src&#x2F;lib.rs&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;package
&lt;ul&gt;
&lt;li&gt;bundle of one or more crates that provides a set of functionality&lt;&#x2F;li&gt;
&lt;li&gt;contains Cargo.toml
&lt;ul&gt;
&lt;li&gt;describes how to build those crates&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;defining-modules-to-control-scope-and-privacy&quot;&gt;Defining Modules to Control Scope and Privacy&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;paths
&lt;ul&gt;
&lt;li&gt;allow you to name items&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;use
&lt;ul&gt;
&lt;li&gt;brings a path into scope&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;pub
&lt;ul&gt;
&lt;li&gt;make items public&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;modules
&lt;ul&gt;
&lt;li&gt;organize code within a crate for readability and easy reuse&lt;&#x2F;li&gt;
&lt;li&gt;allow control of privacy of items because code within a module is private by default&lt;&#x2F;li&gt;
&lt;li&gt;mod
&lt;ul&gt;
&lt;li&gt;how to define a module&lt;&#x2F;li&gt;
&lt;li&gt;we can place modules inside modules&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;paths-for-referring-to-an-item-in-the-module-tree&quot;&gt;Paths for Referring to an item in the Module Tree&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;absolute path
&lt;ul&gt;
&lt;li&gt;full path starting from a crate root; for code from an external crate, the absolute path begins with the crate name, and for code from the current crate, it starts with the literal crate&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;relative path
&lt;ul&gt;
&lt;li&gt;starts from the current module and uses self, super, or an identified in the current module&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;both absolute path and relative pats are followed by one or more identifiers separated by double colons (::)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;exposing-paths-with-the-pub-keyword&quot;&gt;Exposing Paths with the pub Keyword&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;have to make nested code public as well&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;starting-relative-paths-with-super&quot;&gt;Starting Relative Paths with super&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;using &quot;super&quot; allows us to reference an item that we know is in the parent module, which can make rearranging the module tree easier when the module is closely related to the parent&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;making-structs-and-enums-public&quot;&gt;Making Structs and Enums Public&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;if we use &quot;pub&quot; before a struct definition, we make the struct public, but the struct&#x27;s fields will still be private&lt;&#x2F;li&gt;
&lt;li&gt;we can make each field public or not on a case-by-case basis&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;bringing-paths-into-scope-with-the-use-keyword&quot;&gt;Bringing Paths into Scope with the use Keyword&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;we can create a shortcut to a path with the use keyword once, and tehn use the shorter name everhwere else in the scope&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;creating-idiomatic-use-paths&quot;&gt;Creating Idiomatic use Paths&lt;&#x2F;h4&gt;
&lt;h4 id=&quot;providing-new-names-with-pub-use&quot;&gt;Providing New Names with pub use&lt;&#x2F;h4&gt;
&lt;h4 id=&quot;re-exporting-names-with-pub-usee&quot;&gt;Re-exporting Names with pub usee&lt;&#x2F;h4&gt;
&lt;h4 id=&quot;using-external-packages&quot;&gt;Using External Packages&lt;&#x2F;h4&gt;
&lt;h4 id=&quot;using-nested-paths-to-clean-up-large-use-lists&quot;&gt;Using Nested Paths to Clean Up Large use Lists&lt;&#x2F;h4&gt;
&lt;h4 id=&quot;the-glob-operator&quot;&gt;The glob operator&lt;&#x2F;h4&gt;
&lt;h3 id=&quot;separating-modules-into-different-files&quot;&gt;Separating Modules into Different Files&lt;&#x2F;h3&gt;
&lt;h3 id=&quot;summary&quot;&gt;Summary&lt;&#x2F;h3&gt;
&lt;h2 id=&quot;8-common-collections&quot;&gt;8 Common Collections&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;collections contain multiple Values&lt;&#x2F;li&gt;
&lt;li&gt;unlike the built-in array and tuple types, the data that these colelctions point to is stored on the heap.&lt;&#x2F;li&gt;
&lt;li&gt;amount of data does not need to be known at runtime.&lt;&#x2F;li&gt;
&lt;li&gt;vector
&lt;ul&gt;
&lt;li&gt;allows you to store a varaible number of values next to each other&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;string
&lt;ul&gt;
&lt;li&gt;collection of characters&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;hash map
&lt;ul&gt;
&lt;li&gt;allows yhou tro associate a value iwth a specific key&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;storing-lists-of-values-with-vectors&quot;&gt;Storing Lists of Values with Vectors&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;create a new vector
&lt;ul&gt;
&lt;li&gt;let v: Vec&lt;i32&gt; = Vec::new();&lt;&#x2F;li&gt;
&lt;li&gt;let v = vec![1,2,3];&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;updating a vector
&lt;ul&gt;
&lt;li&gt;use the push method
&lt;ul&gt;
&lt;li&gt;let mut v = Vec::new();&lt;&#x2F;li&gt;
&lt;li&gt;v.push(5);&lt;&#x2F;li&gt;
&lt;li&gt;v.push(6);&lt;&#x2F;li&gt;
&lt;li&gt;v.push(7);&lt;&#x2F;li&gt;
&lt;li&gt;v.push(8);&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;reading elements in a vector
&lt;ul&gt;
&lt;li&gt;get an element by indexing
&lt;ul&gt;
&lt;li&gt;let third: &amp;amp;i32 = &amp;amp;v[2];&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;get an element by get
&lt;ul&gt;
&lt;li&gt;let third: Option&amp;lt;&amp;amp;i32&amp;gt; = v.get(2);&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;stoing-utf-8-encoded-text-with-strings&quot;&gt;Stoing UTF-8 Encoded Text with Strings&lt;&#x2F;h3&gt;
&lt;h3 id=&quot;storing-keys-with-associated-values-in-hash-maps&quot;&gt;Storing Keys with Associated Values in Hash Maps-&lt;&#x2F;h3&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Writing Dr Mario game with Bevy</title>
        <published>2025-01-05T00:00:00+00:00</published>
        <updated>2025-01-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Eladio Caritos
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://caritos.com/posts/writing-dr-mario-game-with-bevy/"/>
        <id>https://caritos.com/posts/writing-dr-mario-game-with-bevy/</id>
        
        <content type="html" xml:base="https://caritos.com/posts/writing-dr-mario-game-with-bevy/">&lt;h1 id=&quot;20250106&quot;&gt;20250106&lt;&#x2F;h1&gt;
&lt;p&gt;To make things more exciting for me for the new year, I&#x27;m starting to write a rust bevy game.. I&#x27;ve decided on Dr. Mario.  I was at the arcade recent for my daughters birthday and they had Dr. Mario in it.  It was the game I most enjoyed.  I&#x27;m using ChatGPT to assist me in creating the bevy game.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Writing a Chess Engine in Rust with the help of ChatGPT</title>
        <published>2025-01-04T00:00:00+00:00</published>
        <updated>2025-01-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Eladio Caritos
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://caritos.com/posts/writing-a-chess-engine-in-rust/"/>
        <id>https://caritos.com/posts/writing-a-chess-engine-in-rust/</id>
        
        <content type="html" xml:base="https://caritos.com/posts/writing-a-chess-engine-in-rust/">&lt;h1 id=&quot;20250104&quot;&gt;20250104&lt;&#x2F;h1&gt;
&lt;p&gt;I&#x27;ve been reading the book &quot;Rust Programming Language&quot; but I feel I need more hands on training.  With that in mind, I thought it would be a cool project to write a chess engine.  Learning to program in Rust while working with a hobby I love would help me stick with the project.  Learning with ChatGTP by my side has been a really cool experience. It&#x27;s providing step by step instructions on how to write a chess engine. I just started and I&#x27;ve already represented the chess board usig a 2D array.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Ktor Telegram Integration</title>
        <published>2024-08-28T00:00:00+00:00</published>
        <updated>2024-08-28T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Eladio Caritos
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://caritos.com/posts/ktor-telegram-integration/"/>
        <id>https://caritos.com/posts/ktor-telegram-integration/</id>
        
        <content type="html" xml:base="https://caritos.com/posts/ktor-telegram-integration/">&lt;p&gt;I was listening to a &lt;a href=&quot;https:&#x2F;&#x2F;lexfridman.com&#x2F;pieter-levels-transcript&#x2F;&quot;&gt;Lex Fridman interview with Pietel Levels&lt;&#x2F;a&gt; and one of the tip Pieter does it send error messages to his telegram account.&lt;&#x2F;p&gt;
&lt;p&gt;I was able to implement this on my ktor app pretty easily. Moving forward, I&#x27;ll ping myself regarding any errors in the websites.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;imgur.com&#x2F;4k2UWsj.jpeg&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Ktor Autoreload</title>
        <published>2024-08-03T00:00:00+00:00</published>
        <updated>2024-08-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Eladio Caritos
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://caritos.com/posts/ktor-autoreload/"/>
        <id>https://caritos.com/posts/ktor-autoreload/</id>
        
        <content type="html" xml:base="https://caritos.com/posts/ktor-autoreload/">&lt;p&gt;The documentation for Ktor Autoreload can be found &lt;a href=&quot;https:&#x2F;&#x2F;ktor.io&#x2F;docs&#x2F;server-auto-reload.html#enable&quot;&gt;here&lt;&#x2F;a&gt;.  I had issues wih using the EmbeddedServer so I switched to EngineMain paired with an application configuration file.&lt;&#x2F;p&gt;
&lt;p&gt;To recompile on changes, i had to run the command &quot;.&#x2F;gradlew -t build&quot; and then on a separate terminal &quot;.&#x2F;gradlew run&quot;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;i.imgur.com&#x2F;0UTa0V0.jpeg&quot; alt=&quot;&quot; &#x2F;&gt;
&lt;img src=&quot;https:&#x2F;&#x2F;i.imgur.com&#x2F;KXA4Xjq.jpeg&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Postgres Complexity, Moving to SQLite</title>
        <published>2024-08-02T00:00:00+00:00</published>
        <updated>2024-08-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Eladio Caritos
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://caritos.com/posts/postgres-complexity/"/>
        <id>https://caritos.com/posts/postgres-complexity/</id>
        
        <content type="html" xml:base="https://caritos.com/posts/postgres-complexity/">&lt;p&gt;I recently faced challenges with database migration and maintaining data consistency between the public version and my local system. Every time I changed the schema of some models, I found it difficult to transfer those changes from my local development environment to the public server hosted on DigitalOcean.&lt;&#x2F;p&gt;
&lt;p&gt;While searching for solutions, I stumbled upon a &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=0rlATWBNvMw&quot;&gt;YouTube interview with DHH on SQLite&lt;&#x2F;a&gt;. The interview made a compelling case for switching from Postgres to SQLite, which seemed to be a good fit for my current needs. With SQLite, the database is simply a file, so I only need to manage one copy at a time, simplifying the migration process significantly.&lt;&#x2F;p&gt;
&lt;p&gt;Inspired by this, I’ve decided to spend today migrating my tennis app from Postgres to SQLite. This switch will help me delay confronting the complexity of database migrations and focus more on development.&lt;&#x2F;p&gt;
&lt;p&gt;Stay tuned for updates on how this transition goes and any lessons learned along the way!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Resume</title>
        <published>2024-07-20T00:00:00+00:00</published>
        <updated>2024-07-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Eladio Caritos
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://caritos.com/posts/resume/"/>
        <id>https://caritos.com/posts/resume/</id>
        
        <content type="html" xml:base="https://caritos.com/posts/resume/">&lt;h1 id=&quot;objective&quot;&gt;Objective&lt;&#x2F;h1&gt;
&lt;p&gt;To secure a software engineering position in a company where my experiences, accomplishments, and proficiency will allow opportunity for growth.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;experience&quot;&gt;Experience&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;architecture-engineer-passur-aerospace-05-18-03-20&quot;&gt;&lt;em&gt;Architecture Engineer&lt;&#x2F;em&gt;, PASSUR Aerospace, 05&#x2F;18 – 03&#x2F;20&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Improve the quality and agility of PASSUR Technology&lt;&#x2F;li&gt;
&lt;li&gt;Select, develop, and maintain tools used in development&lt;&#x2F;li&gt;
&lt;li&gt;Educate and support development and system engineering stat in their use&lt;&#x2F;li&gt;
&lt;li&gt;Research new tools and processes for continuous improvement&lt;&#x2F;li&gt;
&lt;li&gt;Improved Zabbix monitor by implementing agents using JMX technology using Spring Boot framework.&lt;&#x2F;li&gt;
&lt;li&gt;Integrated Pacemaker, high-availability cluster resource manager to provide resource dependability.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;application-developer-hbc-digital-07-16-09-17&quot;&gt;&lt;em&gt;Application Developer&lt;&#x2F;em&gt;, HBC Digital, 07&#x2F;16 - 09&#x2F;17&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Lord &amp;amp; Taylor migration unto a common code base&lt;&#x2F;li&gt;
&lt;li&gt;Migrating Java 6 monolith to microservices using Scala and Play framework&lt;&#x2F;li&gt;
&lt;li&gt;Search implementation using Endeca
All code supports&#x2F;maintains&#x2F;updates the following websites:
http:&#x2F;&#x2F;www.lordandtaylor.com
http:&#x2F;&#x2F;www.saksfiftavenue.com
http:&#x2F;&#x2F;www.saksoff5th.com&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;senior-software-engineer-ca-technologies-07-12-06-16&quot;&gt;&lt;em&gt;Senior Software Engineer&lt;&#x2F;em&gt;, CA Technologies, 07&#x2F;12 - 06&#x2F;16&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Updated CA InterTest’s Eclipse¬-based GUI to include C Support&lt;&#x2F;li&gt;
&lt;li&gt;2nd place winner in site wide Hackathon contest.&lt;&#x2F;li&gt;
&lt;li&gt;Expedite GA release of CA File Master Plus MVS Eclipse¬-based GUI&lt;&#x2F;li&gt;
&lt;li&gt;Transitioning Team to Eclipse 4 for CA File Master Plus IMS Eclipse¬-based GUI&lt;&#x2F;li&gt;
&lt;li&gt;Improving Team’s Code quality output by implementing TDD (using Junit &#x2F; SWTBot)&lt;&#x2F;li&gt;
&lt;li&gt;Implemented XML Processing via JAXB APIs, less errors in code and easier transitions with schema modifications&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;software-developer-spling-inc-08-11-01-12&quot;&gt;&lt;em&gt;Software Developer&lt;&#x2F;em&gt;, Spling Inc., 08&#x2F;11 - 01&#x2F;12&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Website development using Python (Django) &amp;amp; Javascript (Backbone.js &#x2F; JQuery)&lt;&#x2F;li&gt;
&lt;li&gt;Part of DreamIt Ventures startup incubator program in learning to build a successful startup. ¬&lt;&#x2F;li&gt;
&lt;li&gt;Developed Facebook&#x2F;Twitter integration into site which became the leading source for new users&lt;&#x2F;li&gt;
&lt;li&gt;Developed Chrome Extension to easily post to website.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;application-programmer-adeptra-06-09-03-11&quot;&gt;&lt;em&gt;Application Programmer&lt;&#x2F;em&gt;, Adeptra, 06&#x2F;09 - 03&#x2F;11&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Developing Customer Applications using Java and Javascript&lt;&#x2F;li&gt;
&lt;li&gt;Convert Customer&#x27;s documented application requirements into functional applications&lt;&#x2F;li&gt;
&lt;li&gt;Created Excel Merge Tool implementing Apache POI library to decrease time developing Customer Applications.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;senior-software-engineer-nortel-07-98-06-09&quot;&gt;&lt;em&gt;Senior Software Engineer&lt;&#x2F;em&gt;, Nortel, 07&#x2F;98 - 06&#x2F;09&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Second place winner for Agile Prototype Environment Developer Contest, a company wide programming competition to develop a web application that integrates with the Agile Communication Environment web services. Developed Bus Notification Service using GWT.&lt;&#x2F;li&gt;
&lt;li&gt;Winner of the Enterprise Solutions Award of Distinction, an award to recognize outstanding achievements in delivering key business outcomes while demonstrating Nortel’s Core Values and behaviors.&lt;&#x2F;li&gt;
&lt;li&gt;Development of Service Creation Environment, an Eclipse Plugin that graphically creates voice applications. In charge of the graphical editor portion of the Plugin, using ILOG Diagrammer’s API to implement nodes &amp;amp; links and the network that connects them.&lt;&#x2F;li&gt;
&lt;li&gt;Developed Voice Portable Application Framework using J2EE architecture. Development includes database design and implementation using MySQL and DB2. Creating EJB component to access database and LDAP directory. JSP and Servlet development front end access to EJB component. Created Java utility that updates database through XML interface using JDOM. Implementation of SNMP interface using Java Dynamic Management Kit. Speech Recognition integration using VXML, Nuance, and Speechworks. Integrated testing through JUNIT.&lt;&#x2F;li&gt;
&lt;li&gt;Programmed application encoder &#x2F; decoder libraries using C&#x2F;C++ for telecommunication protocols such as GR¬1129, SR¬3511, and CS1R which enables Nortel’s Intelligent Peripherals application layer to understand Abstract Syntax Notation Specification instruction.&lt;&#x2F;li&gt;
&lt;li&gt;Developed and supported network application software that supports redundancy using C&#x2F;C++ and shell scripting that enables Nortel’s Interactive Voice Response Systems to communicate with one or more external hosts through TCP&#x2F;IP connection&lt;&#x2F;li&gt;
&lt;li&gt;Developed and supported telecommunication networks and services in the Advance Intelligent Network environment. Constructed Nortel Automated National directory Assistance integrating Nuance Speech Recognition software to provide the operator with advance knowledge of the query enabling the reduction of call time, increasing customer satisfaction, and improve throughput of the system. Implemented Explicit Call Transfer supplementary service, which enables Nortel’s Voice Processing System to allow switch bridging, freeing up resources for the VPS to reuse.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;education&quot;&gt;Education&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;M.S Computer Science&lt;&#x2F;em&gt;, 2002
NYU Polytechnic School of Engineering, Brooklyn, NY&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;B.E. Electrical Engineering&lt;&#x2F;em&gt;, 1998
State University of New York at Stony Brook, Stony Brook, NY&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Embracing Docker in my Workflow</title>
        <published>2024-07-19T00:00:00+00:00</published>
        <updated>2024-07-19T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Eladio Caritos
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://caritos.com/posts/embracing-docker-in-my-workflow/"/>
        <id>https://caritos.com/posts/embracing-docker-in-my-workflow/</id>
        
        <content type="html" xml:base="https://caritos.com/posts/embracing-docker-in-my-workflow/">&lt;p&gt;Recently, I&#x27;ve integrated Docker into my development workflow. While it introduces some friction compared to my previous setup, the benefits of using Docker are worth the extra steps.&lt;&#x2F;p&gt;
&lt;p&gt;Previously, I could simply press CTRL-R to run the latest code locally on my machine and test out changes instantaneously. However, with Docker, I need to execute a series of commands in the terminal:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;.&#x2F;gradlew build
&lt;&#x2F;span&gt;&lt;span&gt;docker-compose build --no-cache
&lt;&#x2F;span&gt;&lt;span&gt;docker-compose down
&lt;&#x2F;span&gt;&lt;span&gt;docker-compose up -d
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Although these additional steps can be cumbersome, Docker provides a consistent environment for both local development and remote hosting, ensuring that my code runs smoothly across different platforms.&lt;&#x2F;p&gt;
&lt;p&gt;In the next few weeks, I plan to streamline these steps to reduce friction and improve my workflow. Using Docker is a valuable investment in maintaining a consistent development environment, and I’m confident that with some adjustments, it will enhance my productivity even further.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>My Essential Tools for a Portable Workstation</title>
        <published>2024-07-18T00:00:00+00:00</published>
        <updated>2024-07-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Eladio Caritos
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://caritos.com/posts/my-essential-tools-for-a-portable-workstation/"/>
        <id>https://caritos.com/posts/my-essential-tools-for-a-portable-workstation/</id>
        
        <content type="html" xml:base="https://caritos.com/posts/my-essential-tools-for-a-portable-workstation/">&lt;img src=&quot;https:&#x2F;&#x2F;i.imgur.com&#x2F;Wa9SNsI.jpeg&quot; alt=&quot;battlestation&quot; height=&quot;500&quot;&#x2F;&gt;
&lt;h1 id=&quot;hardware&quot;&gt;Hardware&lt;&#x2F;h1&gt;
&lt;p&gt;As someone who likes to stay mobile, I’ve set up a portable workstation to ensure productivity wherever I go. Here&#x27;s a rundown of my current setup:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;M1 MacBook Air: This lightweight and powerful machine is perfect for my needs. The M1 chip offers excellent performance, and the portability is unbeatable.&lt;&#x2F;li&gt;
&lt;li&gt;Laptop Stand: To improve ergonomics, I use a stand that raises the screen height. This, combined with a book for extra elevation, helps reduce neck and shoulder strain—a crucial adjustment as I’ve noticed more discomfort with prolonged computer use.&lt;&#x2F;li&gt;
&lt;li&gt;External Keyboard: I’m currently using an old Apple keyboard from my previous iMac. Although functional, it’s showing its age; the &quot;esc&quot; key no longer works, so I’ve remapped it to &quot;F1&quot;. An upgrade might be in order soon.&lt;&#x2F;li&gt;
&lt;li&gt;Bluetooth Mouse: My mouse is small and portable, featuring a scroll wheel for convenience. It’s nothing fancy but gets the job done.&lt;&#x2F;li&gt;
&lt;li&gt;Bose Headphones: These headphones are essential for blocking out noise and helping me concentrate, especially in bustling environments.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;software&quot;&gt;Software&lt;&#x2F;h1&gt;
&lt;p&gt;As a software developer, I rely on various tools to streamline my workflow:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;IntelliJ IDEA: After experimenting with different IDEs and spending too much time customizing nvim, I’ve settled on IntelliJ IDEA. It’s robust and user-friendly, though I’m still learning all the shortcuts. I plan to stick with it for the long term.&lt;&#x2F;li&gt;
&lt;li&gt;GitHub Desktop: For Git management, I prefer GitHub Desktop over the terminal. It’s more intuitive for me and simplifies version control tasks.&lt;&#x2F;li&gt;
&lt;li&gt;Firefox: I switched to Firefox as my default browser after encountering ad-blocking issues with Google Chrome. Firefox has been reliable and aligns better with my needs.&lt;&#x2F;li&gt;
&lt;li&gt;Obsidian: For note-taking, Obsidian is my go-to app. I appreciate its ability to link notes and visualize connections. Plus, it’s free to use across both my phone and computer.&lt;&#x2F;li&gt;
&lt;li&gt;Fantastical: This app helps me keep my calendar and to-do list organized. Its integration features make managing tasks and schedules much easier.&lt;&#x2F;li&gt;
&lt;li&gt;YouTube&#x27;s LOFI Girl: Background music is vital for maintaining focus, and I often listen to YouTube&#x27;s LOFI girl while working.&lt;&#x2F;li&gt;
&lt;li&gt;Raycast Pomodoro Timer: To enhance productivity, I’m experimenting with the Pomodoro timer in Raycast, breaking work into intervals to maintain concentration and efficiency.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
</feed>
