[{"data":1,"prerenderedAt":310},["ShallowReactive",2],{"case-study-project-raul":3},{"id":4,"title":5,"accent":6,"body":7,"description":273,"extension":286,"liveUrl":287,"meta":288,"metrics":289,"navigation":298,"order":299,"path":300,"role":301,"seo":302,"stem":303,"summary":304,"tech":305,"year":308,"__hash__":309},"caseStudies\u002Fcase-studies\u002Fproject-raul.md","VisaNav","violet",{"type":8,"value":9,"toc":272},"minimark",[10,13,18,27,31,34,37,45,49,54,57,104,108,112,116,120,127,131,134,137,144,148,151,157,163,169,173,176,183,194,220,223,227,230,233,240,243,250,254,265,269],[11,12],"raul-brand",{},[14,15,17],"h2",{"id":16},"the-problem","The problem",[19,20,21,22,26],"p",{},"Immigration guidance is high-stakes, constantly changing, and buried in dense official sources. The people who need it most are often the least equipped to find it: the answers live in English legalese spread across USCIS, the State Department, and the immigration courts, and a wrong answer can cost someone years. So people guess, ask a cousin, or pay for answers they could have found if the rules were easier to read. I wanted an assistant that answers from ",[23,24,25],"strong",{},"real USCIS data"," instead of a model's memory, and that points people to real help when a chatbot isn't enough.",[14,28,30],{"id":29},"listening-before-building","Listening before building",[19,32,33],{},"I didn't start in the editor. I started by talking with organizations that serve immigrant communities, to understand what people actually walk in asking for and where the existing help falls short.",[19,35,36],{},"The plan at the time was a legal SaaS: a trusted assistant plus a referral network, serving individuals for free while the organizations and firms that work with immigrants paid for it.",[19,38,39,40,44],{},"Those conversations shaped the product directly. People need a plain-language answer about where they stand, and right after that they need a person: a clinic, a pro-bono attorney, an accredited representative. That is why VisaNav is a grounded chat ",[41,42,43],"em",{},"and"," a public directory of resources, not just a chatbot.",[14,46,48],{"id":47},"what-i-built","What I built",[50,51],"media-figure",{"caption":52,"src":53},"The chat. Javi, the assistant, opens with a single question box and no account required.","\u002Fimages\u002Fraul\u002Fchat-home.png",[19,55,56],{},"VisaNav (codenamed Project Raul while I built it) is a full product, not a notebook:",[58,59,60,71,81,98],"ul",{},[61,62,63,66,67,70],"li",{},[23,64,65],{},"Retrieval."," Scrapy spiders pull USCIS forms, instructions, and pages; a PySpark job cleans and enriches the text; the chunks are embedded into a ",[23,68,69],{},"Pinecone"," index, 6,600 of them for the US.",[61,72,73,76,77,80],{},[23,74,75],{},"The agent."," A ",[23,78,79],{},"Pydantic-AI"," agent with one tool, semantic search. When a question needs facts, a small summary model condenses the conversation into a single search query, the tool pulls the top matches, and the agent writes from those, citing form numbers and official pages. The system prompt draws hard lines: no tax, no medical, no guarantees of approval, and always \"I am not a lawyer.\"",[61,82,83,76,86,89,90,93,94,97],{},[23,84,85],{},"The product.",[23,87,88],{},"Vue"," chat interface with streaming replies and visible status states, on a ",[23,91,92],{},"Django"," API with JWT auth, anonymous conversations, and rate limiting. Containerized with Docker, provisioned with ",[23,95,96],{},"Terraform",".",[61,99,100,103],{},[23,101,102],{},"The public directory."," A searchable directory of nonprofits, clinics, and pro-bono organizations, seeded from cleaned public lists, so the answer to \"now what?\" is a phone number.",[50,105],{"caption":106,"src":107},"Status states stream over Server-Sent Events while the agent decides whether it needs to search.","\u002Fimages\u002Fraul\u002Fchat-thinking.png",[50,109],{"caption":110,"src":111},"A grounded answer: the agent searched the USCIS corpus, then wrote the steps and forms from what it found.","\u002Fimages\u002Fraul\u002Fchat-answer.png",[50,113],{"caption":114,"src":115},"The public directory: every conversation can end with a real organization to call.","\u002Fimages\u002Fraul\u002Flegal-network.png",[14,117,119],{"id":118},"building-for-trust","Building for trust",[19,121,122,123,126],{},"An immigration assistant that hallucinates is worse than useless: it is harmful. So the design leans hard on ",[23,124,125],{},"grounding",": retrieve first, cite the source, and prefer \"here is where to look\" over a confident wrong answer. The tool results are typed, the prompt fences the scope, and the corpus is only official text.",[14,128,130],{"id":129},"the-enterprise-build","The enterprise build",[19,132,133],{},"Because I was building a legal SaaS, I built it the way a company would.",[135,136],"raul-infra-enterprise",{},[19,138,139,140,143],{},"Everything in that diagram is real Terraform in the repo: a VPC with private subnets and a NAT gateway, Aurora Serverless Postgres, ElastiCache Redis, SQS as the Celery broker, an always-on Fargate worker for chat jobs, a second Fargate task for the monthly scrape, App Runner for the API, CloudFront with WAF managed rules in front of the SPA, Glue for the ingestion job, Secrets Manager, and GitHub Actions deploying through OIDC into ECR. It was a good stack. It was also ",[23,141,142],{},"$100 to $120 a month with zero users",", and about $75 of that was the NAT gateway and Aurora's 0.5-ACU floor, two services that bill for existing.",[14,145,147],{"id":146},"the-road-bump","The road bump",[19,149,150],{},"The legal SaaS route stalled for three reasons, and none of them were technical.",[19,152,153,156],{},[23,154,155],{},"Trust in AI wasn't there yet."," In 2025 the organizations I wanted as customers were rightly cautious about putting an AI between them and a client whose immigration status was on the line. \"Grounded in USCIS data\" is a strong engineering answer; it is not yet a strong answer for a legal director.",[19,158,159,162],{},[23,160,161],{},"The regulatory bar is high."," Anything that looks like case-specific advice brushes against the unauthorized practice of law, and the data involved is some of the most sensitive a person has. Doing that properly means entity structure, counsel, compliance, and insurance before the first paying customer.",[19,164,165,168],{},[23,166,167],{},"It was far more than I wanted to take on alone."," I was paying for an enterprise stack nobody used while looking at a wall of legal, financial, and technical hurdles for one person. So I tore the stack down.",[14,170,172],{"id":171},"the-pivot-an-open-source-public-good","The pivot: an open-source public good",[19,174,175],{},"Tearing it down didn't sit right either. The project was too far along, with too much genuinely useful work in it, to let nobody use it. So the question changed from \"how do I sell this\" to \"how do I make this free, cheap enough to run out of my own pocket, and something other people can build on.\"",[19,177,178,179,182],{},"The insight that reframed it: ",[23,180,181],{},"the code is not the valuable part."," A RAG chatbot is a commodity now. The valuable, hard, unglamorous part is a curated, cited, current corpus of immigration knowledge and a directory of real help, per country. That is exactly the kind of work a community does better than one engineer, and it is the part lawyers, paralegals, law students, and people who have been through the process can contribute to without ever opening the application code.",[19,184,185,186,189,190,193],{},"So the project is becoming ",[23,187,188],{},"immigration-ai",", licensed ",[23,191,192],{},"AGPL-3.0"," so anyone who runs a modified hosted version has to share it back. The heart of the repo is a folder per country:",[58,195,196,202,208,214],{},[61,197,198,201],{},[23,199,200],{},"Knowledge docs"," in Markdown with frontmatter: how a process, category, form, or fee works, in plain language, with a source URL.",[61,203,204,207],{},[23,205,206],{},"Resource lists"," in YAML: legal aid, clinics, accredited nonprofits, with contact details and a source URL.",[61,209,210,213],{},[23,211,212],{},"Rules that keep it trustworthy",", enforced in CI: every entry cites a source; anything marked official must cite a domain that country declares as a government authority; everything carries a last-verified date.",[61,215,216,219],{},[23,217,218],{},"Automation gates format, humans gate truth."," A country maintainer reviews the substance and merges, and the merge ingests the knowledge into that country's own vector namespace.",[19,221,222],{},"Adding Germany means adding files under one new country folder. Nothing else changes.",[14,224,226],{"id":225},"cheap-enough-to-just-run","Cheap enough to just run",[19,228,229],{},"The other half of the pivot was making the thing affordable to keep online, for free, for people who need it, indefinitely.",[231,232],"raul-infra-lean",{},[19,234,235,236,239],{},"The biggest saving was architectural, not a cheaper host. Celery, Redis, SQS, and the always-on worker existed to run one thing: the chat turn. A chat turn is almost entirely waiting on the model and the vector store, so I replaced the whole queue with an ",[23,237,238],{},"async Django view under uvicorn"," that streams the reply over Server-Sent Events. One small process can hold hundreds of in-flight turns, and the frontend went from polling a task endpoint to reading a stream. Three services and a worker became web plus Postgres.",[241,242],"raul-chat-turn",{},[19,244,245,246,249],{},"The model got cheaper too. A provider factory lets the agent run on Anthropic, OpenAI, or Bedrock from one environment variable, and the default is ",[23,247,248],{},"Claude Haiku 4.5"," for both the answer and the search-query summary. At roughly 4k input and 500 output tokens a turn, a turn costs about half a cent to a cent, a whole conversation five to ten cents, and 200 users a month lands around $20 in tokens. Rate limits cap the downside. Hosting is one small machine at $5 to $15 a month, and the vector index fits Pinecone's free tier. A year of serving a couple hundred people a month is about $600 in credits, small enough that I can carry it myself.",[14,251,253],{"id":252},"whats-next","What's next",[58,255,256,259,262],{},[61,257,258],{},"Publish the public repo from clean history, with the contribution guide, the validator, and the US as the worked example.",[61,260,261],{},"Now that the lean stack is live, put it in front of the organizations I talked to at the start and fold their feedback back in.",[61,263,264],{},"Recruit country maintainers from legal-aid clinics and diaspora communities, and add the second country.",[14,266,268],{"id":267},"what-i-learned","What I learned",[19,270,271],{},"I built the company before I built the community. The product was never the bottleneck: the agent, the pipeline, the infrastructure, all of it worked. What stalled was trust and distribution, and those are not problems a better Terraform module solves. Open source turns the legal, financial, and technical hurdles that were a wall for one person into shared work, and it makes the actual asset, a trustworthy corpus of immigration knowledge, something that can outlive any one deployment. The model is the easy part. The value is in the grounding, the data, and the people willing to keep it true.",{"title":273,"searchDepth":274,"depth":274,"links":275},"",2,[276,277,278,279,280,281,282,283,284,285],{"id":16,"depth":274,"text":17},{"id":29,"depth":274,"text":30},{"id":47,"depth":274,"text":48},{"id":118,"depth":274,"text":119},{"id":129,"depth":274,"text":130},{"id":146,"depth":274,"text":147},{"id":171,"depth":274,"text":172},{"id":225,"depth":274,"text":226},{"id":252,"depth":274,"text":253},{"id":267,"depth":274,"text":268},"md","https:\u002F\u002Fapp.visanav.org",{},[290,293,296],{"label":291,"value":292},"Idle hosting per month, before and after","$100 → ~$5",{"label":294,"value":295},"USCIS chunks in the index","6,600+",{"label":297,"value":192},"License for the open-source version",true,3,"\u002Fcase-studies\u002Fproject-raul","Solo, product, full-stack + AI",{"title":5,"description":273},"case-studies\u002Fproject-raul","A free public service for immigrants: plain-language answers grounded in official USCIS data, plus a public directory of resources for real help. Built first as a legal-tech SaaS on a full AWS stack, then pivoted into an open-source public good with community-curated country data, cheap enough to run for free.",[79,306,69,92,88,96,307],"Claude","AWS","2025–26","8N8uuySGnsLVIRPIJV3rbtj4dccaCgxtecE5RSTG06U",1792537541226]