<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Crime Brasil</title>
    <description>The latest articles on DEV Community by Crime Brasil (@crime_brasil).</description>
    <link>https://dev.to/crime_brasil</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3893007%2F1e92bba0-f99c-4daa-b9b6-7cfc95d198a3.jpg</url>
      <title>DEV Community: Crime Brasil</title>
      <link>https://dev.to/crime_brasil</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/crime_brasil"/>
    <language>en</language>
    <item>
      <title>Querying 3M+ Brazil crime records with a free public REST API</title>
      <dc:creator>Crime Brasil</dc:creator>
      <pubDate>Thu, 23 Apr 2026 23:50:28 +0000</pubDate>
      <link>https://dev.to/crime_brasil/querying-3m-brazil-crime-records-with-a-free-public-rest-api-47i3</link>
      <guid>https://dev.to/crime_brasil/querying-3m-brazil-crime-records-with-a-free-public-rest-api-47i3</guid>
      <description>&lt;p&gt;Brazil has one of the most complex crime landscapes in Latin America — but getting clean, queryable data has historically been a nightmare of PDFs, broken government portals, and inconsistent formats.&lt;/p&gt;

&lt;p&gt;We built &lt;a href="https://crimebrasil.com.br" rel="noopener noreferrer"&gt;Crime Brasil&lt;/a&gt; to fix that. It's a free platform with 3M+ geocoded crime records from RS, RJ and MG, exposed via a public REST API.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;3M+ individual crime records&lt;/strong&gt; from Rio Grande do Sul (bairro-level granularity)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Municipality-level aggregates&lt;/strong&gt; for Rio de Janeiro and Minas Gerais&lt;/li&gt;
&lt;li&gt;Data from 2019–2026, updated monthly from official SSP sources&lt;/li&gt;
&lt;li&gt;Rates per 100,000 inhabitants for fair regional comparison&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick API examples
&lt;/h2&gt;

&lt;p&gt;Get state-level totals for Rio Grande do Sul:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET https://crimebrasil.com.br/api/heatmap/states?selected_states=RS
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get municipality heatmap data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET https://crimebrasil.com.br/api/heatmap/municipios?selected_states=RJ&amp;amp;ano=2024
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Search for a location:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET https://crimebrasil.com.br/api/search?q=Porto+Alegre
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get detailed stats for a specific location:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET https://crimebrasil.com.br/api/location-stats?state=RS&amp;amp;municipio=PORTO+ALEGRE&amp;amp;bairro=CENTRO+HISTORICO&amp;amp;ultimos_meses=12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Python example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;

&lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://crimebrasil.com.br/api&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# Get top municipalities by crime rate in RJ
&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/heatmap/municipios&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;selected_states&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RJ&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ano&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rate_mode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;top10&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;weight&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)[:&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;top10&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;weight&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; per 100K&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Open data, open source
&lt;/h2&gt;

&lt;p&gt;All source data comes from official Brazilian state security secretariats (SSP/RS, ISP/RJ, SEJUSP/MG) under open data laws. The platform itself is also open — explore it at &lt;strong&gt;&lt;a href="https://crimebrasil.com.br" rel="noopener noreferrer"&gt;https://crimebrasil.com.br&lt;/a&gt;&lt;/strong&gt; or check our datasets on Kaggle, Zenodo, and HuggingFace.&lt;/p&gt;

&lt;p&gt;Happy to answer questions about the data or methodology in the comments.&lt;/p&gt;

</description>
      <category>opendata</category>
      <category>python</category>
      <category>datascience</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>3 million geocoded crime records from Brazil — free API and datasets</title>
      <dc:creator>Crime Brasil</dc:creator>
      <pubDate>Thu, 23 Apr 2026 22:47:45 +0000</pubDate>
      <link>https://dev.to/crime_brasil/3-million-geocoded-crime-records-from-brazil-free-api-and-datasets-33fc</link>
      <guid>https://dev.to/crime_brasil/3-million-geocoded-crime-records-from-brazil-free-api-and-datasets-33fc</guid>
      <description>&lt;p&gt;We've been quietly building &lt;a href="https://crimebrasil.com.br" rel="noopener noreferrer"&gt;Crime Brasil&lt;/a&gt; — an open-data platform covering violent crime across Brazil. Here's what's in it and how to use it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the data covers
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rio Grande do Sul&lt;/strong&gt;: 2.99 million occurrences (2022–2025), 497 municipalities, geocoded to neighborhood level&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minas Gerais&lt;/strong&gt;: 965K violent-crime records (2019–2026), 853 municipalities&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rio de Janeiro&lt;/strong&gt;: 37K ISP/CISP records&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PRF DATATRAN&lt;/strong&gt;: ~500K federal road accidents nationally (2020–2026)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DATASUS SINAN&lt;/strong&gt;: interpersonal-violence records nationally (2009–2024)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All data comes from state Secretariats of Public Security (SSP-RS, SSP-MG, ISP-RJ) and federal sources. License: CC BY 4.0.&lt;/p&gt;

&lt;h2&gt;
  
  
  The API
&lt;/h2&gt;

&lt;p&gt;Every city/state has its own endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Crime counts by month for Porto Alegre&lt;/span&gt;
curl &lt;span class="s1"&gt;'https://crimebrasil.com.br/api/city/rs/porto-alegre?type=monthly'&lt;/span&gt;

&lt;span class="c"&gt;# Top 10 neighborhoods by homicide, last 12 months&lt;/span&gt;
curl &lt;span class="s1"&gt;'https://crimebrasil.com.br/api/city/rs/porto-alegre/bairros?crime=homicidio'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response is plain JSON — crime counts aggregated by type, period, and neighborhood.&lt;/p&gt;

&lt;h2&gt;
  
  
  Downloading datasets
&lt;/h2&gt;

&lt;p&gt;Full datasets are on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://zenodo.org/records/19712036" rel="noopener noreferrer"&gt;Zenodo&lt;/a&gt; — DOI &lt;code&gt;10.5281/zenodo.19712036&lt;/code&gt; (RS, 3M rows)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://zenodo.org/records/19711971" rel="noopener noreferrer"&gt;Zenodo&lt;/a&gt; — DOI &lt;code&gt;10.5281/zenodo.19711971&lt;/code&gt; (MG, 965K rows)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.kaggle.com/datasets/valdovaldo/minas-gerais-violent-crime-2019-2026" rel="noopener noreferrer"&gt;Kaggle&lt;/a&gt; — MG dataset&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://huggingface.co/datasets/crimebrasil/rio-grande-do-sul-crime-2022-2025" rel="noopener noreferrer"&gt;HuggingFace&lt;/a&gt; — RS dataset&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick Python example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;

&lt;span class="c1"&gt;# Load RS dataset from Zenodo
&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://zenodo.org/records/19712036/files/crime-brasil-rs-2022-2025.csv.gz&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;compression&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;gzip&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Homicides per year in Porto Alegre
&lt;/span&gt;&lt;span class="n"&gt;homicidios&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;municipio_fato&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;PORTO ALEGRE&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tipo_enquadramento&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;HOMICIDIO&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;year_month&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;homicidios&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Coverage and methodology
&lt;/h2&gt;

&lt;p&gt;We cover &lt;strong&gt;99.4% of the Brazilian population&lt;/strong&gt; across the states we have data for. The geocoding pipeline assigns lat/lon using a four-pass hierarchy:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Exact address match&lt;/li&gt;
&lt;li&gt;Neighborhood centroid&lt;/li&gt;
&lt;li&gt;Municipality centroid&lt;/li&gt;
&lt;li&gt;State centroid (fallback)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;99.99% of RS records land at pass 1 or 2.&lt;/p&gt;

&lt;h2&gt;
  
  
  LAI requests in progress
&lt;/h2&gt;

&lt;p&gt;We've filed Freedom of Information (LAI) requests in 14 states: AL, AM, BA, ES, MA, MG, PR, RJ, RN, RO, RR, RS, SC, TO. As responses arrive, we publish them.&lt;/p&gt;




&lt;p&gt;The platform is at &lt;a href="https://crimebrasil.com.br" rel="noopener noreferrer"&gt;crimebrasil.com.br&lt;/a&gt;. Press kit and methodology at &lt;a href="https://crimebrasil.com.br/imprensa" rel="noopener noreferrer"&gt;crimebrasil.com.br/imprensa&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>opendata</category>
      <category>python</category>
      <category>braziliandevs</category>
      <category>datascience</category>
    </item>
    <item>
      <title>How We Built an Open Crime Data Platform for Brazil (3 Million Records)</title>
      <dc:creator>Crime Brasil</dc:creator>
      <pubDate>Thu, 23 Apr 2026 22:42:20 +0000</pubDate>
      <link>https://dev.to/crime_brasil/how-we-built-an-open-crime-data-platform-for-brazil-3-million-records-36l2</link>
      <guid>https://dev.to/crime_brasil/how-we-built-an-open-crime-data-platform-for-brazil-3-million-records-36l2</guid>
      <description>&lt;h1&gt;
  
  
  How We Built an Open Crime Data Platform for Brazil (3 Million Records)
&lt;/h1&gt;

&lt;p&gt;Brazil has one of the world's highest homicide rates — over 47,000 murders per year. Yet accessing crime statistics is surprisingly hard. Data is fragmented across 27 state secretariats, each with different formats, different crime taxonomies, and wildly inconsistent update schedules.&lt;/p&gt;

&lt;p&gt;We built &lt;a href="https://crimebrasil.com.br/" rel="noopener noreferrer"&gt;Crime Brasil&lt;/a&gt; to fix that.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Crime Brasil&lt;/strong&gt; is an interactive crime map covering Rio Grande do Sul, Rio de Janeiro, and Minas Gerais — with bairro (neighborhood) level granularity for RS, and municipality-level for the others.&lt;/p&gt;

&lt;p&gt;Key features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;3+ million individual crime records for RS (2022–2026)&lt;/li&gt;
&lt;li&gt;Choropleth maps at state → city → neighborhood drill-down&lt;/li&gt;
&lt;li&gt;Per-100K-inhabitants rate normalization (so you can actually compare)&lt;/li&gt;
&lt;li&gt;Crime type filters (homicide, robbery, drug offenses, etc.)&lt;/li&gt;
&lt;li&gt;Time range selector (last 6/12/24/36 months or full history)&lt;/li&gt;
&lt;li&gt;API access — all data available via REST endpoints&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Backend&lt;/strong&gt;: FastAPI + SQLAlchemy + SQLite (yeah, SQLite — handles 3M rows fine with proper indexes)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt;: Next.js 14 + Leaflet.js + Tailwind CSS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment&lt;/strong&gt;: Docker + zero-downtime atomic alias swap (no Kubernetes needed at this scale)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data pipeline&lt;/strong&gt;: Python ETL from SSP/RS ZIP files, ISP/RJ CSV, SEJUSP/MG CSV&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The hardest part: bairro name normalization
&lt;/h2&gt;

&lt;p&gt;The same neighborhood appears as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CENTRO HISTÓRICO&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CENTRO HISTORICO&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;centro historico&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CENTRO-HISTÓRICO&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CTR HIST&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Across police records, census data, and map boundaries.&lt;/p&gt;

&lt;p&gt;We built a phonetic normalization pipeline using custom Brazilian Portuguese rules — strips accents, normalizes common abbreviations (RUA → R, AVENIDA → AV), handles compound names. This alone took about 3 weeks of iteration against real data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why SQLite, not PostgreSQL
&lt;/h2&gt;

&lt;p&gt;Conventional wisdom says "use Postgres for anything serious." But SQLite with covering indexes on &lt;code&gt;(state, year_month, tipo_enquadramento)&lt;/code&gt; serves our heatmap queries in &amp;lt;100ms at 3M rows. The database is ~800MB. It fits on any $5 VPS. Zero connection pooling headaches. Zero migrations for most schema changes.&lt;/p&gt;

&lt;p&gt;We do have one performance rule: &lt;strong&gt;always use &lt;code&gt;BETWEEN&lt;/code&gt; for year filters, never &lt;code&gt;LIKE&lt;/code&gt;&lt;/strong&gt;. SQLite uses the covering index for &lt;code&gt;BETWEEN '{ano}-01' AND '{ano}-12'&lt;/code&gt; but not for &lt;code&gt;LIKE '{ano}-%'&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open data
&lt;/h2&gt;

&lt;p&gt;All datasets are published:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.kaggle.com/datasets/valdovaldo/minas-gerais-violent-crime-2019-2026" rel="noopener noreferrer"&gt;Kaggle: MG Violent Crime 2019–2026&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://zenodo.org/records/19712036" rel="noopener noreferrer"&gt;Zenodo: RS Full Dataset&lt;/a&gt; — DOI 10.5281/zenodo.19712036&lt;/li&gt;
&lt;li&gt;&lt;a href="https://huggingface.co/datasets/crimebrasil/rio-grande-do-sul-crime-2022-2025" rel="noopener noreferrer"&gt;HuggingFace: RS 2022–2026&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;São Paulo coverage (aggregated municipal-level data already being processed)&lt;/li&gt;
&lt;li&gt;API authentication for high-volume consumers&lt;/li&gt;
&lt;li&gt;Historical comparison charts per location&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The entire REST API is public: &lt;code&gt;https://crimebrasil.com.br/api/heatmap/municipios&lt;/code&gt; returns municipality-level heatmap data, &lt;code&gt;https://crimebrasil.com.br/api/location-stats&lt;/code&gt; returns detailed stats per location.&lt;/p&gt;

&lt;p&gt;Happy to answer questions about the data pipeline, the normalization approach, or the zero-downtime deploy architecture.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Crime Brasil: &lt;a href="https://crimebrasil.com.br" rel="noopener noreferrer"&gt;https://crimebrasil.com.br&lt;/a&gt; — open crime data for Brazil&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>opendata</category>
      <category>fastapi</category>
      <category>brazil</category>
    </item>
    <item>
      <title>How we built Crime Brasil: an open-data crime map for 214 million Brazilians</title>
      <dc:creator>Crime Brasil</dc:creator>
      <pubDate>Thu, 23 Apr 2026 22:19:37 +0000</pubDate>
      <link>https://dev.to/crime_brasil/how-we-built-crime-brasil-an-open-data-crime-map-for-214-million-brazilians-gfl</link>
      <guid>https://dev.to/crime_brasil/how-we-built-crime-brasil-an-open-data-crime-map-for-214-million-brazilians-gfl</guid>
      <description>&lt;p&gt;Brazil has one of the highest homicide rates in the world — yet finding reliable, granular crime data at the neighbourhood level has historically been nearly impossible for ordinary citizens, journalists and researchers.&lt;/p&gt;

&lt;p&gt;We built &lt;a href="https://crimebrasil.com.br" rel="noopener noreferrer"&gt;Crime Brasil&lt;/a&gt; to fix that.&lt;/p&gt;

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

&lt;p&gt;Crime Brasil is a free, open-data interactive map that lets anyone explore violence and criminality statistics across Brazil — broken down by state, city and neighbourhood. No paywall. No signup required.&lt;/p&gt;

&lt;p&gt;Current coverage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rio Grande do Sul&lt;/strong&gt; — neighbourhood-level (bairro) data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rio de Janeiro&lt;/strong&gt; — city-level breakdown&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minas Gerais&lt;/strong&gt; — city-level breakdown&lt;/li&gt;
&lt;li&gt;3 million+ crime records from official government registers&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js 15&lt;/strong&gt; (App Router) + TypeScript&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PostgreSQL&lt;/strong&gt; with PostGIS for geospatial queries&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deck.gl + MapLibre&lt;/strong&gt; for the map rendering&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloudflare&lt;/strong&gt; CDN and WAF&lt;/li&gt;
&lt;li&gt;REST API with per-100k-inhabitants normalisation built in&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Open data, all the way
&lt;/h2&gt;

&lt;p&gt;All source data is published as open datasets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.kaggle.com/datasets/valdovaldo/minas-gerais-violent-crime-2019-2026" rel="noopener noreferrer"&gt;Kaggle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://zenodo.org/records/19711971" rel="noopener noreferrer"&gt;Zenodo DOI 10.5281/zenodo.19711971&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://huggingface.co/datasets/valdovaldo1500/crime-brasil-rs-2022-2026" rel="noopener noreferrer"&gt;HuggingFace&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://crimebrasil.com.br" rel="noopener noreferrer"&gt;crimebrasil.com.br&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're working on public safety research, data journalism, or civic tech in Brazil — we'd love to hear from you.&lt;/p&gt;

</description>
      <category>opendata</category>
      <category>showdev</category>
      <category>nextjs</category>
      <category>dataviz</category>
    </item>
    <item>
      <title>4,524 commits in 7 weeks: what I learned shipping a real product with Claude Code</title>
      <dc:creator>Crime Brasil</dc:creator>
      <pubDate>Thu, 23 Apr 2026 19:23:29 +0000</pubDate>
      <link>https://dev.to/crime_brasil/4524-commits-in-7-weeks-what-i-learned-shipping-a-real-product-with-claude-code-1kc9</link>
      <guid>https://dev.to/crime_brasil/4524-commits-in-7-weeks-what-i-learned-shipping-a-real-product-with-claude-code-1kc9</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;4,524 git commits in 7 weeks (~92/day)&lt;/li&gt;
&lt;li&gt;~42,000 lines of code across Python backend + Next.js frontend&lt;/li&gt;
&lt;li&gt;~3M records ingested, 79,024 neighborhoods geocoded, zero-downtime production deploys, E2E smoke tests, APScheduler jobs, SEO snapshot system&lt;/li&gt;
&lt;li&gt;Total spend: ~$500 (Claude Max $200 × 2 months + Hetzner ~$30 × 2 months)&lt;/li&gt;
&lt;li&gt;Built alone. Shipped.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm not going to tell you Claude Code is magic. It isn't. But if you treat it like a very fast, very literal colleague who forgets things between sessions, you can ship more than you'd think. Here's the workflow that worked for me.&lt;/p&gt;

&lt;p&gt;The product is &lt;a href="https://crimebrasil.com.br" rel="noopener noreferrer"&gt;Crime Brasil&lt;/a&gt; — an open-data platform for Brazilian crime statistics. Doesn't matter for this post. What matters is the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Workflow that actually worked
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Plan mode before anything non-trivial
&lt;/h3&gt;

&lt;p&gt;Before any change touching &amp;gt;3 files or introducing new abstractions, I forced a &lt;code&gt;/plan&lt;/code&gt; pass. No code, just a tree of what changes where and why.&lt;/p&gt;

&lt;p&gt;This cut the "Claude confidently wrote 400 lines of the wrong thing" bug in half. The other half came from me being sloppy about what I was actually asking for.&lt;/p&gt;

&lt;p&gt;Pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Tell Claude the goal
2. Ask for a plan (no code)
3. Push back on anything that feels wrong — usually scope creep
4. When the plan feels right, say "implement"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Boring. Works.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Sub-agents for parallel anything
&lt;/h3&gt;

&lt;p&gt;Independent work ran in parallel sub-agents. Research + implementation + QA could all run concurrently instead of me waiting for each to finish.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;research&lt;/code&gt; agent — "understand how X works, come back with a map"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;implement&lt;/code&gt; agent — "apply the diff described"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;qa&lt;/code&gt; agent — "verify the fix, run the regression tests"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;review&lt;/code&gt; agent — "is this safe to merge"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'd fire three of these in parallel and get stitched output in a third the wall time.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Session scratchpad as an anti-compaction tool
&lt;/h3&gt;

&lt;p&gt;Claude Code compacts its context when conversations get long. After compaction you can lose crucial decisions from earlier.&lt;/p&gt;

&lt;p&gt;Fix: every session writes to a scratchpad file (&lt;code&gt;~/claude-sessions/session_&amp;lt;topic&amp;gt;.md&lt;/code&gt;) with timestamped entries. Key decisions, user preferences, things we tried that failed. Before spawning any sub-agent I inject the relevant scratchpad entries into the prompt.&lt;/p&gt;

&lt;p&gt;This alone probably saved a dozen hours of "wait, why did we decide not to do that again?"&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Memory system for permanent preferences
&lt;/h3&gt;

&lt;p&gt;Claude Code has a memory system that persists across conversations. I ended up writing ~80 memory files over 7 weeks, categorized:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;user&lt;/strong&gt; — who I am, what I work on, what I already know&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;feedback&lt;/strong&gt; — rules I've enforced ("never push to main directly", "always chrome-verify fixes, not just curl")&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;project&lt;/strong&gt; — state of ongoing work&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;reference&lt;/strong&gt; — where external resources live (dashboards, tokens, API docs)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every time I corrected Claude on the same thing twice, I saved a memory rule. Examples from my actual file:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Never slow bot renders for SEO&lt;/code&gt; — fixed a bad server-side bot-detection idea&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;No lossy analytics filters&lt;/code&gt; — never exclude geographic data to "clean up" analytics&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Wait-loop pattern&lt;/code&gt; — use &lt;code&gt;while pgrep&lt;/code&gt; not &lt;code&gt;until ... &amp;amp;&amp;amp; ! kill -0&lt;/code&gt; (the latter busy-waits)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;No arbitrary safeguards&lt;/code&gt; — don't add population floors to hide bad data, fix the data&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Never substitute solutions&lt;/code&gt; — if user asks to fix X, fix X, don't silently solve by changing Y&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last one came up repeatedly. Claude loves to pivot to an "easier" problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Hooks for guardrails
&lt;/h3&gt;

&lt;p&gt;Some rules can't be enforced by just asking nicely. For those, I used Claude Code's hook system to block certain actions entirely.&lt;/p&gt;

&lt;p&gt;Examples I ended up needing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Block any &lt;code&gt;git commit --no-verify&lt;/code&gt; (never bypass pre-commit hooks)&lt;/li&gt;
&lt;li&gt;Block &lt;code&gt;rm&lt;/code&gt; on data files without explicit confirmation&lt;/li&gt;
&lt;li&gt;Warn on any &lt;code&gt;git push origin main&lt;/code&gt; — all changes must go through dev branch + staging first&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hooks turned bad defaults into impossible-by-default. Worth the setup time.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Verification before declaring "done"
&lt;/h3&gt;

&lt;p&gt;Claude loves to say "fixed!" based on an API test passing. That's not the same as the feature actually working in a browser.&lt;/p&gt;

&lt;p&gt;I ended up with a rule: &lt;strong&gt;every UI-touching change gets Chrome-verified before being marked complete.&lt;/strong&gt; A Playwright script clicks through the real flow and screenshots the result. If the screenshot looks wrong, it's not done.&lt;/p&gt;

&lt;p&gt;Memory file: &lt;em&gt;"NEVER report a fix as done without Chrome visual verification."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Before this rule: "fixed!" → deploy → user finds it broken → revert. After: "fixed, verified on &lt;code&gt;/cidade/rs/porto-alegre&lt;/code&gt;, panel shows 509K crimes, screenshot attached."&lt;/p&gt;

&lt;h2&gt;
  
  
  Specific bugs Claude caused
&lt;/h2&gt;

&lt;p&gt;Honest list. These are patterns; I saw each of them multiple times.&lt;/p&gt;

&lt;h3&gt;
  
  
  "Let me also refactor while I'm here"
&lt;/h3&gt;

&lt;p&gt;Ask for a small bug fix, get back 400 lines of unrelated cleanup. Sometimes broke unrelated features.&lt;/p&gt;

&lt;p&gt;Memory rule: &lt;em&gt;"Don't add features, refactor, or introduce abstractions beyond what the task requires. Three similar lines is better than a premature abstraction."&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Inventing API endpoints
&lt;/h3&gt;

&lt;p&gt;Asked Claude to "call the API to get X data." It wrote code calling &lt;code&gt;/api/thing&lt;/code&gt; that didn't exist. Tests failed. When pushed: "oh right, that endpoint doesn't exist. Let me write it first."&lt;/p&gt;

&lt;p&gt;Fix: when consuming an API, I started forcing it to read the actual source files first. &lt;code&gt;Read src/api/routes.py&lt;/code&gt;, then write the client. Slower, zero hallucinations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Silent feature deletion
&lt;/h3&gt;

&lt;p&gt;Twice Claude "fixed" a bug by removing the buggy feature. Asked to fix a map polygon render issue, got back code that just disabled polygons entirely. Clean green tests. Feature gone.&lt;/p&gt;

&lt;p&gt;Memory rule: &lt;em&gt;"NEVER remove features unless user explicitly says to. 'bugado' means fix, not remove."&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Overclaiming completion
&lt;/h3&gt;

&lt;p&gt;The biggest pattern. "Done!" → I check → 2 of 4 items done, 2 untouched. Claude was genuinely under the impression it had finished.&lt;/p&gt;

&lt;p&gt;Fix: I stopped taking "done" at face value. Every "done" got a follow-up "walk me through what you changed file-by-file, and show me the diff for each." Usually the second response corrected the first.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Claude can't do (yet)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Architect from scratch.&lt;/strong&gt; Given a vague brief like "build a data platform for X," Claude produces a generic Django blog. Needs strong direction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Know your domain.&lt;/strong&gt; Took months to teach it Brazilian bairro-name quirks — there's no substitute for local knowledge, and Claude will confidently generalize from Stack Overflow examples that don't apply.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remember across sessions without help.&lt;/strong&gt; Compaction + context limits mean every session is partial amnesia. The scratchpad + memory system is the only thing that saved me.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decide what not to build.&lt;/strong&gt; Claude will happily implement bad feature ideas. Saying "no" is still human work.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cost breakdown (~$500)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Claude Max subscription ($200/mo × 2)&lt;/td&gt;
&lt;td&gt;$400&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hetzner dedicated server ($30/mo × 2)&lt;/td&gt;
&lt;td&gt;$60&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resend email API (free tier)&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloudflare (free tier)&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;td&gt;$12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~$472&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For reference: a single senior contract dev week at market rates is $4-6K. I shipped this in 7 weeks of evenings + weekends for ~$472 in tools + hosting.&lt;/p&gt;

&lt;p&gt;The caveat: this is a solo project. I didn't have to coordinate with anyone, and nobody needed to review my work. That's a rare situation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lines of code
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Lines&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Python backend (FastAPI + scrapers + ingest + APIs)&lt;/td&gt;
&lt;td&gt;23,559&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TypeScript frontend (Next.js + Leaflet)&lt;/td&gt;
&lt;td&gt;18,762&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MDX content (articles)&lt;/td&gt;
&lt;td&gt;6,165&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;48,486&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;92 commits/day sounds insane. In practice most commits are small and auto-checkpointed. Real "unit of work" commits are maybe 20-30/day.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I wouldn't skip if doing it again
&lt;/h2&gt;

&lt;p&gt;In priority order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Scratchpad files.&lt;/strong&gt; Save at least 10x their cost in "wait, what did we decide?" time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The &lt;code&gt;/plan&lt;/code&gt; discipline.&lt;/strong&gt; Every non-trivial change gets a plan first. Boring, works.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory rules for every recurring correction.&lt;/strong&gt; Rule of twos: if you correct Claude on the same thing twice, write it down.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chrome-verify before declaring done.&lt;/strong&gt; API tests don't cover UI. UI bugs always happen on the last Friday.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hooks for dangerous defaults.&lt;/strong&gt; Anything you really don't want — make it impossible by default, not just discouraged.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What I'd do differently
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Start the memory system earlier.&lt;/strong&gt; I was 2 weeks in before I realized it existed. Week 1 was slower than it needed to be.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spin up sub-agents sooner.&lt;/strong&gt; For a while I was doing everything sequentially in the main agent. Parallel work is a huge speed-up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write the CLAUDE.md from day 1.&lt;/strong&gt; A per-project &lt;code&gt;CLAUDE.md&lt;/code&gt; explaining architecture and conventions prevents a lot of drift.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;Crime Brasil is live at &lt;a href="https://crimebrasil.com.br" rel="noopener noreferrer"&gt;crimebrasil.com.br&lt;/a&gt;. It serves ~3M records across 497 municipalities, gets Google traffic for specific city and neighborhood queries, and was built almost entirely in a Claude Code harness.&lt;/p&gt;

&lt;p&gt;I'm happy to answer questions about the workflow. The answer to "can AI replace developers" is still no, but "can a developer with AI replace two developers without AI" is absolutely yes, and that's interesting enough.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Follow along on X at &lt;a href="https://x.com/Crime_Brasil" rel="noopener noreferrer"&gt;@Crime_Brasil&lt;/a&gt; if you want to see what ships next.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>ai</category>
      <category>python</category>
      <category>nextjs</category>
    </item>
  </channel>
</rss>
